Line data Source code
1 : /**
2 : Copyright (c) 2016-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_CORE_SPCORE_H_
25 : #define STAPPLER_CORE_SPCORE_H_
26 :
27 : /* Stappler Common library
28 : *
29 : * this file should be included before any other files to enable
30 : * precompiled-header compilation optimization
31 : * (if no other specific precompiled header needed)
32 : *
33 : * Some header-only STL features (like std::numeric_limits) will be
34 : * used in both cases
35 : */
36 :
37 : #ifdef __MINGW32__
38 : #define _POSIX_THREAD_SAFE_FUNCTIONS 1
39 : #endif
40 :
41 : // IDE-specific definition
42 : #if __CDT_PARSER__ // Eclipse CDT parser
43 :
44 : // enable all modules
45 :
46 : #define MODULE_STAPPLER_DATA 1
47 : #define MODULE_STAPPLER_FILESYSTEM 1
48 : #define MODULE_STAPPLER_BROTLI_LIB 1
49 : #define MODULE_STAPPLER_THREADS 1
50 : #define MODULE_STAPPLER_IDN 1
51 : #define MODULE_STAPPLER_CRYPTO 1
52 : #define MODULE_STAPPLER_BITMAP 1
53 : #define MODULE_STAPPLER_THREADS 1
54 : #define MODULE_STAPPLER_NETWORK 1
55 : #define MODULE_STAPPLER_GEOM 1
56 : #define MODULE_STAPPLER_TESS 1
57 : #define MODULE_STAPPLER_VG 1
58 : #define MODULE_STAPPLER_SEARCH 1
59 : #define MODULE_STAPPLER_SQL 1
60 : #define MODULE_STAPPLER_DB 1
61 : #define MODULE_STAPPLER_ZIP 1
62 :
63 : #define MODULE_STAPPLER_WEBSERVER_WEBSERVER 1
64 : #define MODULE_STAPPLER_WEBSERVER_UNIX 1
65 :
66 : #define MODULE_XENOLITH_CORE 1
67 : #define MODULE_XENOLITH_APPLICATION 1
68 : #define MODULE_XENOLITH_BACKEND_VK 1
69 : #define MODULE_XENOLITH_BACKEND_VKGUI 1
70 : #define MODULE_XENOLITH_RENDERER_BASIC2D 1
71 : #define MODULE_XENOLITH_RENDERER_MATERIAL2D 1
72 :
73 : #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
74 : //define something for Windows (32-bit and 64-bit, this part is common)
75 : #ifdef _WIN64
76 : #define WINDOWS 1
77 : #ifndef WIN32
78 : #define WIN32 1
79 : #endif
80 : #else
81 : #define WINDOWS 1
82 : #ifndef WIN32
83 : #define WIN32 1
84 : #endif
85 : #endif
86 : #elif __APPLE__
87 : #include <TargetConditionals.h>
88 : #if TARGET_IPHONE_SIMULATOR
89 : #define IOS 1
90 : #elif TARGET_OS_MACCATALYST
91 : #define IOS 1
92 : #elif TARGET_OS_IPHONE
93 : #define IOS 1
94 : #elif TARGET_OS_MAC
95 : #define MACOS 1
96 : #else
97 : # error "Unknown Apple platform"
98 : #endif
99 : #elif __ANDROID__
100 : #define ANDROID 1
101 : #elif __linux__
102 : #define LINUX 1
103 : #else
104 : # error "Unknown compiler"
105 : #endif
106 :
107 : namespace std {
108 :
109 : template <typename T>
110 : using iter_reference_t = typename T::reference;
111 :
112 : }
113 :
114 : #if WIN32
115 : #define __cdecl
116 : #endif
117 :
118 : #endif // __CDT_PARSER__
119 :
120 : #ifndef DEBUG
121 : #ifndef NDEBUG
122 : #define DEBUG 1
123 : #endif
124 : #endif
125 :
126 : #if __LCC__ && __LCC__ <= 127
127 : #define SP_HAVE_THREE_WAY_COMPARISON 0
128 : #elif __cpp_impl_three_way_comparison >= 201711
129 : #define SP_HAVE_THREE_WAY_COMPARISON 1
130 : #else
131 : #define SP_HAVE_THREE_WAY_COMPARISON 0
132 : #endif
133 :
134 :
135 : // Enable default <=> operator if we can
136 : #if SP_HAVE_THREE_WAY_COMPARISON
137 : #define SP_THREE_WAY_COMPARISON_TYPE(Type) auto operator<=>(const Type&) const = default;
138 : #define SP_THREE_WAY_COMPARISON_FRIEND(Type) friend auto operator<=>(const Type&, const Type &) = default;
139 : #define SP_THREE_WAY_COMPARISON_TYPE_CONSTEXPR(Type) constexpr auto operator<=>(const Type &) const = default;
140 : #define SP_THREE_WAY_COMPARISON_FRIEND_CONSTEXPR(Type) friend constexpr auto operator<=>(const Type&, const Type &) = default;
141 : #else
142 : #if __LCC__ && __LCC__ >= 127
143 : #define SP_THREE_WAY_COMPARISON_TYPE(Type) \
144 : bool operator==(const Type&) const = default;\
145 : bool operator!=(const Type&) const = default;\
146 : bool operator>(const Type&) const = default;\
147 : bool operator>=(const Type&) const = default;\
148 : bool operator<=(const Type&) const = default;\
149 : bool operator<(const Type&) const = default;
150 : #define SP_THREE_WAY_COMPARISON_FRIEND(Type) \
151 : friend bool operator==(const Type&, const Type &) = default;\
152 : friend bool operator!=(const Type&, const Type &) = default;\
153 : friend bool operator>(const Type&, const Type &) = default;\
154 : friend bool operator>=(const Type&, const Type &) = default;\
155 : friend bool operator<=(const Type&, const Type &) = default;\
156 : friend bool operator<(const Type&, const Type &) = default;
157 : #define SP_THREE_WAY_COMPARISON_TYPE_CONSTEXPR(Type) \
158 : constexpr bool operator==(const Type&) const = default;\
159 : constexpr bool operator!=(const Type&) const = default;\
160 : constexpr bool operator>(const Type&) const = default;\
161 : constexpr bool operator>=(const Type&) const = default;\
162 : constexpr bool operator<=(const Type&) const = default;\
163 : constexpr bool operator<(const Type&) const = default;
164 : #define SP_THREE_WAY_COMPARISON_FRIEND_CONSTEXPR(Type) \
165 : friend constexpr bool operator==(const Type&, const Type &) = default;\
166 : friend constexpr bool operator!=(const Type&, const Type &) = default;\
167 : friend constexpr bool operator>(const Type&, const Type &) = default;\
168 : friend constexpr bool operator>=(const Type&, const Type &) = default;\
169 : friend constexpr bool operator<=(const Type&, const Type &) = default;\
170 : friend constexpr bool operator<(const Type&, const Type &) = default;
171 : #else
172 : #define SP_THREE_WAY_COMPARISON_TYPE(Type)
173 : #define SP_THREE_WAY_COMPARISON_FRIEND(Type)
174 : #define SP_THREE_WAY_COMPARISON_TYPE_CONSTEXPR(Type)
175 : #define SP_THREE_WAY_COMPARISON_FRIEND_CONSTEXPR(Type)
176 : #endif
177 : #endif
178 :
179 : // we want _Float16 and _Float64
180 : #define __STDC_WANT_IEC_60559_TYPES_EXT__ 1
181 :
182 : // Suppress windows warnings for cross-compilation with clang
183 : #if XWIN
184 : #pragma clang diagnostic push
185 : #pragma clang diagnostic ignored "-Wnonportable-include-path"
186 : #pragma clang diagnostic ignored "-Wignored-attributes"
187 : #pragma clang diagnostic ignored "-Wmicrosoft-include"
188 : #pragma clang diagnostic ignored "-Wignored-pragma-intrinsic"
189 : #pragma clang diagnostic ignored "-Wpragma-pack"
190 : #pragma clang diagnostic ignored "-Wunknown-pragmas"
191 : #pragma clang diagnostic ignored "-Wunused-local-typedef"
192 : #endif
193 :
194 : // Suppress windows MIN/MAX macro
195 : // Actually, windows-specific includes should be only in SPPlatformUnistd.h with proper filters for macro leaking
196 : #if WIN32
197 : #define NOMINMAX 1
198 : #define _USE_MATH_DEFINES 1
199 : #endif
200 :
201 : #ifndef STAPPLER_VERSION_PREFIX
202 : #define STAPPLER_VERSIONIZED
203 : #define STAPPLER_VERSIONIZED_NAMESPACE ::stappler
204 : #else
205 : #define STAPPLER_VERSIONIZED STAPPLER_VERSION_PREFIX::
206 : #define STAPPLER_VERSIONIZED_NAMESPACE ::STAPPLER_VERSION_PREFIX::stappler
207 : #endif
208 :
209 : #include <type_traits>
210 : #include <iterator>
211 : #include <limits>
212 : #include <utility>
213 : #include <iterator>
214 : #include <algorithm>
215 : #include <tuple>
216 : #include <cmath>
217 : #include <float.h>
218 : #include <stdlib.h>
219 : #include <stdint.h>
220 : #include <stdarg.h>
221 : #include <stdio.h>
222 : #include <string.h>
223 : #include <assert.h>
224 : #include <limits.h>
225 : #include <stddef.h>
226 :
227 : #include <tuple>
228 : #include <string>
229 : #include <vector>
230 : #include <functional>
231 : #include <sstream>
232 : #include <fstream>
233 : #include <map>
234 : #include <set>
235 : #include <bit>
236 :
237 : #include <istream>
238 : #include <ostream>
239 : #include <array>
240 : #include <iostream>
241 : #include <istream>
242 : #include <ostream>
243 : #include <iomanip>
244 : #include <mutex>
245 : #include <atomic>
246 : #include <deque>
247 : #include <thread>
248 : #include <condition_variable>
249 : #include <initializer_list>
250 : #include <unordered_map>
251 : #include <unordered_set>
252 : #include <bitset>
253 : #include <forward_list>
254 :
255 : #if SP_HAVE_THREE_WAY_COMPARISON
256 : #include <compare>
257 : #endif
258 :
259 : #if XWIN
260 : #pragma clang diagnostic pop
261 : #endif
262 :
263 : // suppress common macro leak
264 : #if WIN32
265 : #undef interface
266 : #endif
267 :
268 : // IDE-specific standart library mods
269 : #if __CDT_PARSER__
270 : #define SPUNUSED __attribute__((unused))
271 : #define SPINLINE
272 :
273 : // Eclipse fails to detect iterator_traits for pointer in new libstdc++
274 : // so, define it manually
275 : #ifdef _LIBCPP_BEGIN_NAMESPACE_STD
276 : _LIBCPP_BEGIN_NAMESPACE_STD
277 : #else
278 : namespace std {
279 : #endif
280 :
281 : template <typename PointerValue>
282 : struct iterator_traits<const PointerValue *> {
283 : using value_type = PointerValue;
284 : using difference_type = ptrdiff_t;
285 : using pointer = const PointerValue *;
286 : using reference = const PointerValue &;
287 : };
288 :
289 : template <typename PointerValue>
290 : struct iterator_traits<PointerValue *> {
291 : using value_type = PointerValue;
292 : using difference_type = ptrdiff_t;
293 : using pointer = PointerValue *;
294 : using reference = PointerValue &;
295 : };
296 :
297 : #ifdef _LIBCPP_END_NAMESPACE_STD
298 : _LIBCPP_END_NAMESPACE_STD
299 : #else
300 : }
301 : #endif
302 :
303 : #else // __CDT_PARSER__
304 : #define SPUNUSED [[maybe_unused]]
305 : #define SPINLINE __attribute__((always_inline))
306 : #endif // __CDT_PARSER__
307 :
308 : // GCC-specific formatting attribute
309 : #if defined(__GNUC__) && (__GNUC__ >= 4)
310 : #define SPPRINTF(formatPos, argPos) __attribute__((__format__(printf, formatPos, argPos)))
311 : #define SP_COVERAGE_TRIVIAL __attribute__ ((no_profile_instrument_function))
312 : #elif defined(__has_attribute)
313 : #if __has_attribute(format)
314 : #define SPPRINTF(formatPos, argPos) __attribute__((__format__(printf, formatPos, argPos)))
315 : #endif // __has_attribute(format)
316 : #define SP_COVERAGE_TRIVIAL
317 : #else
318 : #define SPPRINTF(formatPos, argPos)
319 : #define SP_COVERAGE_TRIVIAL
320 : #endif
321 :
322 : #define SP_EXTERN_C extern "C"
323 :
324 : /*
325 : * User Defined literals
326 : *
327 : * Functions:
328 : * - _hash / _tag - FNV-1 32-bit compile-time hashing
329 : * - _hash64 / _tag64 - FNV-1 64-bit compile-time hashing
330 : * - _len / _length - string literal length
331 : * - _to_rad - convert degrees to radians
332 : * - _GiB / _MiB / _KiB - binary size numbers
333 : * - _c8 / _c16 - convert integer literal to character
334 : */
335 :
336 : #include "SPHash.h"
337 :
338 : namespace STAPPLER_VERSIONIZED stappler {
339 :
340 : using std::forward;
341 : using std::move;
342 : using std::min;
343 : using std::max;
344 :
345 : using nullptr_t = std::nullptr_t;
346 :
347 : namespace numbers {
348 : template<typename T> inline constexpr T pi_v =
349 : std::enable_if_t<std::is_floating_point_v<T>, T>(3.141592653589793238462643383279502884L);
350 :
351 : inline constexpr double pi = pi_v<double>;
352 :
353 : }
354 :
355 : // used for naming/hashing (like "MyTag"_tag)
356 25 : constexpr uint32_t operator"" _hash ( const char* str, size_t len) {
357 25 : return stappler::hash::hash32(str, uint32_t(len));
358 : }
359 1246 : constexpr uint32_t operator"" _tag ( const char* str, size_t len) {
360 1246 : return stappler::hash::hash32(str, uint32_t(len));
361 : }
362 :
363 25 : constexpr uint64_t operator"" _hash64 ( const char* str, size_t len) {
364 25 : return stappler::hash::hash64(str, len);
365 : }
366 25 : constexpr uint64_t operator"" _tag64 ( const char* str, size_t len) {
367 25 : return stappler::hash::hash64(str, len);
368 : }
369 :
370 4000 : constexpr long double operator"" _to_rad ( long double val ) { return val * numbers::pi / 180.0; }
371 1000 : constexpr long double operator"" _to_rad ( unsigned long long int val ) { return val * numbers::pi / 180.0; }
372 :
373 : // string length (useful for comparation: memcmp(str, "Test", "Test"_len) )
374 25 : constexpr size_t operator"" _length ( const char* str, size_t len) { return len; }
375 25 : constexpr size_t operator"" _length ( const char16_t* str, size_t len) { return len; }
376 20771 : constexpr size_t operator"" _len ( const char* str, size_t len) { return len; }
377 100 : constexpr size_t operator"" _len ( const char16_t* str, size_t len) { return len; }
378 :
379 25 : constexpr unsigned long long int operator"" _GiB ( unsigned long long int val ) { return val * 1024 * 1024 * 1024; }
380 150 : constexpr unsigned long long int operator"" _MiB ( unsigned long long int val ) { return val * 1024 * 1024; }
381 1735500 : constexpr unsigned long long int operator"" _KiB ( unsigned long long int val ) { return val * 1024; }
382 :
383 25 : constexpr char16_t operator"" _c16 (unsigned long long int val) { return (char16_t)val; }
384 25 : constexpr char operator"" _c8 (unsigned long long int val) { return (char)val; }
385 :
386 :
387 : /*
388 : * Misc templates
389 : *
390 : * Functions:
391 : * - nan<float / double>() - shortcut for Not A Number value
392 : * - minOf<T>() / maxOf<T>() - shortcuts for minimal/maximal values
393 : * - toInt<T>(EnumVal) - extract integer from strong-typed enum
394 : *
395 : * - T GetErrorValue<T>() - get default value, that can be easily
396 : * interpreted as error (NaN for floats, maxOf<T> for integers)
397 : *
398 : * - bool IsErrorValue(T val) - check for error value
399 : *
400 : * - T reinterpretValue(V) - relaxed version of reinterpret_cast,
401 : * often used to convert signed to unsigned
402 : *
403 : * - T StringToNumber(const char *ptr, char ** tail) - read specified
404 : * numeric type from string in `strtod` style
405 : *
406 : * - progress(A, B, p) - progress between A and B, defined by float
407 : * between 0.0f and 1.0f
408 : *
409 : * - SP_DEFINE_ENUM_AS_MASK(Type) - defines strongly-typed enum class
410 : * as bitmask
411 : */
412 :
413 : template <typename... Args>
414 30198787 : inline constexpr auto pair(Args&&... args) -> decltype(std::make_pair(forward<Args>(args)...)) {
415 30198787 : return std::make_pair(forward<Args>(args)...);
416 : }
417 :
418 : template <typename T, typename V>
419 : using Pair = std::pair<T, V>;
420 :
421 : template <typename T>
422 : using NumericLimits = std::numeric_limits<T>;
423 :
424 : template <typename T>
425 : using InitializerList = std::initializer_list<T>;
426 :
427 : template <typename T = float>
428 18541884 : inline constexpr auto nan() -> T {
429 18541884 : return NumericLimits<T>::quiet_NaN();
430 : }
431 :
432 : template <typename T = float>
433 125 : inline constexpr auto epsilon() -> T {
434 125 : return NumericLimits<T>::epsilon();
435 : }
436 :
437 : template <typename T>
438 16438893 : inline auto isnan(T && t) -> bool {
439 16438893 : return std::isnan(std::forward<T>(t));
440 : }
441 :
442 : template <class T>
443 1173938834 : inline constexpr T maxOf() {
444 1173938834 : return NumericLimits<T>::max();
445 : }
446 :
447 : template <class T>
448 50 : inline constexpr T minOf() {
449 50 : return NumericLimits<T>::min();
450 : }
451 :
452 : template <typename T, typename V>
453 : struct HasMultiplication {
454 : template<class A, class B>
455 : static auto test(A *, B *) -> decltype(std::declval<A>() * std::declval<B>());
456 :
457 : template<typename, typename>
458 : static auto test(...) -> std::false_type;
459 :
460 : using type = typename std::is_same<T, decltype(test<T, V>(0, 0))>::type;
461 : };
462 :
463 : template <class T>
464 13886 : constexpr inline T progress(const T &a, const T &b, float p) { return (a * (1.0f - p) + b * p); }
465 :
466 : template <class T, class V>
467 : struct _ValueReinterpretator {
468 41967142 : inline static T reinterpret(V v) { T ret; memcpy(&ret, &v, sizeof(V)); return ret; } // follow strict aliasing rules
469 : };
470 :
471 : template <class T>
472 : struct _ValueReinterpretator<T, T> {
473 14641718 : inline static T reinterpret(T v) { return v; }
474 : };
475 :
476 : template <class T, class V, typename std::enable_if<sizeof(T) == sizeof(V)>::type* = nullptr>
477 56608860 : inline T reinterpretValue(V v) {
478 56608860 : return _ValueReinterpretator<T, V>::reinterpret(v);
479 : }
480 :
481 : template <typename E>
482 31729030499 : constexpr typename std::underlying_type<E>::type toInt(const E &e) {
483 31729030499 : return static_cast<typename std::underlying_type<E>::type>(e);
484 : }
485 :
486 : template <typename T> auto StringToNumber(const char *ptr, char ** tail, int base) -> T;
487 :
488 : template <> inline auto
489 50 : StringToNumber<unsigned int>(const char *ptr, char ** tail, int base) -> unsigned int {
490 50 : if (ptr) {
491 25 : return (unsigned int)strtoul(ptr, tail, base);
492 : }
493 25 : return 0;
494 : }
495 :
496 : template <> inline auto
497 275 : StringToNumber<unsigned long>(const char *ptr, char ** tail, int base) -> unsigned long {
498 275 : if (ptr) {
499 250 : return strtoul(ptr, tail, base);
500 : }
501 25 : return 0;
502 : }
503 :
504 : template <> inline auto
505 50 : StringToNumber<unsigned long long>(const char *ptr, char ** tail, int base) -> unsigned long long {
506 50 : if (ptr) {
507 25 : return strtoull(ptr, tail, base);
508 : }
509 25 : return 0;
510 : }
511 :
512 : template <> inline auto
513 50 : StringToNumber<int>(const char *ptr, char ** tail, int base) -> int {
514 50 : if (ptr) {
515 25 : return (int)strtol(ptr, tail, base);
516 : }
517 25 : return 0;
518 : }
519 :
520 : template <> inline auto
521 5082672 : StringToNumber<long>(const char *ptr, char ** tail, int base) -> long {
522 5082672 : if (ptr) {
523 5082647 : return strtol(ptr, tail, base);
524 : }
525 25 : return 0;
526 : }
527 :
528 : template <> inline auto
529 50 : StringToNumber<long long>(const char *ptr, char ** tail, int base) -> long long {
530 50 : if (ptr) {
531 25 : return strtoll(ptr, tail, base);
532 : }
533 25 : return 0;
534 : }
535 :
536 : template <> inline auto
537 5200 : StringToNumber<float>(const char *ptr, char ** tail, int base) -> float {
538 5200 : if (ptr) {
539 5175 : return strtof(ptr, tail);
540 : }
541 25 : return 0.0f;
542 : }
543 :
544 : template <> inline auto
545 51450 : StringToNumber<double>(const char *ptr, char ** tail, int base) -> double {
546 51450 : if (ptr) {
547 51425 : return strtod(ptr, tail);
548 : }
549 25 : return 0.0;
550 : }
551 :
552 : /** SP_DEFINE_ENUM_AS_MASK is utility to make a bitwise-mask from typed enum
553 : * It defines a set of overloaded operators, that allow some bitwise operations
554 : * on this enum class
555 : */
556 : #define SP_DEFINE_ENUM_AS_MASK(Type) \
557 : SP_COVERAGE_TRIVIAL constexpr inline Type operator | (const Type &l, const Type &r) { return Type(stappler::toInt(l) | stappler::toInt(r)); } \
558 : SP_COVERAGE_TRIVIAL constexpr inline Type operator & (const Type &l, const Type &r) { return Type(stappler::toInt(l) & stappler::toInt(r)); } \
559 : SP_COVERAGE_TRIVIAL constexpr inline Type operator ^ (const Type &l, const Type &r) { return Type(stappler::toInt(l) ^ stappler::toInt(r)); } \
560 : SP_COVERAGE_TRIVIAL constexpr inline Type & operator |= (Type &l, const Type &r) { l = Type(stappler::toInt(l) | stappler::toInt(r)); return l; } \
561 : SP_COVERAGE_TRIVIAL constexpr inline Type & operator &= (Type &l, const Type &r) { l = Type(stappler::toInt(l) & stappler::toInt(r)); return l; } \
562 : SP_COVERAGE_TRIVIAL constexpr inline Type & operator ^= (Type &l, const Type &r) { l = Type(stappler::toInt(l) ^ stappler::toInt(r)); return l; } \
563 : SP_COVERAGE_TRIVIAL constexpr inline bool operator == (const Type &l, const std::underlying_type<Type>::type &r) { return stappler::toInt(l) == r; } \
564 : SP_COVERAGE_TRIVIAL constexpr inline bool operator == (const std::underlying_type<Type>::type &l, const Type &r) { return l == stappler::toInt(r); } \
565 : SP_COVERAGE_TRIVIAL constexpr inline bool operator != (const Type &l, const std::underlying_type<Type>::type &r) { return stappler::toInt(l) != r; } \
566 : SP_COVERAGE_TRIVIAL constexpr inline bool operator != (const std::underlying_type<Type>::type &l, const Type &r) { return l != stappler::toInt(r); } \
567 : SP_COVERAGE_TRIVIAL constexpr inline Type operator~(const Type &t) { return Type(~stappler::toInt(t)); }
568 :
569 :
570 : /** Value wrapper is a syntactic sugar struct, that allow you to create
571 : * an alias type for some other type, that will be statically and uniquely
572 : * different from all other types
573 : *
574 : * Most common usage is type-based overload resolution, like
575 : *
576 : * using FilePath = ValueWrapper<StringView, class FilePathFlag>;
577 : * using DataString = ValueWrapper<StringView, class DataStringFlag>;
578 : *
579 : * ...
580 : *
581 : * class SomeClass {
582 : * SomeClass(FilePath); // init with data from file
583 : * SomeClass(DataString); // init with data from memory
584 : * };
585 : *
586 : * Also, ValueWrapper used in implementation of function with named arguments
587 : * and function, that requires additional type-checking
588 : */
589 :
590 : template <class T, class Flag>
591 : struct ValueWrapper {
592 : using Type = T;
593 :
594 64886 : static constexpr ValueWrapper<T, Flag> max() { return ValueWrapper<T, Flag>(NumericLimits<T>::max()); }
595 25 : static constexpr ValueWrapper<T, Flag> min() { return ValueWrapper<T, Flag>(NumericLimits<T>::min()); }
596 25 : static constexpr ValueWrapper<T, Flag> epsilon() { return ValueWrapper<T, Flag>(NumericLimits<T>::epsilon()); }
597 2236390 : static constexpr ValueWrapper<T, Flag> zero() { return ValueWrapper<T, Flag>(0); }
598 :
599 : inline constexpr ValueWrapper() = default;
600 4859 : inline explicit constexpr ValueWrapper(const T &val) : value(val) { }
601 3638331 : inline explicit constexpr ValueWrapper(T &&val) : value(std::move(val)) { }
602 :
603 : inline ValueWrapper(const ValueWrapper<T, Flag> &other) = default;
604 : inline ValueWrapper<T, Flag> &operator=(const ValueWrapper<T, Flag> &other) = default;
605 :
606 : inline ValueWrapper(ValueWrapper<T, Flag> &&other) = default;
607 : inline ValueWrapper<T, Flag> &operator=(ValueWrapper<T, Flag> &&other) = default;
608 :
609 25 : inline void set(const T &val) { value = val; }
610 25 : inline void set(T &&val) { value = std::move(val); }
611 3758197 : inline constexpr T & get() { return value; }
612 688501 : inline constexpr const T & get() const { return value; }
613 6797 : inline constexpr bool empty() const { return value == 0; }
614 :
615 797107 : inline constexpr bool operator == (const ValueWrapper<T, Flag> & other) const { return value == other.value; }
616 7588667 : inline constexpr bool operator != (const ValueWrapper<T, Flag> & other) const { return value != other.value; }
617 25 : inline constexpr bool operator > (const ValueWrapper<T, Flag> & other) const { return value > other.value; }
618 1862985 : inline constexpr bool operator < (const ValueWrapper<T, Flag> & other) const { return value < other.value; }
619 2603 : inline constexpr bool operator >= (const ValueWrapper<T, Flag> & other) const { return value >= other.value; }
620 2603 : inline constexpr bool operator <= (const ValueWrapper<T, Flag> & other) const { return value <= other.value; }
621 :
622 162 : inline constexpr void operator |= (const ValueWrapper<T, Flag> & other) { value |= other.value; }
623 25 : inline constexpr void operator &= (const ValueWrapper<T, Flag> & other) { value &= other.value; }
624 25 : inline constexpr void operator ^= (const ValueWrapper<T, Flag> & other) { value ^= other.value; }
625 50 : inline constexpr void operator += (const ValueWrapper<T, Flag> & other) { value += other.value; }
626 25 : inline constexpr void operator -= (const ValueWrapper<T, Flag> & other) { value -= other.value; }
627 25 : inline constexpr void operator *= (const ValueWrapper<T, Flag> & other) { value *= other.value; }
628 25 : inline constexpr void operator /= (const ValueWrapper<T, Flag> & other) { value /= other.value; }
629 :
630 25 : inline constexpr ValueWrapper<T, Flag> operator|(const ValueWrapper<T, Flag>& v) const { return ValueWrapper<T, Flag>(value | v.value); }
631 25 : inline constexpr ValueWrapper<T, Flag> operator&(const ValueWrapper<T, Flag>& v) const { return ValueWrapper<T, Flag>(value & v.value); }
632 25 : inline constexpr ValueWrapper<T, Flag> operator^(const ValueWrapper<T, Flag>& v) const { return ValueWrapper<T, Flag>(value ^ v.value); }
633 425 : inline constexpr ValueWrapper<T, Flag> operator+(const ValueWrapper<T, Flag>& v) const { return ValueWrapper<T, Flag>(value + v.value); }
634 581 : inline constexpr ValueWrapper<T, Flag> operator-(const ValueWrapper<T, Flag>& v) const { return ValueWrapper<T, Flag>(value - v.value); }
635 25 : inline constexpr ValueWrapper<T, Flag> operator*(const ValueWrapper<T, Flag>& v) const { return ValueWrapper<T, Flag>(value * v.value); }
636 25 : inline constexpr ValueWrapper<T, Flag> operator/(const ValueWrapper<T, Flag>& v) const { return ValueWrapper<T, Flag>(value / v.value); }
637 161 : inline constexpr ValueWrapper<T, Flag> operator-() const { return ValueWrapper<T, Flag>(-value); }
638 :
639 896 : inline ValueWrapper<T, Flag> &operator++ () { value ++; return *this; }
640 50 : inline ValueWrapper<T, Flag> &operator-- () { value --; return *this; }
641 :
642 871 : inline ValueWrapper<T, Flag> operator++ (int) { ValueWrapper<T, Flag> result(*this); ++(*this); return result; }
643 25 : inline ValueWrapper<T, Flag> operator-- (int) { ValueWrapper<T, Flag> result(*this); --(*this); return result; }
644 :
645 : // to enable progress
646 : template <typename M>
647 : inline constexpr std::enable_if_t<HasMultiplication<Type, M>::type::value, ValueWrapper<T, Flag>>
648 50 : operator*(const M &v) const { return ValueWrapper<T, Flag>(value * v); }
649 :
650 : #if SP_HAVE_THREE_WAY_COMPARISON
651 343131 : SP_THREE_WAY_COMPARISON_TYPE(ValueWrapper)
652 : #endif
653 :
654 343131 : T value;
655 : };
656 :
657 : /** Result is a helper class for functions, that returns some result
658 : * or fails and returns nothing. It defines several mechanisms to handle
659 : * error state:
660 : * - get with default value in case of failure (`get`)
661 : * - grab value into object, provided by reference, if value is valid (`grab`)
662 : * - call a callback with value, if it's valid (`unwrap`)
663 : */
664 : template <typename T>
665 : struct Result {
666 : enum Status {
667 : Ok,
668 : Error
669 : };
670 :
671 : Status status = Error;
672 : T result;
673 :
674 : static Result<T> error() { return Result(); }
675 :
676 : Result(T && t) : status(Ok), result(move(t)) { }
677 5133123 : Result(const T & t) : status(Ok), result(t) { }
678 :
679 4325 : Result() = default;
680 : Result(const Result &) = default;
681 : Result(Result &&) = default;
682 : Result& operator=(const Result &) = default;
683 : Result& operator=(Result &&) = default;
684 :
685 3000 : bool valid() const { return status == Ok; }
686 :
687 : template <typename Callback>
688 5094442 : bool unwrap(const Callback &cb) const {
689 5094442 : if (status == Ok) {
690 5094417 : cb(result);
691 5094417 : return true;
692 : }
693 25 : return false;
694 : }
695 :
696 23550 : bool grab(T &value) {
697 23550 : if (status == Ok) {
698 19250 : value = move(result);
699 19250 : return true;
700 : }
701 4300 : return false;
702 : }
703 :
704 7674 : const T & get() const { return result; }
705 4410 : const T & get(const T &def) const { return (status == Ok) ? result : def; }
706 : };
707 :
708 : /*
709 : * Invoker/CallTest macro
710 : */
711 :
712 : #define InvokerCallTest_MakeCallTest(Name, Success, Failure) \
713 : private: \
714 : template <typename C> static Success CallTest_ ## Name( typeof(&C::Name) ); \
715 : template <typename C> static Failure CallTest_ ## Name(...); \
716 : public: \
717 : static constexpr bool Name = sizeof(CallTest_ ## Name<T>(0)) == sizeof(success);
718 :
719 : const char * getStapplerVersionString();
720 : uint32_t getStapplerVersionNumber();
721 : uint32_t getStapplerVersionBuild();
722 :
723 : }
724 :
725 : /*
726 : * Extra math functions
727 : */
728 :
729 : namespace STAPPLER_VERSIONIZED stappler::math {
730 :
731 : constexpr float MATH_FLOAT_SMALL = 1.0e-37f;
732 : constexpr float MATH_TOLERANCE = 2e-37f;
733 :
734 : /**
735 : * Updates this vector towards the given target using a smoothing function.
736 : * The given response time determines the amount of smoothing (lag). A longer
737 : * response time yields a smoother result and more lag. To force this vector to
738 : * follow the target closely, provide a response time that is very small relative
739 : * to the given elapsed time. */
740 :
741 : // avoid constexpr to support SIMD-based implementation
742 : template <typename T> inline
743 : T smooth(const T &source, const T &target, float elapsed, float response) {
744 : if (elapsed > 0) {
745 : return source + (target - source) * (elapsed / (elapsed + response));
746 : }
747 : return source;
748 : }
749 :
750 : // avoid constexpr to support SIMD-based implementation
751 : template <typename T> inline
752 2480 : T lerp(const T &a, const T &b, float alpha) {
753 2480 : return (a * (1.0f - alpha) + b * alpha);
754 : }
755 :
756 : template<class T, class Compare> constexpr inline
757 52549 : const T& clamp(const T& v, const T& lo, const T& hi, Compare comp) {
758 52549 : if (comp(hi, lo)) {
759 25 : return comp(v, hi) ? hi : comp(lo, v) ? lo : v;
760 : } else {
761 52524 : return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
762 : }
763 : }
764 :
765 : template<class T> constexpr inline
766 52549 : const T& clamp(const T& v, const T& lo, const T& hi) {
767 52549 : return math::clamp( v, lo, hi, std::less<T>() );
768 : }
769 :
770 : template<class T, class Compare> constexpr inline
771 125 : T clamp_distance(const T& v, const T& lo, const T& hi, Compare comp, const T &z) {
772 125 : assert( !comp(hi, lo) );
773 125 : return comp(v, lo) ? (lo - v) : comp(hi, v) ? (v - hi) : z;
774 : }
775 :
776 : template<class T, class Compare> constexpr inline
777 25 : T clamp_distance(const T& v, const T& lo, const T& hi, Compare comp) {
778 25 : return clamp_distance(v, lo, hi, comp, T(0));
779 : }
780 :
781 : template<class T> constexpr inline
782 25 : T clamp_distance(const T& v, const T& lo, const T& hi, const T &z) {
783 25 : return clamp_distance(v, lo, hi, std::less<T>(), z);
784 : }
785 :
786 : template<class T> constexpr inline
787 75 : T clamp_distance(const T& v, const T& lo, const T& hi) {
788 75 : return clamp_distance(v, lo, hi, std::less<T>(), T(0));
789 : }
790 :
791 : // next power of two
792 75 : inline uint32_t npot(uint32_t n) {
793 75 : --n;
794 :
795 75 : n |= n >> 1;
796 75 : n |= n >> 2;
797 75 : n |= n >> 4;
798 75 : n |= n >> 8;
799 75 : n |= n >> 16;
800 :
801 75 : return n + 1;
802 : }
803 :
804 1334 : inline uint64_t npot(uint64_t n) {
805 1334 : --n;
806 :
807 1334 : n |= n >> 1;
808 1334 : n |= n >> 2;
809 1334 : n |= n >> 4;
810 1334 : n |= n >> 8;
811 1334 : n |= n >> 16;
812 1334 : n |= n >> 32;
813 :
814 1334 : return n + 1;
815 : }
816 :
817 : // Align on a power of 2 boundary
818 : template <typename T = uint64_t>
819 29688122 : static constexpr auto align(T size, T boundary) -> T {
820 29688122 : return (((size) + ((boundary) - 1)) & ~((boundary) - 1));
821 : }
822 :
823 : // convert degrees to radians
824 : template <typename T>
825 150 : constexpr auto to_rad(T val) -> T {
826 150 : return T(val) * numbers::pi_v<T> / T(180);
827 : }
828 :
829 : // convert radians to degrees
830 : template <typename T>
831 25 : constexpr auto to_deg(T val) -> T {
832 25 : return T(val) * T(180) / numbers::pi_v<T>;
833 : }
834 :
835 : }
836 :
837 : namespace std {
838 :
839 : template <typename Value, typename Flag>
840 : struct hash<STAPPLER_VERSIONIZED_NAMESPACE::ValueWrapper<Value, Flag>> {
841 25 : hash() { }
842 :
843 25 : size_t operator() (const STAPPLER_VERSIONIZED_NAMESPACE::ValueWrapper<Value, Flag> &value) const noexcept {
844 25 : return hash<Value>()(value.get());
845 : }
846 : };
847 :
848 : }
849 :
850 : #endif /* STAPPLER_CORE_SPCORE_H_ */
|