LCOV - code coverage report
Current view: top level - core/core - SPCore.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 167 167 100.0 %
Date: 2024-05-12 00:16:13 Functions: 900 996 90.4 %

          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_ */

Generated by: LCOV version 1.14