//MIT License // //Copyright (c) 2017 Mindaugas Vinkelis // //Permission is hereby granted, free of charge, to any person obtaining a copy //of this software and associated documentation files (the "Software"), to deal //in the Software without restriction, including without limitation the rights //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell //copies of the Software, and to permit persons to whom the Software is //furnished to do so, subject to the following conditions: // //The above copyright notice and this permission notice shall be included in all //copies or substantial portions of the Software. // //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE //SOFTWARE. #ifndef BITSERY_COMMON_H #define BITSERY_COMMON_H #include namespace bitsery { template constexpr size_t BITS_SIZE = sizeof(T) << 3; template struct BIGGER_TYPE { }; template<> struct BIGGER_TYPE { typedef uint16_t type; }; template<> struct BIGGER_TYPE { typedef uint32_t type; }; template<> struct BIGGER_TYPE { typedef uint64_t type; }; template<> struct BIGGER_TYPE { typedef int16_t type; }; template<> struct BIGGER_TYPE { typedef int32_t type; }; template<> struct BIGGER_TYPE { typedef int64_t type; }; template<> struct BIGGER_TYPE { typedef int16_t type; }; template constexpr size_t ARITHMETIC_OR_ENUM_SIZE = std::is_arithmetic::value || std::is_enum::value ? sizeof(T) : 0; template struct SAME_SIZE_UNSIGNED_TYPE { typedef std::make_unsigned_t type; }; template struct SAME_SIZE_UNSIGNED_TYPE::value>::type> { typedef std::make_unsigned_t> type; }; template struct SAME_SIZE_UNSIGNED_TYPE::value>::type> { typedef std::conditional_t::value, uint32_t, uint64_t> type; }; template using SAME_SIZE_UNSIGNED = typename SAME_SIZE_UNSIGNED_TYPE::type; template struct ProcessAnyType { template static void serialize(S &s, T &&v) { s.template value(std::forward(v)); } }; template<> struct ProcessAnyType<0> { template static void serialize(S &s, T &&v) { s.object(std::forward(v)); } }; #define SERIALIZE(ObjectType) \ template ::value || std::is_same::value>::type* = nullptr> \ S& serialize(S& s, T& o) /* * range functions */ template constexpr size_t calcRequiredBits(T min, T max) { size_t res{}; for (auto diff = max - min; diff > 0; diff >>= 1) ++res; return res; } template struct RangeSpec { constexpr RangeSpec(T minValue, T maxValue) : min{minValue}, max{maxValue}, bitsRequired{calcRequiredBits(min, max)} { } const T min; const T max; const size_t bitsRequired; }; template struct RangeSpec::value>::type> { constexpr RangeSpec(T minValue, T maxValue) : min{minValue}, max{maxValue}, bitsRequired{calcRequiredBits( static_cast>(min), static_cast>(max))} { } const T min; const T max; const size_t bitsRequired; }; //this class is used to make default RangeSpec float specialization always prefer constructor with precision struct BitsConstraint { explicit constexpr BitsConstraint(size_t bits) : value{bits} {} const size_t value; }; template struct RangeSpec::value>::type> { constexpr RangeSpec(T minValue, T maxValue, BitsConstraint bits) : min{minValue}, max{maxValue}, bitsRequired{bits.value} { } constexpr RangeSpec(T minValue, T maxValue, T precision) : min{minValue}, max{maxValue}, bitsRequired{calcRequiredBits>({}, ((max - min) / precision))} { } const T min; const T max; const size_t bitsRequired; }; template::value>::type * = nullptr> bool isRangeValid(const T &v, const RangeSpec &r) { return !(r.min > v || v > r.max); } template::value>::type * = nullptr> bool isRangeValid(const T &v, const RangeSpec &r) { using VT = std::underlying_type_t; return !(static_cast(r.min) > static_cast(v) || static_cast(v) > static_cast(r.max)); } /* * delta functions */ class ObjectMemoryPosition { public: template ObjectMemoryPosition(const T &oldObj, const T &newObj) :ObjectMemoryPosition{reinterpret_cast(&oldObj), reinterpret_cast(&newObj), sizeof(T)} { } template bool isFieldsEquals(const T &newObjField) { return *getOldObjectField(newObjField) == newObjField; } template const T *getOldObjectField(const T &field) { auto offset = reinterpret_cast(&field) - newObj; return reinterpret_cast(oldObj + offset); } private: ObjectMemoryPosition(const char *objOld, const char *objNew, size_t) : oldObj{objOld}, newObj{objNew} { } const char *oldObj; const char *newObj; }; } #endif //BITSERY_COMMON_H