From 7964679ec2d05daeded296af1d0a1f07fb05ed3e Mon Sep 17 00:00:00 2001 From: fraillt Date: Mon, 20 Feb 2017 15:40:30 +0200 Subject: [PATCH] default renamed to substitution and covered with tests --- examples/basic_usage.cpp | 4 +- include/BufferReader.h | 185 ++++----- include/BufferWriter.h | 231 ++++++------ include/Common.h | 293 ++++++++------- include/DeltaDeserializer.h | 310 +++++++-------- include/DeltaSerializer.h | 356 +++++++++--------- include/Deserializer.h | 402 ++++++++++---------- include/Serializer.h | 457 ++++++++++++----------- tests/BufferBitsOpTests.cpp | 8 +- tests/BufferBytesOpTests.cpp | 7 +- tests/SerializationContainerTests.cpp | 20 +- tests/SerializationRangeTests.cpp | 6 +- tests/SerializationSubstitutionTests.cpp | 143 +++++++ tests/SerializationTestUtils.h | 12 +- tests/SerializationTextTests.cpp | 20 +- tests/SerializerObjectsTests.cpp | 16 +- tests/SerializerValuesTests.cpp | 18 +- 17 files changed, 1358 insertions(+), 1130 deletions(-) create mode 100644 tests/SerializationSubstitutionTests.cpp diff --git a/examples/basic_usage.cpp b/examples/basic_usage.cpp index cec9417..41f84e4 100644 --- a/examples/basic_usage.cpp +++ b/examples/basic_usage.cpp @@ -23,7 +23,7 @@ SERIALIZE(MyStruct) { return s. value(o.i). value(o.e). - container(o.fs); + container(o.fs, 100); } void print(const char* msg, const MyStruct& v) { @@ -36,6 +36,8 @@ void print(const char* msg, const MyStruct& v) { std::cout << std::endl << std::endl; } +using namespace bitsery; + int main() { //set some random data MyStruct data{}; diff --git a/include/BufferReader.h b/include/BufferReader.h index e35f36b..3852e0c 100644 --- a/include/BufferReader.h +++ b/include/BufferReader.h @@ -10,115 +10,120 @@ #include #include -struct BufferReader { +namespace bitsery { - using value_type = uint8_t; - BufferReader(const std::vector& buf):_buf{buf}, _pos{std::begin(buf)}{ + struct BufferReader { - } + using value_type = uint8_t; - template - bool readBytes(T& v) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); - using UT = typename std::make_unsigned::type; - return !m_scratch - ? directRead(&v, 1) - : readBits(reinterpret_cast(v), BITS_SIZE); - } + BufferReader(const std::vector &buf) : _buf{buf}, _pos{std::begin(buf)} { - template - bool readBuffer(T* buf, size_t count) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); + } - if (!m_scratchBits) { - return directRead(buf, count); - } else { + template + bool readBytes(T &v) { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); using UT = typename std::make_unsigned::type; - //todo improve implementation - const auto end = buf + count; - for (auto it = buf; it != end; ++it) { - if (!readBits(reinterpret_cast(*it), BITS_SIZE)) - return false; + return !m_scratch + ? directRead(&v, 1) + : readBits(reinterpret_cast(v), BITS_SIZE); + } + + template + bool readBuffer(T *buf, size_t count) { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); + + if (!m_scratchBits) { + return directRead(buf, count); + } else { + using UT = typename std::make_unsigned::type; + //todo improve implementation + const auto end = buf + count; + for (auto it = buf; it != end; ++it) { + if (!readBits(reinterpret_cast(*it), BITS_SIZE)) + return false; + } } + return true; } - return true; - } - template - bool readBits(T& v, size_t bitsCount) { - static_assert(std::is_integral() && std::is_unsigned(), ""); - assert(bitsCount <= BITS_SIZE); + template + bool readBits(T &v, size_t bitsCount) { + static_assert(std::is_integral() && std::is_unsigned(), ""); + assert(bitsCount <= BITS_SIZE); - const auto bytesRequired = bitsCount > m_scratchBits - ? ((bitsCount - 1 - m_scratchBits) >> 3) + 1u - : 0u; - if (static_cast(std::distance(_pos, std::end(_buf))) < bytesRequired ) - return false; - readBitsInternal(v, bitsCount); - return true; - } - - bool align() { - if ( m_scratchBits ) { - SCRATCH_TYPE tmp{}; - readBitsInternal(tmp, BITS_SIZE - m_scratchBits); - return tmp == 0; + const auto bytesRequired = bitsCount > m_scratchBits + ? ((bitsCount - 1 - m_scratchBits) >> 3) + 1u + : 0u; + if (static_cast(std::distance(_pos, std::end(_buf))) < bytesRequired) + return false; + readBitsInternal(v, bitsCount); + return true; } - return true; - } - bool isCompleted() const { - return _pos == std::end(_buf); - } - -private: - const std::vector& _buf; - decltype(std::begin(_buf)) _pos; - template - bool directRead(T* v, size_t count) { - static_assert(!std::is_const::value, ""); - const auto bytesCount = sizeof(T) * count; - if (static_cast(std::distance(_pos, std::end(_buf))) < bytesCount) - return false; - std::copy_n(_pos, bytesCount, reinterpret_cast(v)); - std::advance(_pos, bytesCount); - return true; - } - - template - void readBitsInternal(T& v, size_t size) { - auto bitsLeft = size; - T res{}; - while (bitsLeft > 0) { - auto bits = std::min(bitsLeft, BITS_SIZE); - if ( m_scratchBits < bits ) { - value_type tmp; - - std::copy_n(_pos, 1, reinterpret_cast(&tmp)); - std::advance(_pos, 1); - - m_scratch |= static_cast(tmp) << m_scratchBits; - m_scratchBits += BITS_SIZE; + bool align() { + if (m_scratchBits) { + SCRATCH_TYPE tmp{}; + readBitsInternal(tmp, BITS_SIZE - m_scratchBits); + return tmp == 0; } - auto shiftedRes = static_cast(m_scratch & ( (static_cast(1)<>= bits; - m_scratchBits -= bits; - bitsLeft -= bits; + return true; } - v = res; - } - using SCRATCH_TYPE = typename BIGGER_TYPE::type; + bool isCompleted() const { + return _pos == std::end(_buf); + } - SCRATCH_TYPE m_scratch{}; - size_t m_scratchBits{}; ///< Number of bits currently in the scratch buffer. If the user wants to read more bits than this, we have to go fetch another dword from memory. + private: + const std::vector &_buf; + decltype(std::begin(_buf)) _pos; -}; + template + bool directRead(T *v, size_t count) { + static_assert(!std::is_const::value, ""); + const auto bytesCount = sizeof(T) * count; + if (static_cast(std::distance(_pos, std::end(_buf))) < bytesCount) + return false; + std::copy_n(_pos, bytesCount, reinterpret_cast(v)); + std::advance(_pos, bytesCount); + return true; + } + template + void readBitsInternal(T &v, size_t size) { + auto bitsLeft = size; + T res{}; + while (bitsLeft > 0) { + auto bits = std::min(bitsLeft, BITS_SIZE); + if (m_scratchBits < bits) { + value_type tmp; + std::copy_n(_pos, 1, reinterpret_cast(&tmp)); + std::advance(_pos, 1); + + m_scratch |= static_cast(tmp) << m_scratchBits; + m_scratchBits += BITS_SIZE; + } + auto shiftedRes = + static_cast(m_scratch & ((static_cast(1) << bits) - 1)) << (size - bitsLeft); + res |= shiftedRes; + m_scratch >>= bits; + m_scratchBits -= bits; + bitsLeft -= bits; + } + v = res; + } + + using SCRATCH_TYPE = typename BIGGER_TYPE::type; + + SCRATCH_TYPE m_scratch{}; + size_t m_scratchBits{}; ///< Number of bits currently in the scratch buffer. If the user wants to read more bits than this, we have to go fetch another dword from memory. + + }; + +} #endif //PROJECT_TEMPLATE_BUFFER_READER_H diff --git a/include/BufferWriter.h b/include/BufferWriter.h index 3befdb5..cb5e6bc 100644 --- a/include/BufferWriter.h +++ b/include/BufferWriter.h @@ -10,138 +10,141 @@ #include #include -struct MeasureSize { +namespace bitsery { - template - void writeBytes(const T& ) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); - _bitsCount += BITS_SIZE; - } + struct MeasureSize { - template - void writeBits(const T& , size_t bitsCount) { - static_assert(std::is_integral() && std::is_unsigned(), ""); - assert(bitsCount <= BITS_SIZE); - _bitsCount += bitsCount; - } - - template - void writeBuffer(const T* , size_t count) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); - _bitsCount += BITS_SIZE * count; - } - - //get size in bytes - size_t getSize() const { - return _bitsCount / 8; - } -private: - size_t _bitsCount{}; - -}; - - -struct BufferWriter { - using value_type = uint8_t; - BufferWriter(std::vector& buffer):_buf{buffer}, _outIt{std::back_inserter(buffer)} { - static_assert(std::is_unsigned::value, ""); - } - - template - void writeBytes(const T& v) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); - - if (!m_scratchBits) { - directWrite(&v,1); - } else { - using UT = typename std::make_unsigned::type; - writeBits(reinterpret_cast(v), BITS_SIZE); + template + void writeBytes(const T &) { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); + _bitsCount += BITS_SIZE; } - } - template - void writeBuffer(const T* buf, size_t count) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); - if (!m_scratchBits) { - directWrite(buf, count); - } else { - using UT = typename std::make_unsigned::type; - //todo improve implementation - const auto end = buf + count; - for (auto it = buf; it != end; ++it) - writeBits(reinterpret_cast(*it), BITS_SIZE); + template + void writeBits(const T &, size_t bitsCount) { + static_assert(std::is_integral() && std::is_unsigned(), ""); + assert(bitsCount <= BITS_SIZE); + _bitsCount += bitsCount; } - } - template - void writeBits(const T& v, size_t bitsCount) { - static_assert(std::is_integral() && std::is_unsigned(), ""); - assert(bitsCount <= BITS_SIZE); - assert( v <= (( 1ULL << bitsCount ) - 1 ) ); - writeBitsInternal(v, bitsCount); - } - - void align() { - if ( m_scratchBits ) - writeBitsInternal(value_type{}, BITS_SIZE - m_scratchBits); - } - - void flush() { - if ( m_scratchBits ) - { - auto tmp = static_cast( m_scratch & bufTypeMask ); - directWrite(&tmp, 1); - m_scratch >>= m_scratchBits; - m_scratchBits -= m_scratchBits; + template + void writeBuffer(const T *, size_t count) { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); + _bitsCount += BITS_SIZE * count; } - } + + //get size in bytes + size_t getSize() const { + return _bitsCount / 8; + } + + private: + size_t _bitsCount{}; + + }; -private: + struct BufferWriter { + using value_type = uint8_t; - template - void directWrite(const T* v, size_t count) { - const auto bytesSize = sizeof(T) * count; - const auto pos = _buf.size(); - _buf.resize(pos + bytesSize); - std::copy_n(reinterpret_cast(v), bytesSize, _buf.data()+pos); - } + BufferWriter(std::vector &buffer) : _buf{buffer}, _outIt{std::back_inserter(buffer)} { + static_assert(std::is_unsigned::value, ""); + } - template - void writeBitsInternal(const T& v, size_t size) { - auto value = v; - auto bitsLeft = size; - while (bitsLeft > 0) { - auto bits = std::min(bitsLeft, BITS_SIZE); - m_scratch |= static_cast( value ) << m_scratchBits; - m_scratchBits += bits; - if ( m_scratchBits >= BITS_SIZE ) { - auto tmp = static_cast(m_scratch & bufTypeMask); - directWrite(&tmp, 1); - m_scratch >>= BITS_SIZE; - m_scratchBits -= BITS_SIZE; + template + void writeBytes(const T &v) { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); - value >>= BITS_SIZE; + if (!m_scratchBits) { + directWrite(&v, 1); + } else { + using UT = typename std::make_unsigned::type; + writeBits(reinterpret_cast(v), BITS_SIZE); } - bitsLeft -= bits; } - } - const value_type bufTypeMask = 0xFF; - using SCRATCH_TYPE = typename BIGGER_TYPE::type; - std::vector& _buf; - std::back_insert_iterator> _outIt; - SCRATCH_TYPE m_scratch{}; - size_t m_scratchBits{}; + template + void writeBuffer(const T *buf, size_t count) { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); + if (!m_scratchBits) { + directWrite(buf, count); + } else { + using UT = typename std::make_unsigned::type; + //todo improve implementation + const auto end = buf + count; + for (auto it = buf; it != end; ++it) + writeBits(reinterpret_cast(*it), BITS_SIZE); + } + } + + template + void writeBits(const T &v, size_t bitsCount) { + static_assert(std::is_integral() && std::is_unsigned(), ""); + assert(bitsCount <= BITS_SIZE); + assert(v <= ((1ULL << bitsCount) - 1)); + writeBitsInternal(v, bitsCount); + } + + void align() { + if (m_scratchBits) + writeBitsInternal(value_type{}, BITS_SIZE - m_scratchBits); + } + + void flush() { + if (m_scratchBits) { + auto tmp = static_cast( m_scratch & bufTypeMask ); + directWrite(&tmp, 1); + m_scratch >>= m_scratchBits; + m_scratchBits -= m_scratchBits; + } + } - //size_t _bufSize{}; + private: -}; + template + void directWrite(const T *v, size_t count) { + const auto bytesSize = sizeof(T) * count; + const auto pos = _buf.size(); + _buf.resize(pos + bytesSize); + std::copy_n(reinterpret_cast(v), bytesSize, _buf.data() + pos); + } + template + void writeBitsInternal(const T &v, size_t size) { + auto value = v; + auto bitsLeft = size; + while (bitsLeft > 0) { + auto bits = std::min(bitsLeft, BITS_SIZE); + m_scratch |= static_cast( value ) << m_scratchBits; + m_scratchBits += bits; + if (m_scratchBits >= BITS_SIZE) { + auto tmp = static_cast(m_scratch & bufTypeMask); + directWrite(&tmp, 1); + m_scratch >>= BITS_SIZE; + m_scratchBits -= BITS_SIZE; + + value >>= BITS_SIZE; + } + bitsLeft -= bits; + } + } + + const value_type bufTypeMask = 0xFF; + using SCRATCH_TYPE = typename BIGGER_TYPE::type; + std::vector &_buf; + std::back_insert_iterator> _outIt; + SCRATCH_TYPE m_scratch{}; + size_t m_scratchBits{}; + + + //size_t _bufSize{}; + + }; +} #endif //PROJECT_TEMPLATE_BUFFER_WRITER_H diff --git a/include/Common.h b/include/Common.h index 0f1c2aa..bbaaca7 100644 --- a/include/Common.h +++ b/include/Common.h @@ -7,190 +7,193 @@ #include -template -constexpr size_t BITS_SIZE = sizeof(T) << 3; +namespace bitsery { -template -struct BIGGER_TYPE {}; + template + constexpr size_t BITS_SIZE = sizeof(T) << 3; -template <> -struct BIGGER_TYPE { - typedef uint16_t type; -}; + template + struct BIGGER_TYPE { + }; -template <> -struct BIGGER_TYPE { - typedef uint32_t type; -}; + template<> + struct BIGGER_TYPE { + typedef uint16_t type; + }; -template <> -struct BIGGER_TYPE { - typedef uint64_t type; -}; + template<> + struct BIGGER_TYPE { + typedef uint32_t type; + }; -template <> -struct BIGGER_TYPE { - typedef int16_t type; -}; + template<> + struct BIGGER_TYPE { + typedef uint64_t type; + }; -template <> -struct BIGGER_TYPE { - typedef int32_t type; -}; + template<> + struct BIGGER_TYPE { + typedef int16_t type; + }; -template <> -struct BIGGER_TYPE { - typedef int64_t type; -}; + template<> + struct BIGGER_TYPE { + typedef int32_t type; + }; -template <> -struct BIGGER_TYPE { - typedef int16_t type; -}; + template<> + struct BIGGER_TYPE { + typedef int64_t type; + }; -template -constexpr size_t ARITHMETIC_OR_ENUM_SIZE = std::is_arithmetic::value || std::is_enum::value ? sizeof(T) : 0; + 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 { + 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::make_unsigned_t> type; + }; -template -struct SAME_SIZE_UNSIGNED_TYPE::value>::type> { - typedef std::conditional_t::value, uint32_t, uint64_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 + 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 { + 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)); - } -}; + 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) -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)} - { + template + constexpr size_t calcRequiredBits(T min, T max) { + size_t res{}; + for (auto diff = max - min; diff > 0; diff >>= 1) + ++res; + return res; } - const T min; - const T max; - const size_t bitsRequired; -}; + + 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> { + 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; -}; + 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; -}; + struct BitsConstraint { + explicit constexpr BitsConstraint(size_t bits) : value{bits} {} -template -struct RangeSpec::value>::type> { + const size_t value; + }; - constexpr RangeSpec(T minValue, T maxValue, BitsConstraint bits): - min{minValue}, - max{maxValue}, - bitsRequired{bits.value} - { - } + template + struct RangeSpec::value>::type> { - constexpr RangeSpec(T minValue, T maxValue, T precision): - min{minValue}, - max{maxValue}, - bitsRequired{calcRequiredBits>({}, ((max - min) / precision))} - { - - } + constexpr RangeSpec(T minValue, T maxValue, BitsConstraint bits) : + min{minValue}, + max{maxValue}, + bitsRequired{bits.value} { + } - const T min; - const T max; - const size_t bitsRequired; -}; + 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; + }; -class ObjectMemoryPosition { -public: + class ObjectMemoryPosition { + public: - template - ObjectMemoryPosition(const T& oldObj, const T& newObj) - :ObjectMemoryPosition{reinterpret_cast(&oldObj), reinterpret_cast(&newObj), sizeof(T)} - { - } + 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: + template + bool isFieldsEquals(const T &newObjField) { + return *getOldObjectField(newObjField) == newObjField; + } - ObjectMemoryPosition(const char* objOld, const char* objNew, size_t ) - :oldObj{objOld}, - newObj{objNew} - { - } + template + const T *getOldObjectField(const T &field) { + auto offset = reinterpret_cast(&field) - newObj; + return reinterpret_cast(oldObj + offset); + } - const char* oldObj; - const char* newObj; -}; + private: + ObjectMemoryPosition(const char *objOld, const char *objNew, size_t) + : oldObj{objOld}, + newObj{objNew} { + } + + const char *oldObj; + const char *newObj; + }; + +} #endif //TMP_COMMON_H diff --git a/include/DeltaDeserializer.h b/include/DeltaDeserializer.h index d05d502..aee6c3a 100644 --- a/include/DeltaDeserializer.h +++ b/include/DeltaDeserializer.h @@ -10,183 +10,191 @@ #include #include "Deserializer.h" -template -class DeltaDeserializer { -public: - DeltaDeserializer(Reader& r, const TObj& oldObj, const TObj& newObj) - :_deserializer{r}, - _reader{r}, - _oldObj{oldObj}, - _newObj{newObj}, - _objMemPos(std::deque(1, ObjectMemoryPosition{oldObj, newObj})), - _isNewElement{false} - { - }; +namespace bitsery { - template::value>::type* = nullptr> - DeltaDeserializer& value(T& v) { - if (getChangedState(v)) { - constexpr size_t ValueSize = SIZE == 0 ? sizeof(T) : SIZE; - _reader.template readBytes(v); - } - return *this; - } + template + class DeltaDeserializer { + public: + DeltaDeserializer(Reader &r, const TObj &oldObj, const TObj &newObj) + : _deserializer{r}, + _reader{r}, + _oldObj{oldObj}, + _newObj{newObj}, + _objMemPos(std::deque(1, ObjectMemoryPosition{oldObj, newObj})), + _isNewElement{false} { + }; - template - DeltaDeserializer& object(T&& obj) { - if (getChangedState(obj)) - return serialize(*this, std::forward(obj)); - return *this; - } - - template - DeltaDeserializer& text(T&& str) { - if (getChangedState(str)) { - _deserializer.text(str); - } - return *this; - } - - - - template - DeltaDeserializer & array(std::array &arr, Fnc&& fnc) { - if (getChangedState(arr)) { - if (!_isNewElement) { - const auto old = *_objMemPos.top().getOldObjectField(arr); - processContainer(std::begin(old), std::end(old), std::begin(arr), std::end(arr), fnc); - } else { - for (auto& v:arr) - fnc(v); + template::value>::type * = nullptr> + DeltaDeserializer &value(T &v) { + if (getChangedState(v)) { + constexpr size_t ValueSize = SIZE == 0 ? sizeof(T) : SIZE; + _reader.template readBytes(v); } + return *this; } - return *this; - } + template + DeltaDeserializer &object(T &&obj) { + if (getChangedState(obj)) + return serialize(*this, std::forward(obj)); + return *this; + } - template - DeltaDeserializer& array(T (&arr)[N], Fnc&& fnc) { - if (getChangedState(arr)) { - if (!_isNewElement) { - const auto old = *_objMemPos.top().getOldObjectField(arr); - T* tmp = arr; - processContainer(old, old + N, tmp, tmp + N, fnc); - } else { - T* tmp = arr; - for (auto i=0u; i < N; ++i, ++tmp) - fnc(*tmp); + template + DeltaDeserializer &text(std::basic_string &str, size_t maxSize) { + if (getChangedState(str)) { + _deserializer.text(str, maxSize); } + return *this; } - return *this; - } - template - DeltaDeserializer& container(T& obj, Fnc&& fnc) { - if(getChangedState(obj)) { - size_t newSize{}; - _reader.readBits(newSize, 32); - if (!_isNewElement) { - auto old = *_objMemPos.top().getOldObjectField(obj); - if (old.size() != newSize) + template + DeltaDeserializer &text(T (&str)[N], size_t maxSize) { + if (getChangedState(str)) { + _deserializer.text(str, maxSize); + } + return *this; + } + + + template + DeltaDeserializer &array(std::array &arr, Fnc &&fnc) { + if (getChangedState(arr)) { + if (!_isNewElement) { + const auto old = *_objMemPos.top().getOldObjectField(arr); + processContainer(std::begin(old), std::end(old), std::begin(arr), std::end(arr), fnc); + } else { + for (auto &v:arr) + fnc(v); + } + } + return *this; + } + + + template + DeltaDeserializer &array(T (&arr)[N], Fnc &&fnc) { + if (getChangedState(arr)) { + if (!_isNewElement) { + const auto old = *_objMemPos.top().getOldObjectField(arr); + T *tmp = arr; + processContainer(old, old + N, tmp, tmp + N, fnc); + } else { + T *tmp = arr; + for (auto i = 0u; i < N; ++i, ++tmp) + fnc(*tmp); + } + } + return *this; + } + + template + DeltaDeserializer &container(T &obj, Fnc &&fnc, size_t maxSize) { + if (getChangedState(obj)) { + size_t newSize{}; + _reader.readBits(newSize, 32); + if (!_isNewElement) { + auto old = *_objMemPos.top().getOldObjectField(obj); + if (old.size() != newSize) + obj.resize(newSize); + processContainer(std::begin(old), std::end(old), std::begin(obj), std::end(obj), + std::forward(fnc)); + } else { obj.resize(newSize); - processContainer(std::begin(old), std::end(old), std::begin(obj), std::end(obj), std::forward(fnc)); - } else { - obj.resize(newSize); - for (auto& v:obj) - fnc(v); + for (auto &v:obj) + fnc(v); + } } + return *this; } - return *this; - } -private: - Deserializer _deserializer; - Reader& _reader; + private: + Deserializer _deserializer; + Reader &_reader; - const TObj& _oldObj; - const TObj& _newObj; - std::stack _objMemPos; - bool _isNewElement; + const TObj &_oldObj; + const TObj &_newObj; + std::stack _objMemPos; + bool _isNewElement; - template - bool getChangedState(T& obj) { - if (!_isNewElement) { - if (!readChangedState()) { - obj = *_objMemPos.top().getOldObjectField(obj); - return false; + template + bool getChangedState(T &obj) { + if (!_isNewElement) { + if (!readChangedState()) { + obj = *_objMemPos.top().getOldObjectField(obj); + return false; + } } + return true; } - return true; - } - template - bool getChangedState(T (&arr)[N]) { - if (!_isNewElement) { - if (!readChangedState()) { - auto old = *_objMemPos.top().getOldObjectField(arr); - auto end = arr + N; - auto pOld = old; - for (auto p=arr; p != end; ++p, ++pOld) + template + bool getChangedState(T (&arr)[N]) { + if (!_isNewElement) { + if (!readChangedState()) { + auto old = *_objMemPos.top().getOldObjectField(arr); + auto end = arr + N; + auto pOld = old; + for (auto p = arr; p != end; ++p, ++pOld) + *p = *pOld; + return false; + } + } + return true; + } + + template + bool processContainer(TConstIt oldBegin, TConstIt oldEnd, TIt begin, TIt end, Fnc &&fnc) { + auto offset = readIndexOffset(); + auto p = begin; + auto pOld = oldBegin; + for (; p != end && pOld != oldEnd; ++p, ++pOld) { + if (offset) { *p = *pOld; + --offset; + } else { + _objMemPos.emplace(ObjectMemoryPosition{*pOld, *p}); + fnc(*p); + _objMemPos.pop(); + offset = readIndexOffset(); + } + } + if (offset != 0 && pOld != oldEnd) return false; - } - } - return true; - } - - template - bool processContainer(TConstIt oldBegin, TConstIt oldEnd, TIt begin, TIt end, Fnc&& fnc) { - auto offset = readIndexOffset(); - auto p = begin; - auto pOld = oldBegin; - for (; p != end && pOld != oldEnd; ++p, ++pOld) { - if (offset) { - *p = *pOld; - --offset; - } else { - _objMemPos.emplace(ObjectMemoryPosition{*pOld, *p}); + _isNewElement = true; + for (; p != end; ++p, --offset) fnc(*p); - _objMemPos.pop(); - offset = readIndexOffset(); - } + _isNewElement = false; + return offset == 0; + } - if (offset != 0 && pOld != oldEnd) - return false; - _isNewElement = true; - for (; p != end; ++p, --offset) - fnc(*p); - _isNewElement = false; - return offset == 0; - } - - bool readChangedState() { - unsigned char res{}; - _reader.readBits(res, 1); - return res; - } - - - - size_t readIndexOffset() { - //special case, if items are updated sequentialy - unsigned char tmp{}; - _reader.readBits(tmp, 1); - if (tmp) { - return 0u; - } - else { - size_t res{}; - _reader.readBits(tmp, 1); - if (tmp > 0) - _reader.readBits(res, 4); - else - _reader.readBits(res, 32); + bool readChangedState() { + unsigned char res{}; + _reader.readBits(res, 1); return res; } - } -}; + size_t readIndexOffset() { + //special case, if items are updated sequentialy + unsigned char tmp{}; + _reader.readBits(tmp, 1); + if (tmp) { + return 0u; + } else { + size_t res{}; + _reader.readBits(tmp, 1); + if (tmp > 0) + _reader.readBits(res, 4); + else + _reader.readBits(res, 32); + return res; + } + } + + }; + +} #endif //TMP_DELTADESERIALIZER_H diff --git a/include/DeltaSerializer.h b/include/DeltaSerializer.h index f4dd74b..7e50ca2 100644 --- a/include/DeltaSerializer.h +++ b/include/DeltaSerializer.h @@ -10,179 +10,191 @@ #include #include "Serializer.h" -template -class DeltaSerializer { -public: - DeltaSerializer(Writter& w, const TObj& oldObj, const TObj& newObj) - :_serializer{w}, - _writter{w}, - _oldObj{oldObj}, - _newObj{newObj}, - _objMemPos(std::deque(1, ObjectMemoryPosition{oldObj, newObj})), - _isNewElement{false} - { +namespace bitsery { + + template + class DeltaSerializer { + public: + DeltaSerializer(Writter &w, const TObj &oldObj, const TObj &newObj) + : _serializer{w}, + _writter{w}, + _oldObj{oldObj}, + _newObj{newObj}, + _objMemPos(std::deque(1, ObjectMemoryPosition{oldObj, newObj})), + _isNewElement{false} { + + }; + + template::value>::type * = nullptr> + DeltaSerializer &value(const T &v) { + if (setChangedState(v)) { + constexpr size_t ValueSize = SIZE == 0 ? sizeof(T) : SIZE; + _writter.template writeBytes(v); + } + return *this; + } + + template + DeltaSerializer &object(T &&obj) { + if (setChangedState(obj)) { + serialize(*this, std::forward(obj)); + } + return *this; + } + + template + DeltaSerializer &text(const std::basic_string &str, size_t maxSize) { + if (setChangedState(str)) { + _serializer.text(str, maxSize); + } + return *this; + + } + + template + DeltaSerializer &text(const T (&str)[N]) { + if (setChangedState(str)) { + _serializer.text(str); + } + return *this; + + } + + template + DeltaSerializer &array(const std::array &arr, Fnc &&fnc) { + if (setChangedState(arr)) { + if (!_isNewElement) { + const auto &old = *_objMemPos.top().getOldObjectField(arr); + processContainer(std::begin(old), std::end(old), std::begin(arr), std::end(arr), fnc); + } else { + for (auto &v:arr) + fnc(v); + } + } + return *this; + } + + + template + DeltaSerializer &array(const T (&arr)[N], Fnc &&fnc) { + if (setChangedState(arr)) { + if (!_isNewElement) { + auto old = *_objMemPos.top().getOldObjectField(arr); + const T *tmp = arr; + processContainer(old, old + N, tmp, tmp + N, fnc); + } else { + const T *tmp = arr; + for (auto i = 0u; i < N; ++i, ++tmp) + fnc(*tmp); + } + } + return *this; + } + + template + DeltaSerializer &container(T &&obj, Fnc &&fnc, size_t maxSize) { + if (setChangedState(obj)) { + _writter.writeBits(obj.size(), 32); + if (!_isNewElement) { + auto old = *_objMemPos.top().getOldObjectField(obj); + processContainer(std::begin(old), std::end(old), std::begin(obj), std::end(obj), + std::forward(fnc)); + } else { + for (auto &v:obj) + fnc(v); + } + } + return *this; + } + + private: + Serializer _serializer; + Writter &_writter; + const TObj &_oldObj; + const TObj &_newObj; + std::stack _objMemPos; + bool _isNewElement; + + template + bool setChangedState(const T &obj) { + if (!_isNewElement) { + auto res = !_objMemPos.top().isFieldsEquals(obj); + writeChangedState(res); + return res; + } + return true; + } + + template + bool setChangedState(const T (&arr)[N]) { + if (!_isNewElement) { + auto old = *_objMemPos.top().getOldObjectField(arr); + auto end = arr + N; + bool changed{}; + for (auto p = arr, pOld = old; p != end; ++p, ++pOld) { + if (!(*p == *pOld)) { + changed = true; + break; + } + } + writeChangedState(changed); + return changed; + } + return true; + } + + + template + void processContainer(const T oldBegin, const T oldEnd, const T begin, const T end, Fnc &&fnc) { + auto misMatch = std::mismatch(oldBegin, oldEnd, begin, end); + auto lastChanged = begin; + while (misMatch.first != oldEnd && misMatch.second != end) { + writeIndexOffset(std::distance(lastChanged, misMatch.second)); + _objMemPos.emplace(ObjectMemoryPosition{*misMatch.first, *misMatch.second}); + fnc(*misMatch.second); + _objMemPos.pop(); + ++misMatch.first; + ++misMatch.second; + lastChanged = misMatch.second; + misMatch = std::mismatch(misMatch.first, oldEnd, misMatch.second, end); + } + auto p = misMatch.second; + //write items left + writeIndexOffset(std::distance(lastChanged, end)); + //write old elements + for (auto pOld = misMatch.first; p != end && pOld != oldEnd; ++p, ++pOld) { + _objMemPos.emplace(ObjectMemoryPosition{*pOld, *p}); + fnc(*p); + _objMemPos.pop(); + } + + //write new elements + _isNewElement = true; + for (; p != end; ++p) + fnc(*p); + _isNewElement = false; + } + + void writeChangedState(bool state) { + _writter.writeBits(state ? 1u : 0u, 1); + } + + void writeIndexOffset(const size_t offset) { + //special case, if items are updated sequentialy + if (offset == 0) { + _writter.writeBits(1u, 1); + } else { + _writter.writeBits(0u, 1); + auto smallOffset = offset < 16; + _writter.writeBits(smallOffset ? 1u : 0u, 1); + if (smallOffset) + _writter.writeBits(offset, 4); + else + _writter.writeBits(offset, 32); + } + } }; - template::value>::type* = nullptr> - DeltaSerializer& value(const T& v) { - if (setChangedState(v)) { - constexpr size_t ValueSize = SIZE == 0 ? sizeof(T) : SIZE; - _writter.template writeBytes(v); - } - return *this; - } - - template - DeltaSerializer& object(T&& obj) { - if (setChangedState(obj)) { - serialize(*this, std::forward(obj)); - } - return *this; - } - - template - DeltaSerializer& text(T&& str) { - if(setChangedState(str)) { - _serializer.text(str); - } - return *this; - - } - - template - DeltaSerializer & array(const std::array &arr, Fnc&& fnc) { - if (setChangedState(arr)) { - if (!_isNewElement) { - const auto& old = *_objMemPos.top().getOldObjectField(arr); - processContainer(std::begin(old), std::end(old), std::begin(arr), std::end(arr), fnc); - } else { - for (auto& v:arr) - fnc(v); - } - } - return *this; - } - - - template - DeltaSerializer& array(const T (&arr)[N], Fnc&& fnc) { - if (setChangedState(arr)) { - if (!_isNewElement) { - auto old = *_objMemPos.top().getOldObjectField(arr); - const T* tmp = arr; - processContainer(old, old + N, tmp, tmp + N, fnc); - } else { - const T* tmp = arr; - for (auto i=0u; i < N; ++i, ++tmp) - fnc(*tmp); - } - } - return *this; - } - - template - DeltaSerializer& container(T&& obj, Fnc&& fnc) { - if(setChangedState(obj)) { - _writter.writeBits(obj.size(), 32); - if (!_isNewElement) { - auto old = *_objMemPos.top().getOldObjectField(obj); - processContainer(std::begin(old), std::end(old), std::begin(obj), std::end(obj), std::forward(fnc)); - } else { - for (auto& v:obj) - fnc(v); - } - } - return *this; - } - -private: - Serializer _serializer; - Writter& _writter; - const TObj& _oldObj; - const TObj& _newObj; - std::stack _objMemPos; - bool _isNewElement; - - template - bool setChangedState(const T& obj) { - if (!_isNewElement) { - auto res = !_objMemPos.top().isFieldsEquals(obj); - writeChangedState(res); - return res; - } - return true; - } - - template - bool setChangedState(const T (&arr)[N]) { - if (!_isNewElement) { - auto old = *_objMemPos.top().getOldObjectField(arr); - auto end = arr + N; - bool changed{}; - for (auto p=arr, pOld=old; p != end; ++p, ++pOld) { - if (!(*p == *pOld)) { - changed = true; - break; - } - } - writeChangedState(changed); - return changed; - } - return true; - } - - - template - void processContainer(const T oldBegin, const T oldEnd, const T begin, const T end, Fnc&& fnc) { - auto misMatch = std::mismatch(oldBegin, oldEnd, begin, end); - auto lastChanged = begin; - while (misMatch.first != oldEnd && misMatch.second != end) { - writeIndexOffset(std::distance(lastChanged, misMatch.second)); - _objMemPos.emplace(ObjectMemoryPosition{*misMatch.first, *misMatch.second}); - fnc(*misMatch.second); - _objMemPos.pop(); - ++misMatch.first; - ++misMatch.second; - lastChanged = misMatch.second; - misMatch = std::mismatch(misMatch.first, oldEnd, misMatch.second, end); - } - auto p = misMatch.second; - //write items left - writeIndexOffset(std::distance(lastChanged, end)); - //write old elements - for (auto pOld = misMatch.first; p != end && pOld != oldEnd; ++p, ++pOld) { - _objMemPos.emplace(ObjectMemoryPosition{*pOld, *p}); - fnc(*p); - _objMemPos.pop(); - } - - //write new elements - _isNewElement = true; - for (; p != end; ++p) - fnc(*p); - _isNewElement = false; - } - - void writeChangedState(bool state) { - _writter.writeBits(state ? 1u : 0u, 1); - } - - void writeIndexOffset(const size_t offset) { - //special case, if items are updated sequentialy - if (offset == 0) { - _writter.writeBits(1u, 1); - } else { - _writter.writeBits(0u, 1); - auto smallOffset = offset < 16; - _writter.writeBits(smallOffset ? 1u : 0u, 1); - if (smallOffset) - _writter.writeBits(offset, 4); - else - _writter.writeBits(offset, 32); - } - } - -}; - +} #endif //TMP_DELTASERIALIZER_H diff --git a/include/Deserializer.h b/include/Deserializer.h index cf4e739..257436d 100644 --- a/include/Deserializer.h +++ b/include/Deserializer.h @@ -8,220 +8,246 @@ #include "Common.h" #include -template -class Deserializer { -public: - Deserializer(Reader& r):_reader{r} {}; - - template - Deserializer& object(T&& obj) { - return serialize(*this, std::forward(obj)); - } +namespace bitsery { /* - * value overloads + * functions for range */ + template::value>::type* = nullptr> + void setRangeValue(T& v, const RangeSpec& r) { + v += r.min; + }; - template::value>::type* = nullptr> - Deserializer& value(T& v) { - static_assert(std::numeric_limits::is_iec559, ""); - static_assert(std::numeric_limits::is_iec559, ""); + template::value>::type* = nullptr> + void setRangeValue(T& v, const RangeSpec& r) { + using VT = std::underlying_type_t; + reinterpret_cast(v) += static_cast(r.min); + }; - constexpr size_t ValueSize = VSIZE == 0 ? sizeof(T) : VSIZE; - _reader.template readBytes(reinterpret_cast&>(v)); - return *this; - } - - template::value>::type* = nullptr> - Deserializer& value(T& v) { - constexpr size_t ValueSize = VSIZE == 0 ? sizeof(T) : VSIZE; - using UT = std::underlying_type_t; - _reader.template readBytes(reinterpret_cast(v)); - return *this; - } - - template::value>::type* = nullptr> - Deserializer& value(T& v) { - constexpr size_t ValueSize = VSIZE == 0 ? sizeof(T) : VSIZE; - _reader.template readBytes(v); - return *this; - } - - /* - * range - */ - - template - Deserializer& range(T& v, const RangeSpec& range) { - _reader.template readBits(reinterpret_cast&>(v), range.bitsRequired); - setRangeValue(v, range); - return *this; - } - - /* - * default overloads - */ - template - Deserializer& defaultV(T& v, const std::array& defValues) { - size_t index; - _reader.template readBits(index, calcRequiredBits({}, N + 1)); - if (index) - v = defValues[index-1]; - else - ProcessAnyType::serialize(*this, v); + template::value>::type* = nullptr> + void setRangeValue(T& v, const RangeSpec& r) { + using UIT = SAME_SIZE_UNSIGNED; + const auto intRep = reinterpret_cast(v); + const UIT maxUint = (static_cast(1) << r.bitsRequired) - 1; + v = r.min + (static_cast(intRep) / maxUint) * (r.max - r.min); }; - /* - * text overloads - */ + template + class Deserializer { + public: + Deserializer(Reader& r):_reader{r} {}; - template - Deserializer& text(std::basic_string& str) { - size_t size; - readLength(size); - std::vector buf(size); - _reader.template readBuffer(buf.data(), size); - str.assign(buf.data(), size); -// str.resize(size); -// if (size) -// _reader.template readBuffer(str.data(), size); - return *this; - } + template + Deserializer& object(T&& obj) { + return serialize(*this, std::forward(obj)); + } - template - Deserializer& text(T (&str)[N]) { - size_t size; - readLength(size); - _reader.template readBuffer(str, size); - str[size] = {}; - return *this; - } + /* + * value overloads + */ - /* - * container overloads - */ + template::value>::type* = nullptr> + Deserializer& value(T& v) { + static_assert(std::numeric_limits::is_iec559, ""); + static_assert(std::numeric_limits::is_iec559, ""); - template - Deserializer& container(T&& obj, Fnc&& fnc) { - decltype(obj.size()) size{}; - readLength(size); - obj.resize(size); - for (auto& v:obj) - fnc(v); - return *this; - } + constexpr size_t ValueSize = VSIZE == 0 ? sizeof(T) : VSIZE; + _reader.template readBytes(reinterpret_cast&>(v)); + return *this; + } - template - Deserializer& container(T& obj) { - decltype(obj.size()) size{}; - readLength(size); - obj.resize(size); - procContainer(obj); - return *this; - } + template::value>::type* = nullptr> + Deserializer& value(T& v) { + constexpr size_t ValueSize = VSIZE == 0 ? sizeof(T) : VSIZE; + using UT = std::underlying_type_t; + _reader.template readBytes(reinterpret_cast(v)); + return *this; + } - template - Deserializer& container(T& obj) { - decltype(obj.size()) size{}; - readLength(size); - obj.resize(size); - procContainer>(obj); - return *this; - } + template::value>::type* = nullptr> + Deserializer& value(T& v) { + constexpr size_t ValueSize = VSIZE == 0 ? sizeof(T) : VSIZE; + _reader.template readBytes(v); + return *this; + } - /* - * array overloads (fixed size array (std::array, and c-style array)) - */ + /* + * range + */ - //std::array overloads + template + Deserializer& range(T& v, const RangeSpec& range) { + _reader.template readBits(reinterpret_cast&>(v), range.bitsRequired); + setRangeValue(v, range); + return *this; + } - template - Deserializer & array(std::array &arr, Fnc && fnc) { - for (auto& v: arr) - fnc(v); - return *this; - } + /* + * substitution overloads + */ + template + Deserializer& substitution(T& v, const std::array& expectedValues, Fnc&& fnc) { + size_t index; + range(index, {{}, N + 1}); + if (index) + v = expectedValues[index-1]; + else + fnc(v); + return *this; + }; - template - Deserializer & array(std::array &arr) { - procContainer(arr); - return *this; - } + template + Deserializer& substitution(T& v, const std::array& expectedValues) { + size_t index; + range(index, {{}, N + 1}); + if (index) + v = expectedValues[index-1]; + else + ProcessAnyType::serialize(*this, v); + return *this; + }; - template - Deserializer & array(std::array &arr) { - procContainer>(arr); - return *this; - } + template + Deserializer& substitution(T& v, const std::array& expectedValues) { + size_t index; + range(index, {{}, N + 1}); + if (index) + v = expectedValues[index-1]; + else + ProcessAnyType>::serialize(*this, v); + return *this; + }; - //c-style array overloads + /* + * text overloads + */ - template - Deserializer& array(T (&arr)[N], Fnc&& fnc) { - T* tmp = arr; - for (auto i = 0u; i < N; ++i, ++tmp) - fnc(*tmp); - return *this; - } + template + Deserializer& text(std::basic_string& str, size_t maxSize) { + size_t size; + readLength(size); + std::vector buf(size); + _reader.template readBuffer(buf.data(), size); + str.assign(buf.data(), size); + // str.resize(size); + // if (size) + // _reader.template readBuffer(str.data(), size); + return *this; + } - template - Deserializer& array(T (&arr)[N]) { - procCArray(arr); - return *this; - } + template + Deserializer& text(T (&str)[N]) { + size_t size; + readLength(size); + _reader.template readBuffer(str, size); + str[size] = {}; + return *this; + } - template - Deserializer& array(T (&arr)[N]) { - procCArray>(arr); - return *this; - } + /* + * container overloads + */ + + template + Deserializer& container(T&& obj, Fnc&& fnc, size_t maxSize) { + decltype(obj.size()) size{}; + readLength(size); + obj.resize(size); + for (auto& v:obj) + fnc(v); + return *this; + } + + template + Deserializer& container(T& obj, size_t maxSize) { + decltype(obj.size()) size{}; + readLength(size); + obj.resize(size); + procContainer(obj); + return *this; + } + + template + Deserializer& container(T& obj, size_t maxSize) { + decltype(obj.size()) size{}; + readLength(size); + obj.resize(size); + procContainer>(obj); + return *this; + } + + /* + * array overloads (fixed size array (std::array, and c-style array)) + */ + + //std::array overloads + + template + Deserializer& array(std::array &arr, Fnc && fnc) { + for (auto& v: arr) + fnc(v); + return *this; + } + + template + Deserializer& array(std::array &arr) { + procContainer(arr); + return *this; + } + + template + Deserializer& array(std::array &arr) { + procContainer>(arr); + return *this; + } + + //c-style array overloads + + template + Deserializer& array(T (&arr)[N], Fnc&& fnc) { + T* tmp = arr; + for (auto i = 0u; i < N; ++i, ++tmp) + fnc(*tmp); + return *this; + } + + template + Deserializer& array(T (&arr)[N]) { + procCArray(arr); + return *this; + } + + template + Deserializer& array(T (&arr)[N]) { + procCArray>(arr); + return *this; + } + + private: + Reader& _reader; + void readLength(size_t& size) { + size = {}; + _reader.readBits(size, 32); + } + template + void procContainer(T&& obj) { + //todo could be improved for arithmetic types in contiguous containers (std::vector, std::array) (keep in mind std::vector specialization) + for (auto& v: obj) + ProcessAnyType::serialize(*this, v); + }; + + template + void procCArray(T (&arr)[N]) { + //todo could be improved for arithmetic types + T* end = arr + N; + for (T* it = arr; it != end; ++it) + ProcessAnyType::serialize(*this, *it); + }; -private: - Reader& _reader; - void readLength(size_t& size) { - size = {}; - _reader.readBits(size, 32); - } - template - void procContainer(T&& obj) { - //todo could be improved for arithmetic types in contiguous containers (std::vector, std::array) (keep in mind std::vector specialization) - for (auto& v: obj) - ProcessAnyType::serialize(*this, v); }; - template - void procCArray(T (&arr)[N]) { - //todo could be improved for arithmetic types - T* end = arr + N; - for (T* it = arr; it != end; ++it) - ProcessAnyType::serialize(*this, *it); - }; - -}; - -/* - * functions for range - */ -template::value>::type* = nullptr> -void setRangeValue(T& v, const RangeSpec& r) { - v += r.min; -}; - -template::value>::type* = nullptr> -void setRangeValue(T& v, const RangeSpec& r) { - using VT = std::underlying_type_t; - reinterpret_cast(v) += static_cast(r.min); -}; - -template::value>::type* = nullptr> -void setRangeValue(T& v, const RangeSpec& r) { - using UIT = SAME_SIZE_UNSIGNED; - const auto intRep = reinterpret_cast(v); - const UIT maxUint = (static_cast(1) << r.bitsRequired) - 1; - v = r.min + (static_cast(intRep) / maxUint) * (r.max - r.min); -}; - +} #endif //TMP_DESERIALIZER_H diff --git a/include/Serializer.h b/include/Serializer.h index 38ae1f0..be3c84b 100644 --- a/include/Serializer.h +++ b/include/Serializer.h @@ -8,234 +8,263 @@ #include "Common.h" #include -template -class Serializer { -public: - Serializer(Writter& w):_writter{w} {}; - - template - Serializer& object(const T& obj) { - return serialize(*this, obj); - } - - /* - * value overloads - */ - - template::value>::type* = nullptr> - Serializer& value(const T& v) { - static_assert(std::numeric_limits::is_iec559, ""); - static_assert(std::numeric_limits::is_iec559, ""); - - constexpr size_t ValueSize = VSIZE == 0 ? sizeof(T) : VSIZE; - _writter.template writeBytes(reinterpret_cast&>(v)); - return *this; - } - - template::value>::type* = nullptr> - Serializer& value(const T& v) { - constexpr size_t ValueSize = VSIZE == 0 ? sizeof(T) : VSIZE; - _writter.template writeBytes(reinterpret_cast&>(v)); - return *this; - } - - template::value>::type* = nullptr> - Serializer& value(const T& v) { - constexpr size_t ValueSize = VSIZE == 0 ? sizeof(T) : VSIZE; - _writter.template writeBytes(v); - return *this; - } - - /* - * range - */ - - template - Serializer& range(const T& v, const RangeSpec& range) { - assert(isRangeValid(v, range)); - _writter.template writeBits(getRangeValue(v,range), range.bitsRequired); - return *this; - } - - /* - * default overloads - */ - template - Serializer& defaultV(const T& v, const std::array& defValues) { - auto index = findDefault(v, defValues); - _writter.template writeBits(index, calcRequiredBits({}, N + 1)); - if (!index) - ProcessAnyType::serialize(*this, v); - }; - - /* - * text overloads - */ - - template - Serializer& text(const std::basic_string& str) { - procText(str.data(), str.size()); - return *this; - } - - template - Serializer& text(const T (&str)[N]) { - procText(str, std::min(std::char_traits::length(str), N-1)); - return *this; - } - - /* - * container overloads - */ - - template - Serializer& container(const T& obj, Fnc&& fnc) { - writeLength(obj.size()); - for (auto& v: obj) - fnc(v); - return *this; - } - - template - Serializer& container(const T& obj) { - writeLength(obj.size()); - procContainer(obj); - return *this; - } - - template - Serializer& container(const T& obj) { - writeLength(obj.size()); - procContainer>(obj); - return *this; - } - - /* - * array overloads (fixed size array (std::array, and c-style array)) - */ - - //std::array overloads - - template - Serializer & array(const std::array &arr, Fnc&& fnc) { - for (auto& v: arr) - fnc(v); - return *this; - } - - template - Serializer & array(const std::array &arr) { - procContainer(arr); - return *this; - } - - template - Serializer & array(const std::array &arr) { - procContainer>(arr); - return *this; - } - - //c-style array overloads - - template - Serializer& array(const T (&arr)[N], Fnc&& fnc) { - const T* end = arr + N; - for (const T* tmp = arr; tmp != end; ++tmp) - fnc(*tmp); - return *this; - } - - template - Serializer& array(const T (&arr)[N]) { - procCArray(arr); - return *this; - } - - template - Serializer& array(const T (&arr)[N]) { - procCArray>(arr); - return *this; - } - - -private: - Writter& _writter; - void writeLength(const size_t size) { - _writter.writeBits(size, 32); - } - - template - void procContainer(T&& obj) { - //todo could be improved for arithmetic types in contiguous containers (std::vector, std::array) (keep in mind std::vector specialization) - for (auto& v: obj) - ProcessAnyType::serialize(*this, v); - }; - - template - void procCArray(T (&arr)[N]) { - //todo could be improved for arithmetic types - const T* end = arr + N; - for (const T* it = arr; it != end; ++it) - ProcessAnyType::serialize(*this, *it); - }; - - template - void procText(const T* str, size_t size) { - writeLength(size); - if (size) - _writter.template writeBuffer(str, size); - } -}; +namespace bitsery { /* * functions for range */ -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) { + 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)); -} + 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)); + } -template::value>::type* = nullptr> -auto getRangeValue(const T& v, const RangeSpec& r) { - return static_cast>(v - r.min); -}; + template::value>::type * = nullptr> + auto getRangeValue(const T &v, const RangeSpec &r) { + return static_cast>(v - r.min); + }; -template::value>::type* = nullptr> -auto getRangeValue(const T& v, const RangeSpec& r) { - return static_cast>(v) - static_cast>(r.min); -}; + template::value>::type * = nullptr> + auto getRangeValue(const T &v, const RangeSpec &r) { + return static_cast>(v) - static_cast>(r.min); + }; -template::value>::type* = nullptr> -auto getRangeValue(const T& v, const RangeSpec& r) { - using VT = SAME_SIZE_UNSIGNED; - const VT maxUint = (static_cast(1) << r.bitsRequired) - 1; - const auto ratio = (v - r.min) / (r.max - r.min); - return static_cast(ratio * maxUint); -}; + template::value>::type * = nullptr> + auto getRangeValue(const T &v, const RangeSpec &r) { + using VT = SAME_SIZE_UNSIGNED; + const VT maxUint = (static_cast(1) << r.bitsRequired) - 1; + const auto ratio = (v - r.min) / (r.max - r.min); + return static_cast(ratio * maxUint); + }; /* - * functions for default + * functions for substitution */ -template -size_t findDefault(const T& v, const std::array& defValues) { - auto index{1u}; - for (auto& d:defValues) { - if (d == v) - return index; - ++index; - } - return 0u; -}; + template + size_t findSubstitutionIndex(const T &v, const std::array &defValues) { + auto index{1u}; + for (auto &d:defValues) { + if (d == v) + return index; + ++index; + } + return 0u; + }; + + + template + class Serializer { + public: + Serializer(Writter &w) : _writter{w} {}; + + template + Serializer& object(const T &obj) { + return serialize(*this, obj); + } + + /* + * value overloads + */ + + template::value>::type * = nullptr> + Serializer& value(const T &v) { + static_assert(std::numeric_limits::is_iec559, ""); + static_assert(std::numeric_limits::is_iec559, ""); + + constexpr size_t ValueSize = VSIZE == 0 ? sizeof(T) : VSIZE; + _writter.template writeBytes(reinterpret_cast &>(v)); + return *this; + } + + template::value>::type * = nullptr> + Serializer& value(const T &v) { + constexpr size_t ValueSize = VSIZE == 0 ? sizeof(T) : VSIZE; + _writter.template writeBytes(reinterpret_cast &>(v)); + return *this; + } + + template::value>::type * = nullptr> + Serializer& value(const T &v) { + constexpr size_t ValueSize = VSIZE == 0 ? sizeof(T) : VSIZE; + _writter.template writeBytes(v); + return *this; + } + + /* + * range + */ + + template + Serializer& range(const T &v, const RangeSpec &range) { + assert(isRangeValid(v, range)); + _writter.template writeBits(getRangeValue(v, range), range.bitsRequired); + return *this; + } + + /* + * substitution overloads + */ + template + Serializer& substitution(const T &v, const std::array &expectedValues, Fnc &&fnc) { + auto index = findSubstitutionIndex(v, expectedValues); + range(index, {{}, N +1}); + if (!index) + fnc(v); + return *this; + }; + + template + Serializer& substitution(const T &v, const std::array &expectedValues) { + auto index = findSubstitutionIndex(v, expectedValues); + range(index, {{}, N +1}); + if (!index) + ProcessAnyType::serialize(*this, v); + return *this; + }; + + template + Serializer& substitution(const T &v, const std::array &expectedValues) { + auto index = findSubstitutionIndex(v, expectedValues); + range(index, {{}, N +1}); + if (!index) + ProcessAnyType>::serialize(*this, v); + return *this; + }; + + /* + * text overloads + */ + + template + Serializer& text(const std::basic_string &str, size_t maxSize) { + assert(str.size() <= maxSize); + procText(str.data(), str.size()); + return *this; + } + + template + Serializer& text(const T (&str)[N]) { + procText(str, std::min(std::char_traits::length(str), N - 1)); + return *this; + } + + /* + * container overloads + */ + + template + Serializer& container(const T &obj, Fnc &&fnc, size_t maxSize) { + assert(obj.size() <= maxSize); + writeLength(obj.size()); + for (auto &v: obj) + fnc(v); + return *this; + } + + template + Serializer& container(const T &obj, size_t maxSize) { + assert(obj.size() <= maxSize); + writeLength(obj.size()); + procContainer(obj); + return *this; + } + + template + Serializer& container(const T &obj, size_t maxSize) { + assert(obj.size() <= maxSize); + writeLength(obj.size()); + procContainer>(obj); + return *this; + } + + /* + * array overloads (fixed size array (std::array, and c-style array)) + */ + + //std::array overloads + + template + Serializer& array(const std::array &arr, Fnc &&fnc) { + for (auto &v: arr) + fnc(v); + return *this; + } + + template + Serializer& array(const std::array &arr) { + procContainer(arr); + return *this; + } + + template + Serializer& array(const std::array &arr) { + procContainer>(arr); + return *this; + } + + //c-style array overloads + + template + Serializer& array(const T (&arr)[N], Fnc &&fnc) { + const T *end = arr + N; + for (const T *tmp = arr; tmp != end; ++tmp) + fnc(*tmp); + return *this; + } + + template + Serializer& array(const T (&arr)[N]) { + procCArray(arr); + return *this; + } + + template + Serializer& array(const T (&arr)[N]) { + procCArray>(arr); + return *this; + } + + + private: + Writter &_writter; + + void writeLength(const size_t size) { + _writter.writeBits(size, 32); + } + + template + void procContainer(T &&obj) { + //todo could be improved for arithmetic types in contiguous containers (std::vector, std::array) (keep in mind std::vector specialization) + for (auto &v: obj) + ProcessAnyType::serialize(*this, v); + }; + + template + void procCArray(T (&arr)[N]) { + //todo could be improved for arithmetic types + const T *end = arr + N; + for (const T *it = arr; it != end; ++it) + ProcessAnyType::serialize(*this, *it); + }; + + template + void procText(const T *str, size_t size) { + writeLength(size); + if (size) + _writter.template writeBuffer(str, size); + } + }; + +} #endif //TMP_SERIALIZER_H diff --git a/tests/BufferBitsOpTests.cpp b/tests/BufferBitsOpTests.cpp index 9ee4ca3..33cb9d5 100644 --- a/tests/BufferBitsOpTests.cpp +++ b/tests/BufferBitsOpTests.cpp @@ -4,13 +4,13 @@ #include #include "BufferWriter.h" #include "BufferReader.h" - -using testing::Eq; -using testing::ContainerEq; - #include #include +using testing::Eq; +using testing::ContainerEq; +using bitsery::BufferWriter; +using bitsery::BufferReader; struct IntegralUnsignedTypes { uint32_t a; diff --git a/tests/BufferBytesOpTests.cpp b/tests/BufferBytesOpTests.cpp index 6238042..785f861 100644 --- a/tests/BufferBytesOpTests.cpp +++ b/tests/BufferBytesOpTests.cpp @@ -4,12 +4,13 @@ #include #include "BufferWriter.h" #include "BufferReader.h" +#include +#include using testing::Eq; using testing::ContainerEq; - -#include -#include +using bitsery::BufferWriter; +using bitsery::BufferReader; struct IntegralTypes { int64_t a; diff --git a/tests/SerializationContainerTests.cpp b/tests/SerializationContainerTests.cpp index dd73fa2..e4b921a 100644 --- a/tests/SerializationContainerTests.cpp +++ b/tests/SerializationContainerTests.cpp @@ -41,8 +41,8 @@ TYPED_TEST_CASE(SerializeContainerArthmeticTypes, SequenceContainersWithArthmeti TYPED_TEST(SerializeContainerArthmeticTypes, Values) { SerializationContext ctx{}; - ctx.createSerializer().container(this->src); - ctx.createDeserializer().container(this->res); + ctx.createSerializer().container(this->src, 1000); + ctx.createDeserializer().container(this->res, 1000); EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx))); EXPECT_THAT(this->res, ContainerEq(this->src)); @@ -52,8 +52,8 @@ TYPED_TEST(SerializeContainerArthmeticTypes, ValuesWithExplicitSize) { SerializationContext ctx{}; using TValue = typename TestFixture::TValue; - ctx.createSerializer().container(this->src); - ctx.createDeserializer().container(this->res); + ctx.createSerializer().container(this->src, 1000); + ctx.createDeserializer().container(this->res, 1000); EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx))); EXPECT_THAT(this->res, ContainerEq(this->src)); @@ -67,13 +67,13 @@ TYPED_TEST(SerializeContainerArthmeticTypes, CustomFunctionIncrements) { //increment by 1 before writing v++; ser.value(v); - }); + }, 1000); auto des = ctx.createDeserializer(); des.container(this->res, [&des](auto&v ) { des.value(v); //increment by 1 after reading v++; - }); + }, 1000); //decrement result by 2, before comparing for eq for(auto& v:this->res) v -= 2; @@ -128,8 +128,8 @@ TYPED_TEST_CASE(SerializeContainerCompositeTypes, SequenceContainersWithComposit TYPED_TEST(SerializeContainerCompositeTypes, DefaultSerializeFunction) { SerializationContext ctx{}; - ctx.createSerializer().container(this->src); - ctx.createDeserializer().container(this->res); + ctx.createSerializer().container(this->src, 1000); + ctx.createDeserializer().container(this->res, 1000); EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx))); EXPECT_THAT(this->res, ContainerEq(this->src)); @@ -140,8 +140,8 @@ TYPED_TEST(SerializeContainerCompositeTypes, CustomFunctionThatDoNothing) { SerializationContext ctx{}; auto emptyFnc = [](auto v) {}; - ctx.createSerializer().container(this->src, emptyFnc); - ctx.createDeserializer().container(this->res, emptyFnc); + ctx.createSerializer().container(this->src, emptyFnc, 1000); + ctx.createDeserializer().container(this->res, emptyFnc, 1000); EXPECT_THAT(ctx.getBufferSize(), Eq(ctx.containerSizeSerializedBytesCount(this->src.size()))); } diff --git a/tests/SerializationRangeTests.cpp b/tests/SerializationRangeTests.cpp index c589193..bf781fd 100644 --- a/tests/SerializationRangeTests.cpp +++ b/tests/SerializationRangeTests.cpp @@ -5,6 +5,8 @@ #include #include "SerializationTestUtils.h" using namespace testing; +using bitsery::RangeSpec; +using bitsery::BitsConstraint; TEST(SerializeRange, RequiredBitsIsConstexpr) { constexpr RangeSpec r1{0, 31}; @@ -112,7 +114,7 @@ TEST(SerializeRange, FloatUsingBitsSizeConstraint1) { ctx.createDeserializer().range(res1, r1); EXPECT_THAT(ctx.getBufferSize(), Eq(1)); - EXPECT_THAT(res1, ::testing::FloatNear(t1, (max - min) / (static_cast>(1) << bits))); + EXPECT_THAT(res1, ::testing::FloatNear(t1, (max - min) / (static_cast>(1) << bits))); } TEST(SerializeRange, DoubleUsingBitsSizeConstraint2) { @@ -129,5 +131,5 @@ TEST(SerializeRange, DoubleUsingBitsSizeConstraint2) { ctx.createDeserializer().range(res1, r1); EXPECT_THAT(ctx.getBufferSize(), Eq(7)); - EXPECT_THAT(res1, ::testing::DoubleNear(t1, (max - min) / (static_cast>(1) << bits))); + EXPECT_THAT(res1, ::testing::DoubleNear(t1, (max - min) / (static_cast>(1) << bits))); } diff --git a/tests/SerializationSubstitutionTests.cpp b/tests/SerializationSubstitutionTests.cpp new file mode 100644 index 0000000..9d22027 --- /dev/null +++ b/tests/SerializationSubstitutionTests.cpp @@ -0,0 +1,143 @@ +// +// Created by fraillt on 17.2.20. +// + +#include +#include "SerializationTestUtils.h" +using namespace testing; + +TEST(SerializeSubstitution, WhenSubstitutedThenOnlyWriteIndexUsingMinRequiredBits) { + int v = 4849; + int res; + constexpr size_t N = 3; + std::array subsitution{485,4849,89}; + SerializationContext ctx; + ctx.createSerializer().substitution(v, subsitution); + ctx.createDeserializer().substitution(res, subsitution); + + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); + + SerializationContext ctx1; + ctx1.createSerializer().substitution(v, subsitution); + auto des = ctx1.createDeserializer(); + des.range(res, {0, N + 1}); + EXPECT_THAT(res, Eq(2)); +} + +TEST(SerializeSubstitution, WhenNoSubstitutionThenWriteZeroBitsAndValueOrObject) { + int v = 8945; + int res; + std::array subsitution{485,4849,89}; + SerializationContext ctx; + ctx.createSerializer().substitution(v, subsitution); + ctx.createDeserializer().substitution(res, subsitution); + + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq(sizeof(int)+1)); +} + +TEST(SerializeSubstitution, CustomTypeSubstituted) { + MyStruct1 v = {12,10}; + MyStruct1 res; + constexpr size_t N = 4; + std::array subsitution = { + MyStruct1{12,10}, MyStruct1{485, 454}, + MyStruct1{4849,89}, MyStruct1{0,1}}; + SerializationContext ctx; + ctx.createSerializer().substitution(v, subsitution); + ctx.createDeserializer().substitution(res, subsitution); + + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); +} + +TEST(SerializeSubstitution, CustomTypeNotSubstituted) { + MyStruct1 v = {8945,4456}; + MyStruct1 res; + constexpr size_t N = 4; + std::array subsitution = { + MyStruct1{12,10}, MyStruct1{485, 454}, + MyStruct1{4849,89}, MyStruct1{0,1}}; + SerializationContext ctx; + ctx.createSerializer().substitution(v, subsitution); + ctx.createDeserializer().substitution(res, subsitution); + + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq(MyStruct1::SIZE + 1)); +} + +TEST(SerializeSubstitution, ArithmeticTypeWithExplicitSizeNotSubstituted) { + MyEnumClass v = MyEnumClass::E5; + MyEnumClass res; + constexpr size_t N = 3; + std::array subsitution{MyEnumClass::E1,MyEnumClass::E2,MyEnumClass::E3}; + SerializationContext ctx; + ctx.createSerializer().substitution(v, subsitution); + ctx.createDeserializer().substitution(res, subsitution); + + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq(sizeof(MyEnumClass) + 1)); +} + +TEST(SerializeSubstitution, ArithmeticTypeWithExplicitSizeSubstituted) { + MyEnumClass v = MyEnumClass::E1; + MyEnumClass res; + constexpr size_t N = 3; + std::array subsitution{MyEnumClass::E1,MyEnumClass::E2,MyEnumClass::E3}; + SerializationContext ctx; + ctx.createSerializer().substitution(v, subsitution); + ctx.createDeserializer().substitution(res, subsitution); + + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); +} + + +TEST(SerializeSubstitution, CustomFunctionNotSubstituted) { + MyStruct1 v = {8945,4456}; + MyStruct1 res; + constexpr size_t N = 4; + std::array subsitution = { + MyStruct1{12,10}, MyStruct1{485, 454}, + MyStruct1{4849,89}, MyStruct1{0,1}}; + + auto rangeForValue = bitsery::RangeSpec(0, 10000); + auto rangeForIndex = bitsery::RangeSpec{0, N+1}; + + SerializationContext ctx; + auto ser = ctx.createSerializer(); + + //lambdas differ only in capture clauses, it would make sense to use std::bind, but debugger crashes when it sees std::bind... + auto serLambda = [&ser, rangeForValue](const MyStruct1& v) { + ser.range(v.i1, rangeForValue); + ser.range(v.i2, rangeForValue); + }; + ser.substitution(v, subsitution, serLambda); + + auto des = ctx.createDeserializer(); + auto desLambda = [&des, rangeForValue](MyStruct1& v) { + des.range(v.i1, rangeForValue); + des.range(v.i2, rangeForValue); + }; + des.substitution(res, subsitution, desLambda); + + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq((rangeForIndex.bitsRequired + rangeForValue.bitsRequired * 2 - 1) / 8 + 1 )); +} + +TEST(SerializeSubstitution, WhenSubstitutedThenCustomFunctionNotInvoked) { + MyStruct1 v = {4849,89}; + MyStruct1 res; + constexpr size_t N = 4; + std::array subsitution = { + MyStruct1{12,10}, MyStruct1{485, 454}, + MyStruct1{4849,89}, MyStruct1{0,1}}; + + SerializationContext ctx; + ctx.createSerializer().substitution(v, subsitution, [](const MyStruct1& ) {}); + ctx.createDeserializer().substitution(res, subsitution, [](MyStruct1& ) {}); + + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); +} diff --git a/tests/SerializationTestUtils.h b/tests/SerializationTestUtils.h index b44c913..7a157e7 100644 --- a/tests/SerializationTestUtils.h +++ b/tests/SerializationTestUtils.h @@ -56,11 +56,11 @@ SERIALIZE(MyStruct2) { class SerializationContext { std::vector buf{}; - std::unique_ptr bw; - std::unique_ptr br; + std::unique_ptr bw; + std::unique_ptr br; public: - Serializer createSerializer() { - bw = std::make_unique(buf); + bitsery::Serializer createSerializer() { + bw = std::make_unique(buf); return {*bw}; }; @@ -73,9 +73,9 @@ public: return 4; } - Deserializer createDeserializer() { + bitsery::Deserializer createDeserializer() { bw->flush(); - br = std::make_unique(buf); + br = std::make_unique(buf); return {*br}; }; }; diff --git a/tests/SerializationTextTests.cpp b/tests/SerializationTextTests.cpp index b991181..f283659 100644 --- a/tests/SerializationTextTests.cpp +++ b/tests/SerializationTextTests.cpp @@ -11,8 +11,8 @@ TEST(SerializeText, BasicString) { std::string t1 = "some random text"; std::string res; - ctx.createSerializer().text(t1); - ctx.createDeserializer().text(res); + ctx.createSerializer().text(t1, 1000); + ctx.createDeserializer().text(res, 1000); EXPECT_THAT(res, StrEq(t1)); EXPECT_THAT(res, ContainerEq(t1)); @@ -26,8 +26,8 @@ TEST(SerializeText, WhenSizeOfTypeNotEqualsOneThenSetSizeExplicitly) { std::basic_string res; static_assert(VSIZE > 1, "on this system, all character types has sizeof == 1, cannot run this tests"); - ctx.createSerializer().text(t1); - ctx.createDeserializer().text(res); + ctx.createSerializer().text(t1, 1000); + ctx.createDeserializer().text(res, 1000); EXPECT_THAT(res, ContainerEq(t1)); } @@ -38,8 +38,8 @@ TEST(SerializeText, BasicStringUseSizeMethodNotNullterminatedLength) { std::wstring wres; constexpr auto VSIZE = sizeof(std::wstring::value_type); - ctx.createSerializer().text(t1); - ctx.createDeserializer().text(wres); + ctx.createSerializer().text(t1, 1000); + ctx.createDeserializer().text(wres, 1000); EXPECT_THAT(wres, StrEq(t1)); EXPECT_THAT(wres.size(), Eq(t1.size())); @@ -48,16 +48,16 @@ TEST(SerializeText, BasicStringUseSizeMethodNotNullterminatedLength) { SerializationContext ctx2; std::string t2("\0no one cares what is there", 10); std::string res; - ctx2.createSerializer().text(t2); - ctx2.createDeserializer().text(res); + ctx2.createSerializer().text(t2, 1000); + ctx2.createDeserializer().text(res, 1000); EXPECT_THAT(res, StrEq(t2)); EXPECT_THAT(res.size(), Eq(t2.size())); SerializationContext ctx3; std::string t3("never ending buffer that doesnt fit in this string", 10); - ctx3.createSerializer().text(t3); - ctx3.createDeserializer().text(res); + ctx3.createSerializer().text(t3, 1000); + ctx3.createDeserializer().text(res, 1000); EXPECT_THAT(res, StrEq(t3)); EXPECT_THAT(res.size(), Eq(10)); } diff --git a/tests/SerializerObjectsTests.cpp b/tests/SerializerObjectsTests.cpp index 067145f..7fcc973 100644 --- a/tests/SerializerObjectsTests.cpp +++ b/tests/SerializerObjectsTests.cpp @@ -45,17 +45,17 @@ SERIALIZE(Z) SERIALIZE(X) { return s.value(o.x) - .text(o.s); + .text(o.s, 1000); } SERIALIZE(Y) { auto writeInt = [&s](auto& v) { s.template value<4>(v); }; - s.text(o.s); + s.text(o.s, 10000); s.template value<4>(o.y); s.array(o.arr, writeInt); s.array(o.carr, writeInt); - s.container(o.vx, [&s](auto& v) { s.object(v); }); + s.container(o.vx, [&s](auto& v) { s.object(v); }, 10000); return s; } @@ -136,13 +136,13 @@ TEST(DeltaSerializer, GeneralConceptTest) { yNew.vx.push_back(X{ 3 }); std::vector buf; - BufferWriter bw{ buf }; - DeltaSerializer ser(bw, y, yNew); + bitsery::BufferWriter bw{ buf }; + bitsery::DeltaSerializer ser(bw, y, yNew); serialize(ser, yNew); bw.flush(); - - BufferReader br{ buf }; - DeltaDeserializer des(br, y, yRead); + + bitsery::BufferReader br{ buf }; + bitsery::DeltaDeserializer des(br, y, yRead); serialize(des, yRead); EXPECT_THAT(yRead.y, Eq(yNew.y)); diff --git a/tests/SerializerValuesTests.cpp b/tests/SerializerValuesTests.cpp index 4153ef3..dd4e1d8 100644 --- a/tests/SerializerValuesTests.cpp +++ b/tests/SerializerValuesTests.cpp @@ -43,20 +43,14 @@ TEST(SerializeValues, FloatingPointTypes) { TEST(SerializeValues, ExplicitTypeSize) { int v{23472}; - constexpr size_t TSIZE = sizeof(v); - std::vector buf{}; - - BufferWriter bw{buf}; - Serializer ser(bw); - ser.value(v); - bw.flush(); - - BufferReader br{buf}; - Deserializer des(br); int res; - des.value(res); + constexpr size_t TSIZE = sizeof(v); + + SerializationContext ctx; + ctx.createSerializer().value(v); + ctx.createDeserializer().value(res); EXPECT_THAT(res, Eq(v)); - EXPECT_THAT(TSIZE, Eq(buf.size())); + EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize())); }