diff --git a/CMakeLists.txt b/CMakeLists.txt index bc1d7a8..b1c1c70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,8 +12,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/ext) if(CMAKE_COMPILER_IS_GNUCXX) - include(CodeCoverage) - setup_target_for_coverage(${PROJECT_NAME}_coverage ${TEST_PROJECT_NAME} coverage) + #include(CodeCoverage) + #setup_target_for_coverage(${PROJECT_NAME}_coverage ${TEST_PROJECT_NAME} coverage) endif() add_subdirectory(examples) diff --git a/include/bitsery/deserializer.h b/include/bitsery/deserializer.h index 55c95fa..fcf8358 100644 --- a/include/bitsery/deserializer.h +++ b/include/bitsery/deserializer.h @@ -1,357 +1,431 @@ -//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_DESERIALIZER_H -#define BITSERY_DESERIALIZER_H - -#include "common.h" -#include -#include - -namespace bitsery { - - /* - * 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); - }; - - - template - class Deserializer { - public: - Deserializer(Reader& r):_reader{r}, _isValid{true} {}; - - template - Deserializer& object(T&& obj) { - return serialize(*this, std::forward(obj)); - } - - /* - * value overloads - */ - - template::value>::type* = nullptr> - Deserializer& value(T& v) { - static_assert(std::numeric_limits::is_iec559, ""); - static_assert(std::numeric_limits::is_iec559, ""); - if (_isValid) { - constexpr size_t ValueSize = VSIZE == 0 ? sizeof(T) : VSIZE; - _isValid = _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; - if (_isValid) { - _isValid = _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; - if (_isValid) { - _isValid = _reader.template readBytes(v); - } - return *this; - } - - /* - * bool - */ - - Deserializer& boolBit(bool& v) { - if (_isValid) { - unsigned char tmp; - _isValid = _reader.readBits(tmp, 1); - v = tmp == 1; - } - return *this; - } - - Deserializer& boolByte(bool& v) { - if (_isValid) { - unsigned char tmp; - _isValid = _reader.template readBytes<1>(tmp); - if (_isValid) - _isValid = tmp < 2; - v = tmp == 1; - } - return *this; - } - - /* - * range - */ - - template - Deserializer& range(T& v, const RangeSpec& range) { - if (_isValid) { - _isValid = _reader.template readBits(reinterpret_cast&>(v), range.bitsRequired); - setRangeValue(v, range); - if (_isValid) - _isValid = isRangeValid(v, range); - } - return *this; - } - - /* - * substitution overloads - */ - template - Deserializer& substitution(T& v, const std::array& expectedValues, Fnc&& fnc) { - size_t index; - range(index, {{}, N + 1}); - if (_isValid) { - if (index) - v = expectedValues[index-1]; - else - fnc(v); - } - return *this; - }; - - template - Deserializer& substitution(T& v, const std::array& expectedValues) { - size_t index; - range(index, {{}, N + 1}); - if (_isValid) { - if (index) - v = expectedValues[index-1]; - else - ProcessAnyType::serialize(*this, v); - } - return *this; - }; - - template - Deserializer& substitution(T& v, const std::array& expectedValues) { - size_t index; - range(index, {{}, N + 1}); - if (_isValid) { - if (index) - v = expectedValues[index-1]; - else - ProcessAnyType>::serialize(*this, v); - } - return *this; - }; - - /* - * text overloads - */ - - template - Deserializer& text(std::basic_string& str, size_t maxSize) { - size_t size; - readSize(size, maxSize); - if (_isValid) { - str.resize(size); - if (size) { - //if (std::is_const>().data())>::value) { - std::vector buf(size); - _isValid = _reader.template readBuffer(buf.data(), size); - str.assign(buf.data(), size); - //} else { - //_isValid = _reader.template readBuffer(str.data(), size); - //} - } - } - return *this; - } - - template - Deserializer& text(T (&str)[N]) { - size_t size; - readSize(size, N-1); - if (_isValid) { - _isValid = _reader.template readBuffer(str, size); - str[size] = {}; - } - return *this; - } - - /* - * container overloads - */ - - template - Deserializer& container(T&& obj, Fnc&& fnc, size_t maxSize) { - decltype(obj.size()) size{}; - readSize(size, maxSize); - if (_isValid) { - obj.resize(size); - for (auto& v:obj) { - if (_isValid) - fnc(v); - } - - } - return *this; - } - - template - Deserializer& container(T& obj, size_t maxSize) { - decltype(obj.size()) size{}; - readSize(size, maxSize); - if (_isValid) { - obj.resize(size); - procContainer(obj); - } - return *this; - } - - template - Deserializer& container(T& obj, size_t maxSize) { - decltype(obj.size()) size{}; - readSize(size, maxSize); - if (_isValid) { - 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) - if (_isValid) - 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) - if (_isValid) - fnc(*tmp); - return *this; - } - - template - Deserializer& array(T (&arr)[N]) { - procCArray(arr); - return *this; - } - - template - Deserializer& array(T (&arr)[N]) { - procCArray>(arr); - return *this; - } - bool isValid() const { - return _isValid; - } - - private: - Reader& _reader; - bool _isValid; - void readSize(size_t &size, size_t maxSize) { - size = {}; - if (_isValid) { - unsigned char firstBit; - _isValid = _reader.readBits(firstBit, 1); - if (_isValid) { - if (firstBit) { - _isValid = _reader.readBits(size, 7); - } else { - unsigned char secondBit; - _isValid = _reader.readBits(secondBit, 1); - if (_isValid) { - if (secondBit) { - _isValid = _reader.readBits(size,14); - } else { - _isValid = _reader.readBits(size,30); - } - } - } - } - if (_isValid) - _isValid = size <= maxSize; - } - } - 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) - if (_isValid) - 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) - if (_isValid) - ProcessAnyType::serialize(*this, *it); - }; - - }; - - -} - -#endif //BITSERY_DESERIALIZER_H +//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_DESERIALIZER_H +#define BITSERY_DESERIALIZER_H + +#include "common.h" +#include +#include + +namespace bitsery { + + /* + * 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); + }; + + + template + class Deserializer { + public: + Deserializer(Reader& r):_reader{r}, _isValid{true} {}; + + template + Deserializer& object(T&& obj) { + return serialize(*this, std::forward(obj)); + } + + /* + * value overloads + */ + + template::value>::type* = nullptr> + Deserializer& value(T& v) { + static_assert(std::numeric_limits::is_iec559, ""); + if (_isValid) { + _isValid = _reader.template readBytes(reinterpret_cast&>(v)); + } + return *this; + } + + template::value>::type* = nullptr> + Deserializer& value(T& v) { + using UT = std::underlying_type_t; + if (_isValid) { + _isValid = _reader.template readBytes(reinterpret_cast(v)); + } + return *this; + } + + template::value>::type* = nullptr> + Deserializer& value(T& v) { + if (_isValid) { + _isValid = _reader.template readBytes(v); + } + return *this; + } + + /* + * bool + */ + + Deserializer& boolBit(bool& v) { + if (_isValid) { + unsigned char tmp; + _isValid = _reader.readBits(tmp, 1); + v = tmp == 1; + } + return *this; + } + + Deserializer& boolByte(bool& v) { + if (_isValid) { + unsigned char tmp; + _isValid = _reader.template readBytes<1>(tmp); + if (_isValid) + _isValid = tmp < 2; + v = tmp == 1; + } + return *this; + } + + /* + * range + */ + + template + Deserializer& range(T& v, const RangeSpec& range) { + if (_isValid) { + _isValid = _reader.template readBits(reinterpret_cast&>(v), range.bitsRequired); + setRangeValue(v, range); + if (_isValid) + _isValid = isRangeValid(v, range); + } + return *this; + } + + /* + * substitution overloads + */ + template + Deserializer& substitution(T& v, const std::array& expectedValues, Fnc&& fnc) { + size_t index; + range(index, {{}, N + 1}); + if (_isValid) { + if (index) + v = expectedValues[index-1]; + else + fnc(v); + } + return *this; + }; + + template + Deserializer& substitution(T& v, const std::array& expectedValues) { + size_t index; + range(index, {{}, N + 1}); + if (_isValid) { + if (index) + v = expectedValues[index-1]; + else + value(v); + } + return *this; + }; + + template + Deserializer& substitution(T& v, const std::array& expectedValues) { + size_t index; + range(index, {{}, N + 1}); + if (_isValid) { + if (index) + v = expectedValues[index-1]; + else + object(v); + } + return *this; + }; + + /* + * text overloads + */ + + template + Deserializer& text(std::basic_string& str, size_t maxSize) { + size_t size; + readSize(size, maxSize); + if (_isValid) { + str.resize(size); + if (size) { + //if (std::is_const>().data())>::value) { + std::vector buf(size); + _isValid = _reader.template readBuffer(buf.data(), size); + str.assign(buf.data(), size); + //} else { + //_isValid = _reader.template readBuffer(str.data(), size); + //} + } + } + return *this; + } + + template + Deserializer& text(T (&str)[N]) { + size_t size; + readSize(size, N-1); + if (_isValid) { + _isValid = _reader.template readBuffer(str, size); + str[size] = {}; + } + return *this; + } + + /* + * container overloads + */ + + template + Deserializer& container(T&& obj, Fnc&& fnc, size_t maxSize) { + decltype(obj.size()) size{}; + readSize(size, maxSize); + if (_isValid) { + obj.resize(size); + for (auto& v:obj) { + if (_isValid) + fnc(v); + } + + } + return *this; + } + + template + Deserializer& container(T& obj, size_t maxSize) { + decltype(obj.size()) size{}; + readSize(size, maxSize); + if (_isValid) { + obj.resize(size); + for (auto& v: obj) { + if (_isValid) + value(v); + } + } + return *this; + } + + template + Deserializer& container(T& obj, size_t maxSize) { + decltype(obj.size()) size{}; + readSize(size, maxSize); + if (_isValid) { + obj.resize(size); + for (auto& v: obj) { + if (_isValid) + object(v); + } + } + 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) + if (_isValid) + fnc(v); + return *this; + } + + template + Deserializer& array(std::array &arr) { + for (auto& v: arr) { + if (_isValid) + value(v); + } + return *this; + } + + template + Deserializer& array(std::array &arr) { + for (auto& v: arr) { + if (_isValid) + object(v); + } + return *this; + } + + //c-style array overloads + + template + Deserializer& array(T (&arr)[N], Fnc&& fnc) { + T* end = arr + N; + for (T* it= arr; it != end; ++it) { + if (_isValid) + fnc(*it); + } + return *this; + } + + template + Deserializer& array(T (&arr)[N]) { + procCArray(arr); + return *this; + } + + template + Deserializer& array(T (&arr)[N]) { + procCArray>(arr); + return *this; + } + bool isValid() const { + return _isValid; + } + + Deserializer& align() { + _reader.align(); + return *this; + } + + //overloads for functions with explicit type size + template Deserializer& value1(T &&v) { return value<1>(std::forward(v)); } + template Deserializer& value2(T &&v) { return value<2>(std::forward(v)); } + template Deserializer& value4(T &&v) { return value<4>(std::forward(v)); } + template Deserializer& value8(T &&v) { return value<8>(std::forward(v)); } + + template Deserializer& substitution1 + (T &v, const std::array &expectedValues) { return substitution<1>(v, expectedValues); }; + template Deserializer& substitution2 + (T &v, const std::array &expectedValues) { return substitution<2>(v, expectedValues); }; + template Deserializer& substitution4 + (T &v, const std::array &expectedValues) { return substitution<4>(v, expectedValues); }; + template Deserializer& substitution8 + (T &v, const std::array &expectedValues) { return substitution<8>(v, expectedValues); }; + + template Deserializer& text1(std::basic_string &str, size_t maxSize) { + return text<1>(str, maxSize); } + template Deserializer& text2(std::basic_string &str, size_t maxSize) { + return text<2>(str, maxSize); } + template Deserializer& text4(std::basic_string &str, size_t maxSize) { + return text<4>(str, maxSize); } + + template Deserializer& text1(T (&str)[N]) { return text<1>(str); } + template Deserializer& text2(T (&str)[N]) { return text<2>(str); } + template Deserializer& text4(T (&str)[N]) { return text<4>(str); } + + template Deserializer& container1(T &&obj, size_t maxSize) { + return container<1>(std::forward(obj), maxSize); } + template Deserializer& container2(T &&obj, size_t maxSize) { + return container<2>(std::forward(obj), maxSize); } + template Deserializer& container4(T &&obj, size_t maxSize) { + return container<4>(std::forward(obj), maxSize); } + template Deserializer& container8(T &&obj, size_t maxSize) { + return container<8>(std::forward(obj), maxSize); } + + private: + Reader& _reader; + bool _isValid; + void readSize(size_t &size, size_t maxSize) { + size = {}; + if (_isValid) { + unsigned char firstBit; + _isValid = _reader.readBits(firstBit, 1); + if (_isValid) { + if (firstBit) { + _isValid = _reader.readBits(size, 7); + } else { + unsigned char secondBit; + _isValid = _reader.readBits(secondBit, 1); + if (_isValid) { + if (secondBit) { + _isValid = _reader.readBits(size,14); + } else { + _isValid = _reader.readBits(size,30); + } + } + } + } + if (_isValid) + _isValid = size <= maxSize; + } + } + + template< size_t VSIZE, typename TIterator> + void procContainerValues(TIterator begin, TIterator end) { + for (auto it = begin; it != end; ++it) { + if (_isValid) + value(*it); + } + }; + + template + void procContainerValues(TIterator begin, TIterator end) { + for (auto it = begin; it != end; ++it) { + if (_isValid) + object(*it); + } + }; + + + 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) + if (_isValid) + 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) + if (_isValid) + ProcessAnyType::serialize(*this, *it); + }; + + template + void procCont(Iterator begin, Iterator end, Fnc&& fnc) { + for (Iterator it = begin; it != end; ++it) + if (_isValid) + fnc(*it); + }; + + }; + + +} + +#endif //BITSERY_DESERIALIZER_H diff --git a/include/bitsery/serializer.h b/include/bitsery/serializer.h index 26eaa62..746f8b9 100644 --- a/include/bitsery/serializer.h +++ b/include/bitsery/serializer.h @@ -1,300 +1,335 @@ -//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_SERIALIZER_H -#define BITSERY_SERIALIZER_H - -#include "common.h" -#include - -namespace bitsery { - -/* - * functions for range - */ - - 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) { - 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 substitution - */ - - 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; - } - - /* - * bool - */ - - Serializer& boolBit(bool v) { - _writter.template writeBits(static_cast(v ? 1 : 0), 1); - return *this; - } - - Serializer& boolByte(bool v) { - _writter.template writeBytes<1>(static_cast(v ? 1 : 0)); - 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); - writeSize(obj.size()); - for (auto &v: obj) - fnc(v); - return *this; - } - - template - Serializer& container(const T &obj, size_t maxSize) { - assert(obj.size() <= maxSize); - writeSize(obj.size()); - procContainer(obj); - return *this; - } - - template - Serializer& container(const T &obj, size_t maxSize) { - assert(obj.size() <= maxSize); - writeSize(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 writeSize(const size_t size) { - if (size < 0x80u) { - _writter.writeBits(1u, 1); - _writter.writeBits(size, 7); - } else if (size < 0x4000u) { - _writter.writeBits(2u,2); - _writter.writeBits(size, 14); - } else { - assert(size < 0x40000000u); - _writter.writeBits(0u,2); - _writter.writeBits(size, 30); - } - } - - 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) { - writeSize(size); - if (size) - _writter.template writeBuffer(str, size); - } - }; - -} -#endif //BITSERY_SERIALIZER_H +//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_SERIALIZER_H +#define BITSERY_SERIALIZER_H + +#include "common.h" +#include + +namespace bitsery { + +/* + * functions for range + */ + + 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) { + 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 substitution + */ + + 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, ""); + _writter.template writeBytes(reinterpret_cast &>(v)); + return *this; + } + + template::value>::type * = nullptr> + Serializer& value(const T &v) { + _writter.template writeBytes(reinterpret_cast &>(v)); + return *this; + } + + template::value>::type * = nullptr> + Serializer& value(const T &v) { + _writter.template writeBytes(v); + return *this; + } + + /* + * bool + */ + + Serializer& boolBit(bool v) { + _writter.template writeBits(static_cast(v ? 1 : 0), 1); + return *this; + } + + Serializer& boolByte(bool v) { + _writter.template writeBytes<1>(static_cast(v ? 1 : 0)); + 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) + value(v); + return *this; + }; + + template + Serializer& substitution(const T &v, const std::array &expectedValues) { + auto index = findSubstitutionIndex(v, expectedValues); + range(index, {{}, N +1}); + if (!index) + object(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); + writeSize(obj.size()); + for (auto &v: obj) + fnc(v); + return *this; + } + + template + Serializer& container(const T &obj, size_t maxSize) { + assert(obj.size() <= maxSize); + writeSize(obj.size()); + procContainer(obj); + return *this; + } + + template + Serializer& container(const T &obj, size_t maxSize) { + assert(obj.size() <= maxSize); + writeSize(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; + } + + Serializer& align() { + _writter.align(); + return *this; + } + + //overloads for functions with explicit type size + template Serializer& value1(T &&v) { return value<1>(std::forward(v)); } + template Serializer& value2(T &&v) { return value<2>(std::forward(v)); } + template Serializer& value4(T &&v) { return value<4>(std::forward(v)); } + template Serializer& value8(T &&v) { return value<8>(std::forward(v)); } + + template Serializer& substitution1 + (const T &v, const std::array &expectedValues) { return substitution<1>(v, expectedValues); }; + template Serializer& substitution2 + (const T &v, const std::array &expectedValues) { return substitution<2>(v, expectedValues); }; + template Serializer& substitution4 + (const T &v, const std::array &expectedValues) { return substitution<4>(v, expectedValues); }; + template Serializer& substitution8 + (const T &v, const std::array &expectedValues) { return substitution<8>(v, expectedValues); }; + + template Serializer& text1(const std::basic_string &str, size_t maxSize) { + return text<1>(str, maxSize); } + template Serializer& text2(const std::basic_string &str, size_t maxSize) { + return text<2>(str, maxSize); } + template Serializer& text4(const std::basic_string &str, size_t maxSize) { + return text<4>(str, maxSize); } + + template Serializer& text1(const T (&str)[N]) { return text<1>(str); } + template Serializer& text2(const T (&str)[N]) { return text<2>(str); } + template Serializer& text4(const T (&str)[N]) { return text<4>(str); } + + template Serializer& container1(T &&obj, size_t maxSize) { + return container<1>(std::forward(obj), maxSize); } + template Serializer& container2(T &&obj, size_t maxSize) { + return container<2>(std::forward(obj), maxSize); } + template Serializer& container4(T &&obj, size_t maxSize) { + return container<4>(std::forward(obj), maxSize); } + template Serializer& container8(T &&obj, size_t maxSize) { + return container<8>(std::forward(obj), maxSize); } + + private: + Writter &_writter; + + void writeSize(const size_t size) { + if (size < 0x80u) { + _writter.writeBits(1u, 1); + _writter.writeBits(size, 7); + } else if (size < 0x4000u) { + _writter.writeBits(2u,2); + _writter.writeBits(size, 14); + } else { + assert(size < 0x40000000u); + _writter.writeBits(0u,2); + _writter.writeBits(size, 30); + } + } + + 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) { + writeSize(size); + if (size) + _writter.template writeBuffer(str, size); + } + }; + +} +#endif //BITSERY_SERIALIZER_H diff --git a/tests/serialization_container.cpp b/tests/serialization_container.cpp index 7d4e238..0598eac 100644 --- a/tests/serialization_container.cpp +++ b/tests/serialization_container.cpp @@ -1,168 +1,159 @@ -//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. - - - -#include -#include "serialization_test_utils.h" -#include -#include -#include - -using testing::ContainerEq; -using testing::Eq; - -template -Container getFilledContainer() { - return {1,2,3,4,5,78,456,8,54}; -} - -template -class SerializeContainerArthmeticTypes:public testing::Test { -public: - using TContainer = T; - using TValue = typename T::value_type; - - const TContainer src= getFilledContainer() ; - TContainer res{}; - - size_t getExpectedBufSize(const SerializationContext& ctx) const { - return ctx.containerSizeSerializedBytesCount(src.size()) + src.size() * sizeof(TValue); - } -}; -//std::forward_list is not supported, because it doesn't have size() method -using SequenceContainersWithArthmeticTypes = ::testing::Types< - std::vector, - std::list, - std::deque>; - -TYPED_TEST_CASE(SerializeContainerArthmeticTypes, SequenceContainersWithArthmeticTypes); - -TYPED_TEST(SerializeContainerArthmeticTypes, Values) { - SerializationContext ctx{}; - - 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)); -} - -TYPED_TEST(SerializeContainerArthmeticTypes, ValuesWithExplicitSize) { - SerializationContext ctx{}; - using TValue = typename TestFixture::TValue; - - 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)); -} - -TYPED_TEST(SerializeContainerArthmeticTypes, CustomFunctionIncrements) { - SerializationContext ctx{}; - - auto ser = ctx.createSerializer(); - ser.container(this->src, [&ser](auto v ) { - //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; - - EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx))); - EXPECT_THAT(this->res, ContainerEq(this->src)); -} - - - - -template -class SerializeContainerCompositeTypes:public testing::Test { -public: - using TContainer = T; - using TValue = typename T::value_type; - - const TContainer src= getFilledContainer(); - TContainer res{}; - size_t getExpectedBufSize(const SerializationContext& ctx) const { - return ctx.containerSizeSerializedBytesCount(src.size()) + src.size() * TValue::SIZE; - } -}; - -template <> -std::vector getFilledContainer>() { - return { - {0,1}, - {2,3}, - {4,5}, - {6,7}, - {8,9}, - {11,34}, - {5134,1532} - }; -} - -template <> -std::list getFilledContainer>() { - return { - {MyStruct2::V1, {0,1}} , - {MyStruct2::V3, {-45,45}} - }; -} - -using SequenceContainersWithCompositeTypes = ::testing::Types< - std::vector, - std::list>; - -TYPED_TEST_CASE(SerializeContainerCompositeTypes, SequenceContainersWithCompositeTypes); - -TYPED_TEST(SerializeContainerCompositeTypes, DefaultSerializeFunction) { - SerializationContext ctx{}; - - 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)); -} - - -TYPED_TEST(SerializeContainerCompositeTypes, CustomFunctionThatDoNothing) { - SerializationContext ctx{}; - - auto emptyFnc = [](auto v) {}; - ctx.createSerializer().container(this->src, emptyFnc, 1000); - ctx.createDeserializer().container(this->res, emptyFnc, 1000); - - EXPECT_THAT(ctx.getBufferSize(), Eq(ctx.containerSizeSerializedBytesCount(this->src.size()))); -} - - +//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. + + + +#include +#include "serialization_test_utils.h" +#include +#include +#include + +using testing::ContainerEq; +using testing::Eq; + +template +Container getFilledContainer() { + return {1,2,3,4,5,78,456,8,54}; +} + +template +class SerializeContainerArthmeticTypes:public testing::Test { +public: + using TContainer = T; + using TValue = typename T::value_type; + + const TContainer src= getFilledContainer() ; + TContainer res{}; + + size_t getExpectedBufSize(const SerializationContext& ctx) const { + return ctx.containerSizeSerializedBytesCount(src.size()) + src.size() * sizeof(TValue); + } +}; +//std::forward_list is not supported, because it doesn't have size() method +using SequenceContainersWithArthmeticTypes = ::testing::Types< + std::vector, + std::list, + std::deque>; + +TYPED_TEST_CASE(SerializeContainerArthmeticTypes, SequenceContainersWithArthmeticTypes); + +TYPED_TEST(SerializeContainerArthmeticTypes, Values) { + SerializationContext ctx{}; + using TValue = typename TestFixture::TValue; + + 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)); +} + +TYPED_TEST(SerializeContainerArthmeticTypes, CustomFunctionIncrements) { + SerializationContext ctx{}; + + auto ser = ctx.createSerializer(); + ser.container(this->src, [&ser](auto v ) { + //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; + + EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx))); + EXPECT_THAT(this->res, ContainerEq(this->src)); +} + + + + +template +class SerializeContainerCompositeTypes:public testing::Test { +public: + using TContainer = T; + using TValue = typename T::value_type; + + const TContainer src= getFilledContainer(); + TContainer res{}; + size_t getExpectedBufSize(const SerializationContext& ctx) const { + return ctx.containerSizeSerializedBytesCount(src.size()) + src.size() * TValue::SIZE; + } +}; + +template <> +std::vector getFilledContainer>() { + return { + {0,1}, + {2,3}, + {4,5}, + {6,7}, + {8,9}, + {11,34}, + {5134,1532} + }; +} + +template <> +std::list getFilledContainer>() { + return { + {MyStruct2::V1, {0,1}} , + {MyStruct2::V3, {-45,45}} + }; +} + +using SequenceContainersWithCompositeTypes = ::testing::Types< + std::vector, + std::list>; + +TYPED_TEST_CASE(SerializeContainerCompositeTypes, SequenceContainersWithCompositeTypes); + +TYPED_TEST(SerializeContainerCompositeTypes, DefaultSerializeFunction) { + SerializationContext ctx{}; + + 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)); +} + + +TYPED_TEST(SerializeContainerCompositeTypes, CustomFunctionThatDoNothing) { + SerializationContext ctx{}; + + + auto emptyFnc = [](auto v) {}; + 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/serialization_fixed_size_array.cpp b/tests/serialization_fixed_size_array.cpp index 8dddcea..8d2a82a 100644 --- a/tests/serialization_fixed_size_array.cpp +++ b/tests/serialization_fixed_size_array.cpp @@ -1,158 +1,158 @@ -//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. - - -#include -#include "serialization_test_utils.h" -#include - -using testing::ContainerEq; -using testing::Eq; - -TEST(SerializeFSArrayStdArray, ArithmeticValues) { - SerializationContext ctx; - std::array src{5,9,15,-459}; - std::array res{}; - - ctx.createSerializer().array(src); - ctx.createDeserializer().array(res); - - EXPECT_THAT(ctx.getBufferSize(), Eq(src.size() * sizeof(int))); - EXPECT_THAT(res, ContainerEq(src)); - -} - -TEST(SerializeFSArrayStdArray, ArithmeticValuesSettingValueSizeExplicitly) { - SerializationContext ctx; - std::array src{5,9,15,-459}; - std::array res{}; - - ctx.createSerializer().array(src); - ctx.createDeserializer().array(res); - - EXPECT_THAT(ctx.getBufferSize(), Eq(src.size() * sizeof(int))); - EXPECT_THAT(res, ContainerEq(src)); - -} - -TEST(SerializeFSArrayStdArray, CompositeTypes) { - SerializationContext ctx; - std::array src{ - MyStruct1{0,1}, MyStruct1{2,3}, MyStruct1{4,5}, MyStruct1{6,7}, - MyStruct1{8,9}, MyStruct1{11,34}, MyStruct1{5134,1532}}; - std::array res{}; - - ctx.createSerializer().array(src); - ctx.createDeserializer().array(res); - - EXPECT_THAT(ctx.getBufferSize(), Eq(src.size() * MyStruct1::SIZE)); - EXPECT_THAT(res, ContainerEq(src)); -} -// -// -TEST(SerializeFSArrayStdArray, CustomFunctionThatSerializesAnEmptyByteEveryElement) { - SerializationContext ctx; - std::array src{ - MyStruct1{0,1}, MyStruct1{2,3}, MyStruct1{4,5}, MyStruct1{6,7}, - MyStruct1{8,9}, MyStruct1{11,34}, MyStruct1{5134,1532}}; - std::array res{}; - - - auto ser = ctx.createSerializer(); - ser.array(src, [&ser](auto& v) { - char tmp{}; - ser.object(v).value(tmp); - }); - auto des = ctx.createDeserializer(); - des.array(res, [&des](auto& v) { - char tmp{}; - des.object(v).value(tmp); - }); - - EXPECT_THAT(ctx.getBufferSize(), Eq(src.size() * (MyStruct1::SIZE + sizeof(char)))); - EXPECT_THAT(res, ContainerEq(src)); -} - - -TEST(SerializeFSArrayCArray, ArithmeticValues) { - SerializationContext ctx; - int src[4]{5,9,15,-459}; - int res[4]{}; - - ctx.createSerializer().array(src); - ctx.createDeserializer().array(res); - - EXPECT_THAT(ctx.getBufferSize(), Eq(std::extent::value * sizeof(int))); - EXPECT_THAT(res, ContainerEq(src)); - -} - -TEST(SerializeFSArrayCArray, ArithmeticValuesSettingValueSizeExplicitly) { - SerializationContext ctx; - int src[4]{5,9,15,-459}; - int res[4]{}; - - ctx.createSerializer().array(src); - ctx.createDeserializer().array(res); - - EXPECT_THAT(ctx.getBufferSize(), Eq(std::extent::value * sizeof(int))); - EXPECT_THAT(res, ContainerEq(src)); - -} - -TEST(SerializeFSArrayCArray, CompositeTypes) { - SerializationContext ctx; - MyStruct1 src[]{ - MyStruct1{0,1}, MyStruct1{2,3}, MyStruct1{4,5}, MyStruct1{6,7}, - MyStruct1{8,9}, MyStruct1{11,34}, MyStruct1{5134,1532}}; - MyStruct1 res[7]{}; - - ctx.createSerializer().array(src); - ctx.createDeserializer().array(res); - - EXPECT_THAT(ctx.getBufferSize(), Eq(std::extent::value * MyStruct1::SIZE)); - EXPECT_THAT(res, ContainerEq(src)); -} -// -// -TEST(SerializeFSArrayCArray, CustomFunctionThatSerializesAnEmptyByteEveryElement) { - SerializationContext ctx; - MyStruct1 src[]{ - MyStruct1{0,1}, MyStruct1{2,3}, MyStruct1{4,5}, MyStruct1{6,7}, - MyStruct1{8,9}, MyStruct1{11,34}, MyStruct1{5134,1532}}; - MyStruct1 res[7]{}; - - - auto ser = ctx.createSerializer(); - ser.array(src, [&ser](auto& v) { - char tmp{}; - ser.object(v).value(tmp); - }); - auto des = ctx.createDeserializer(); - des.array(res, [&des](auto& v) { - char tmp{}; - des.object(v).value(tmp); - }); - - EXPECT_THAT(ctx.getBufferSize(), Eq(std::extent::value * (MyStruct1::SIZE + sizeof(char)))); - EXPECT_THAT(res, ContainerEq(src)); -} +//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. + + +#include +#include "serialization_test_utils.h" +#include + +using testing::ContainerEq; +using testing::Eq; + +TEST(SerializeFSArrayStdArray, ArithmeticValues) { + SerializationContext ctx; + std::array src{5,9,15,-459}; + std::array res{}; + + ctx.createSerializer().array(src); + ctx.createDeserializer().array(res); + + EXPECT_THAT(ctx.getBufferSize(), Eq(src.size() * sizeof(int))); + EXPECT_THAT(res, ContainerEq(src)); + +} + +TEST(SerializeFSArrayStdArray, ArithmeticValuesSettingValueSizeExplicitly) { + SerializationContext ctx; + std::array src{5,9,15,-459}; + std::array res{}; + + ctx.createSerializer().array(src); + ctx.createDeserializer().array(res); + + EXPECT_THAT(ctx.getBufferSize(), Eq(src.size() * sizeof(int))); + EXPECT_THAT(res, ContainerEq(src)); + +} + +TEST(SerializeFSArrayStdArray, CompositeTypes) { + SerializationContext ctx; + std::array src{ + MyStruct1{0,1}, MyStruct1{2,3}, MyStruct1{4,5}, MyStruct1{6,7}, + MyStruct1{8,9}, MyStruct1{11,34}, MyStruct1{5134,1532}}; + std::array res{}; + + ctx.createSerializer().array(src); + ctx.createDeserializer().array(res); + + EXPECT_THAT(ctx.getBufferSize(), Eq(src.size() * MyStruct1::SIZE)); + EXPECT_THAT(res, ContainerEq(src)); +} +// +// +TEST(SerializeFSArrayStdArray, CustomFunctionThatSerializesAnEmptyByteEveryElement) { + SerializationContext ctx; + std::array src{ + MyStruct1{0,1}, MyStruct1{2,3}, MyStruct1{4,5}, MyStruct1{6,7}, + MyStruct1{8,9}, MyStruct1{11,34}, MyStruct1{5134,1532}}; + std::array res{}; + + + auto ser = ctx.createSerializer(); + ser.array(src, [&ser](auto& v) { + char tmp{}; + ser.object(v).value1(tmp); + }); + auto des = ctx.createDeserializer(); + des.array(res, [&des](auto& v) { + char tmp{}; + des.object(v).value1(tmp); + }); + + EXPECT_THAT(ctx.getBufferSize(), Eq(src.size() * (MyStruct1::SIZE + sizeof(char)))); + EXPECT_THAT(res, ContainerEq(src)); +} + + +TEST(SerializeFSArrayCArray, ArithmeticValues) { + SerializationContext ctx; + int src[4]{5,9,15,-459}; + int res[4]{}; + + ctx.createSerializer().array(src); + ctx.createDeserializer().array(res); + + EXPECT_THAT(ctx.getBufferSize(), Eq(std::extent::value * sizeof(int))); + EXPECT_THAT(res, ContainerEq(src)); + +} + +TEST(SerializeFSArrayCArray, ArithmeticValuesSettingValueSizeExplicitly) { + SerializationContext ctx; + int src[4]{5,9,15,-459}; + int res[4]{}; + + ctx.createSerializer().array(src); + ctx.createDeserializer().array(res); + + EXPECT_THAT(ctx.getBufferSize(), Eq(std::extent::value * sizeof(int))); + EXPECT_THAT(res, ContainerEq(src)); + +} + +TEST(SerializeFSArrayCArray, CompositeTypes) { + SerializationContext ctx; + MyStruct1 src[]{ + MyStruct1{0,1}, MyStruct1{2,3}, MyStruct1{4,5}, MyStruct1{6,7}, + MyStruct1{8,9}, MyStruct1{11,34}, MyStruct1{5134,1532}}; + MyStruct1 res[7]{}; + + ctx.createSerializer().array(src); + ctx.createDeserializer().array(res); + + EXPECT_THAT(ctx.getBufferSize(), Eq(std::extent::value * MyStruct1::SIZE)); + EXPECT_THAT(res, ContainerEq(src)); +} +// +// +TEST(SerializeFSArrayCArray, CustomFunctionThatSerializesAnEmptyByteEveryElement) { + SerializationContext ctx; + MyStruct1 src[]{ + MyStruct1{0,1}, MyStruct1{2,3}, MyStruct1{4,5}, MyStruct1{6,7}, + MyStruct1{8,9}, MyStruct1{11,34}, MyStruct1{5134,1532}}; + MyStruct1 res[7]{}; + + + auto ser = ctx.createSerializer(); + ser.array(src, [&ser](auto& v) { + char tmp{}; + ser.object(v).value1(tmp); + }); + auto des = ctx.createDeserializer(); + des.array(res, [&des](auto& v) { + char tmp{}; + des.object(v).value1(tmp); + }); + + EXPECT_THAT(ctx.getBufferSize(), Eq(std::extent::value * (MyStruct1::SIZE + sizeof(char)))); + EXPECT_THAT(res, ContainerEq(src)); +} diff --git a/tests/serialization_objects.cpp b/tests/serialization_objects.cpp index 1cef990..bcc8581 100644 --- a/tests/serialization_objects.cpp +++ b/tests/serialization_objects.cpp @@ -1,173 +1,173 @@ -//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. - - -#include -#include "serialization_test_utils.h" - -#include -#include - -#include - -using testing::Eq; -using testing::StrEq; -using testing::ContainerEq; - -struct X { - X() {}; - X(int v) :x{ v } {} - std::string s{}; - int x{}; - bool operator ==(const X& r) const { - return r.x == x && r.s == s; - } -}; - - -struct Y { - int y{}; - int carr[3]; - std::array arr; - std::vector vx; - std::string s; -}; -struct Z { X x{}; Y y{}; }; - - -SERIALIZE(Z) -{ - s.object(o.x); - s.object(o.y); - return s; -} - -SERIALIZE(X) -{ - return s.value(o.x) - .text(o.s, 1000); -} - -SERIALIZE(Y) -{ - auto writeInt = [&s](auto& v) { s.template value<4>(v); }; - 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); }, 10000); - return s; -} - -TEST(SerializeObject, GeneralConceptTest) { - //std::string buf; - SerializationContext ctx; - Y y{}; - y.y = 3423; - y.arr[0] = 111; - y.arr[1] = 222; - y.arr[2] = 333; - y.carr[0] = 123; - y.carr[1] = 456; - y.carr[2] = 789; - y.vx.push_back(X(234)); - y.vx.push_back(X(6245)); - y.vx.push_back(X(613461)); - y.s = "labal diena"; - - Z z{}; - z.y = y; - z.x = X{ 234 }; - - - auto ser = ctx.createSerializer(); - ser.object(y); - ser.object(z); - - - Y yres{}; - Z zres{}; - - auto des = ctx.createDeserializer(); - des.object(yres); - des.object(zres); - - EXPECT_THAT(yres.y, Eq(y.y)); - EXPECT_THAT(yres.vx, ContainerEq(y.vx)); - EXPECT_THAT(yres.arr, ContainerEq(y.arr)); - EXPECT_THAT(yres.carr, ContainerEq(y.carr)); - EXPECT_THAT(yres.s, StrEq(y.s)); - - EXPECT_THAT(zres.y.y, Eq(z.y.y)); - EXPECT_THAT(zres.y.vx, ContainerEq(z.y.vx)); - EXPECT_THAT(zres.y.arr, ContainerEq(z.y.arr)); - EXPECT_THAT(zres.y.carr, ContainerEq(z.y.carr)); - EXPECT_THAT(zres.y.s, StrEq(z.y.s)); - EXPECT_THAT(zres.x.s, StrEq(z.x.s)); - EXPECT_THAT(zres.x.x, Eq(z.x.x)); - -} - -TEST(DeltaSerializer, GeneralConceptTest) { - //std::string buf; - Y y{}; - y.y = 3423; - y.arr[0] = 111; - y.arr[1] = 222; - y.arr[2] = 333; - y.carr[0] = 123; - y.carr[1] = 456; - y.carr[2] = 789; - y.vx.push_back(X(234)); - y.vx.push_back(X(6245)); - y.vx.push_back(X(613461)); - y.s = "labal diena"; - y.vx[0].s = "very nice"; - y.vx[1].s = "very nice string, that is a little bit longer that previous"; - - Y yRead = y; - Y yNew = y; - yNew.y = 111111; - yNew.arr[2] = 0xFFFFFFFF; - yNew.carr[1] = 0xFFFFFFFF; - yNew.s = "labas dienaABC"; - yNew.vx[0].s = "very opapa"; - yNew.vx[1].s = "bla"; - yNew.vx.push_back(X{ 3 }); - - std::vector buf; - bitsery::BufferWriter bw{ buf }; - bitsery::DeltaSerializer ser(bw, y, yNew); - serialize(ser, yNew); - bw.flush(); - - bitsery::BufferReader br{ buf }; - bitsery::DeltaDeserializer des(br, y, yRead); - serialize(des, yRead); - - EXPECT_THAT(yRead.y, Eq(yNew.y)); - EXPECT_THAT(yRead.vx, ContainerEq(yNew.vx)); - EXPECT_THAT(yRead.arr, ContainerEq(yNew.arr)); - EXPECT_THAT(yRead.carr, ContainerEq(yNew.carr)); - EXPECT_THAT(yRead.s, StrEq(yNew.s)); -} - +//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. + + +#include +#include "serialization_test_utils.h" + +#include +#include + +#include + +using testing::Eq; +using testing::StrEq; +using testing::ContainerEq; + +struct X { + X() {}; + X(int v) :x{ v } {} + std::string s{}; + int x{}; + bool operator ==(const X& r) const { + return r.x == x && r.s == s; + } +}; + + +struct Y { + int y{}; + int carr[3]; + std::array arr; + std::vector vx; + std::string s; +}; +struct Z { X x{}; Y y{}; }; + + +SERIALIZE(Z) +{ + s.object(o.x); + s.object(o.y); + return s; +} + +SERIALIZE(X) +{ + return s.template value(o.x) + .template text<1>(o.s, 1000); +} + +SERIALIZE(Y) +{ + auto writeInt = [&s](auto& v) { s.template value(v); }; + s.template text<1>(o.s, 10000); + s.template value(o.y); + s.array(o.arr, writeInt); + s.array(o.carr, writeInt); + s.container(o.vx, [&s](auto& v) { s.object(v); }, 10000); + return s; +} + +TEST(SerializeObject, GeneralConceptTest) { + //std::string buf; + SerializationContext ctx; + Y y{}; + y.y = 3423; + y.arr[0] = 111; + y.arr[1] = 222; + y.arr[2] = 333; + y.carr[0] = 123; + y.carr[1] = 456; + y.carr[2] = 789; + y.vx.push_back(X(234)); + y.vx.push_back(X(6245)); + y.vx.push_back(X(613461)); + y.s = "labal diena"; + + Z z{}; + z.y = y; + z.x = X{ 234 }; + + + auto ser = ctx.createSerializer(); + ser.object(y); + ser.object(z); + + + Y yres{}; + Z zres{}; + + auto des = ctx.createDeserializer(); + des.object(yres); + des.object(zres); + + EXPECT_THAT(yres.y, Eq(y.y)); + EXPECT_THAT(yres.vx, ContainerEq(y.vx)); + EXPECT_THAT(yres.arr, ContainerEq(y.arr)); + EXPECT_THAT(yres.carr, ContainerEq(y.carr)); + EXPECT_THAT(yres.s, StrEq(y.s)); + + EXPECT_THAT(zres.y.y, Eq(z.y.y)); + EXPECT_THAT(zres.y.vx, ContainerEq(z.y.vx)); + EXPECT_THAT(zres.y.arr, ContainerEq(z.y.arr)); + EXPECT_THAT(zres.y.carr, ContainerEq(z.y.carr)); + EXPECT_THAT(zres.y.s, StrEq(z.y.s)); + EXPECT_THAT(zres.x.s, StrEq(z.x.s)); + EXPECT_THAT(zres.x.x, Eq(z.x.x)); + +} + +TEST(DeltaSerializer, GeneralConceptTest) { + //std::string buf; + Y y{}; + y.y = 3423; + y.arr[0] = 111; + y.arr[1] = 222; + y.arr[2] = 333; + y.carr[0] = 123; + y.carr[1] = 456; + y.carr[2] = 789; + y.vx.push_back(X(234)); + y.vx.push_back(X(6245)); + y.vx.push_back(X(613461)); + y.s = "labal diena"; + y.vx[0].s = "very nice"; + y.vx[1].s = "very nice string, that is a little bit longer that previous"; + + Y yRead = y; + Y yNew = y; + yNew.y = 111111; + yNew.arr[2] = 0xFFFFFFFF; + yNew.carr[1] = 0xFFFFFFFF; + yNew.s = "labas dienaABC"; + yNew.vx[0].s = "very opapa"; + yNew.vx[1].s = "bla"; + yNew.vx.push_back(X{ 3 }); + + std::vector buf; + bitsery::BufferWriter bw{ buf }; + bitsery::DeltaSerializer ser(bw, y, yNew); + serialize(ser, yNew); + bw.flush(); + + bitsery::BufferReader br{ buf }; + bitsery::DeltaDeserializer des(br, y, yRead); + serialize(des, yRead); + + EXPECT_THAT(yRead.y, Eq(yNew.y)); + EXPECT_THAT(yRead.vx, ContainerEq(yNew.vx)); + EXPECT_THAT(yRead.arr, ContainerEq(yNew.arr)); + EXPECT_THAT(yRead.carr, ContainerEq(yNew.carr)); + EXPECT_THAT(yRead.s, StrEq(yNew.s)); +} + diff --git a/tests/serialization_substitution.cpp b/tests/serialization_substitution.cpp index 56339f0..76324db 100644 --- a/tests/serialization_substitution.cpp +++ b/tests/serialization_substitution.cpp @@ -1,162 +1,135 @@ -//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. - - -#include -#include "serialization_test_utils.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)); -} +//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. + + +#include +#include "serialization_test_utils.h" +using namespace testing; + +TEST(SerializeSubstitution, WhenSubstitutedThenOnlyWriteIndexUsingMinRequiredBits) { + int32_t v = 4849; + int32_t res; + constexpr size_t N = 3; + std::array subsitution{485,4849,89}; + SerializationContext ctx; + ctx.createSerializer().substitution<4>(v, subsitution); + ctx.createDeserializer().substitution<4>(res, subsitution); + + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); + + SerializationContext ctx1; + ctx1.createSerializer().substitution<4>(v, subsitution); + auto des = ctx1.createDeserializer(); + des.range(res, {0, N + 1}); + EXPECT_THAT(res, Eq(2)); +} + +TEST(SerializeSubstitution, WhenNoSubstitutionThenWriteZeroBitsAndValueOrObject) { + int16_t v = 8945; + int16_t res; + std::array subsitution{485,4849,89}; + SerializationContext ctx; + ctx.createSerializer().substitution<2>(v, subsitution); + ctx.createDeserializer().substitution<2>(res, subsitution); + + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq(sizeof(int16_t)+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, 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/serialization_test_utils.h b/tests/serialization_test_utils.h index d5fe43b..57eb2b2 100644 --- a/tests/serialization_test_utils.h +++ b/tests/serialization_test_utils.h @@ -1,103 +1,103 @@ -//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_SERIALIZERTESTS_H -#define BITSERY_SERIALIZERTESTS_H - -#include -#include - -struct MyStruct1 { - MyStruct1(int v1, int v2):i1{v1}, i2{v2} {} - MyStruct1():MyStruct1{0,0} {} - int i1; - int i2; - bool operator == (const MyStruct1& rhs) const { - return i1 == rhs.i1 && i2 == rhs.i2; - } - static constexpr size_t SIZE = sizeof(MyStruct1::i1) + sizeof(MyStruct1::i2); -}; - -SERIALIZE(MyStruct1) { - return s. - value(o.i1). - value(o.i2); -} - -enum class MyEnumClass { - E1, E2, E3, E4, E5, E6 -}; - -struct MyStruct2 { - enum MyEnum { - V1, V2, V3, V4, V5, V6 - }; - - MyStruct2(MyEnum e, MyStruct1 s):e1{e}, s1{s} {} - MyStruct2():MyStruct2{V1,{0,0}} {} - - MyEnum e1; - MyStruct1 s1; - bool operator == (const MyStruct2& rhs) const { - return e1 == rhs.e1 && s1 == rhs.s1; - } - static constexpr size_t SIZE = MyStruct1::SIZE + sizeof(MyStruct2::e1); -}; - -SERIALIZE(MyStruct2) { - return s. - value(o.e1). - object(o.s1); -} - -class SerializationContext { - std::vector buf{}; - std::unique_ptr bw; - std::unique_ptr br; -public: - bitsery::Serializer createSerializer() { - bw = std::make_unique(buf); - return {*bw}; - }; - - size_t getBufferSize() const { - return buf.size(); - } - //since all containers .size() method returns size_t, it cannot be dirrectly serialized, because size_t is platform dependant - //this function returns number of bytes writen to buffer, when reading/writing size of container - static size_t containerSizeSerializedBytesCount(size_t elemsCount) { - if (elemsCount < 0x80u) - return 1; - if (elemsCount < 0x4000u) - return 2; - return 4; - } - - bitsery::Deserializer createDeserializer() { - bw->flush(); - br = std::make_unique(buf); - return {*br}; - }; -}; - -#endif //BITSERY_SERIALIZERTESTS_H +//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_SERIALIZERTESTS_H +#define BITSERY_SERIALIZERTESTS_H + +#include +#include + +struct MyStruct1 { + MyStruct1(int v1, int v2):i1{v1}, i2{v2} {} + MyStruct1():MyStruct1{0,0} {} + int i1; + int i2; + bool operator == (const MyStruct1& rhs) const { + return i1 == rhs.i1 && i2 == rhs.i2; + } + static constexpr size_t SIZE = sizeof(MyStruct1::i1) + sizeof(MyStruct1::i2); +}; + +SERIALIZE(MyStruct1) { + return s. + template value(o.i1). + template value(o.i2); +} + +enum class MyEnumClass { + E1, E2, E3, E4, E5, E6 +}; + +struct MyStruct2 { + enum MyEnum { + V1, V2, V3, V4, V5, V6 + }; + + MyStruct2(MyEnum e, MyStruct1 s):e1{e}, s1{s} {} + MyStruct2():MyStruct2{V1,{0,0}} {} + + MyEnum e1; + MyStruct1 s1; + bool operator == (const MyStruct2& rhs) const { + return e1 == rhs.e1 && s1 == rhs.s1; + } + static constexpr size_t SIZE = MyStruct1::SIZE + sizeof(MyStruct2::e1); +}; + +SERIALIZE(MyStruct2) { + return s. + template value(o.e1). + object(o.s1); +} + +class SerializationContext { + std::vector buf{}; + std::unique_ptr bw; + std::unique_ptr br; +public: + bitsery::Serializer createSerializer() { + bw = std::make_unique(buf); + return {*bw}; + }; + + size_t getBufferSize() const { + return buf.size(); + } + //since all containers .size() method returns size_t, it cannot be dirrectly serialized, because size_t is platform dependant + //this function returns number of bytes writen to buffer, when reading/writing size of container + static size_t containerSizeSerializedBytesCount(size_t elemsCount) { + if (elemsCount < 0x80u) + return 1; + if (elemsCount < 0x4000u) + return 2; + return 4; + } + + bitsery::Deserializer createDeserializer() { + bw->flush(); + br = std::make_unique(buf); + return {*br}; + }; +}; + +#endif //BITSERY_SERIALIZERTESTS_H diff --git a/tests/serialization_text.cpp b/tests/serialization_text.cpp index 4a5b245..39c99c1 100644 --- a/tests/serialization_text.cpp +++ b/tests/serialization_text.cpp @@ -1,138 +1,124 @@ -//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. - - -#include -#include "serialization_test_utils.h" -using namespace testing; - -TEST(SerializeText, BasicString) { - SerializationContext ctx; - std::string t1 = "some random text"; - std::string res; - - ctx.createSerializer().text(t1, 1000); - ctx.createDeserializer().text(res, 1000); - - EXPECT_THAT(res, StrEq(t1)); - EXPECT_THAT(res, ContainerEq(t1)); - -} - -TEST(SerializeText, WhenSizeOfTypeNotEqualsOneThenSetSizeExplicitly) { - SerializationContext ctx; - constexpr auto VSIZE = sizeof(char32_t); - std::basic_string t1 = U"some random text"; - 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, 1000); - ctx.createDeserializer().text(res, 1000); - - EXPECT_THAT(res, ContainerEq(t1)); -} - -TEST(SerializeText, BasicStringUseSizeMethodNotNullterminatedLength) { - SerializationContext ctx; - std::wstring t1(L"some random text\0xxxxxx", 20); - std::wstring wres; - constexpr auto VSIZE = sizeof(std::wstring::value_type); - - ctx.createSerializer().text(t1, 1000); - ctx.createDeserializer().text(wres, 1000); - - EXPECT_THAT(wres, StrEq(t1)); - EXPECT_THAT(wres.size(), Eq(t1.size())); - EXPECT_THAT(wres.size(), Gt(std::char_traits::length(t1.data()))); - - SerializationContext ctx2; - std::string t2("\0no one cares what is there", 10); - std::string 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, 1000); - ctx3.createDeserializer().text(res, 1000); - EXPECT_THAT(res, StrEq(t3)); - EXPECT_THAT(res.size(), Eq(10)); -} - -const int CARR_LENGTH = 10; - -TEST(SerializeText, CArraySerializesTextLength) { - SerializationContext ctx; - char t1[CARR_LENGTH]{"some text"}; - char r1[CARR_LENGTH]{}; - - ctx.createSerializer().text(t1); - ctx.createDeserializer().text(r1); - - EXPECT_THAT(ctx.getBufferSize(), Eq(ctx.containerSizeSerializedBytesCount(CARR_LENGTH) + - std::char_traits::length(t1))); - - EXPECT_THAT(r1, StrEq(t1)); - EXPECT_THAT(r1, ContainerEq(t1)); - - //zero length string - t1[0] = 0; - SerializationContext ctx2; - ctx2.createSerializer().text(t1); - ctx2.createDeserializer().text(r1); - - EXPECT_THAT(ctx2.getBufferSize(), Eq(ctx2.containerSizeSerializedBytesCount(CARR_LENGTH))); - EXPECT_THAT(r1, StrEq(t1)); - EXPECT_THAT(r1, ContainerEq(t1)); -} - -TEST(SerializeText, WhenCArrayWithLargerTypeThenSetSizeExplicitly) { - SerializationContext ctx; - char32_t t1[10]{U"some text"}; - char32_t r1[10]{}; - constexpr auto SIZE = sizeof(char32_t); - ctx.createSerializer().text(t1); - ctx.createDeserializer().text(r1); - - EXPECT_THAT(ctx.getBufferSize(), Eq(ctx.containerSizeSerializedBytesCount(CARR_LENGTH) + - std::char_traits::length(t1) * SIZE)); - EXPECT_THAT(r1, ContainerEq(t1)); -} - - -TEST(SerializeText, WhenCArrayNotNullterminatedThenMakeItNullterminated) { - SerializationContext ctx; - char t1[CARR_LENGTH]{"some text"}; - //make last character not nullterminated - t1[CARR_LENGTH-1] = 'x'; - char r1[CARR_LENGTH]{}; - - ctx.createSerializer().text(t1); - ctx.createDeserializer().text(r1); - - EXPECT_THAT(ctx.getBufferSize(), Eq(ctx.containerSizeSerializedBytesCount(CARR_LENGTH) + - CARR_LENGTH - 1)); - EXPECT_THAT(r1[CARR_LENGTH-1], Eq(0)); +//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. + + +#include +#include "serialization_test_utils.h" +using namespace testing; + +TEST(SerializeText, BasicString) { + SerializationContext ctx; + std::string t1 = "some random text"; + std::string res; + + ctx.createSerializer().text(t1, 1000); + ctx.createDeserializer().text(res, 1000); + + EXPECT_THAT(res, StrEq(t1)); + EXPECT_THAT(res, ContainerEq(t1)); + +} + +TEST(SerializeText, WhenSizeOfTypeNotEqualsOneThenSetSizeExplicitly) { + SerializationContext ctx; + constexpr auto VSIZE = sizeof(char32_t); + std::basic_string t1 = U"some random text"; + 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, 1000); + ctx.createDeserializer().text(res, 1000); + + EXPECT_THAT(res, ContainerEq(t1)); +} + +TEST(SerializeText, BasicStringUseSizeMethodNotNullterminatedLength) { + SerializationContext ctx; + std::wstring t1(L"some random text\0xxxxxx", 20); + std::wstring wres; + constexpr auto VSIZE = sizeof(std::wstring::value_type); + + ctx.createSerializer().text(t1, 1000); + ctx.createDeserializer().text(wres, 1000); + + EXPECT_THAT(wres, StrEq(t1)); + EXPECT_THAT(wres.size(), Eq(t1.size())); + EXPECT_THAT(wres.size(), Gt(std::char_traits::length(t1.data()))); + + SerializationContext ctx2; + std::string t2("\0no one cares what is there", 10); + std::string 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, 1000); + ctx3.createDeserializer().text(res, 1000); + EXPECT_THAT(res, StrEq(t3)); + EXPECT_THAT(res.size(), Eq(10)); +} + +constexpr int CARR_LENGTH = 10; + +TEST(SerializeText, CArraySerializesTextLength) { + SerializationContext ctx; + char t1[CARR_LENGTH]{"some text"}; + char r1[CARR_LENGTH]{}; + + ctx.createSerializer().text<1>(t1); + ctx.createDeserializer().text<1>(r1); + + EXPECT_THAT(ctx.getBufferSize(), Eq(ctx.containerSizeSerializedBytesCount(CARR_LENGTH) + + std::char_traits::length(t1))); + + EXPECT_THAT(r1, StrEq(t1)); + EXPECT_THAT(r1, ContainerEq(t1)); + + //zero length string + t1[0] = 0; + SerializationContext ctx2; + ctx2.createSerializer().text<1>(t1); + ctx2.createDeserializer().text<1>(r1); + + EXPECT_THAT(ctx2.getBufferSize(), Eq(ctx2.containerSizeSerializedBytesCount(CARR_LENGTH))); + EXPECT_THAT(r1, StrEq(t1)); + EXPECT_THAT(r1, ContainerEq(t1)); +} + +TEST(SerializeText, WhenCArrayNotNullterminatedThenMakeItNullterminated) { + SerializationContext ctx; + char16_t t1[CARR_LENGTH]{u"some text"}; + //make last character not nullterminated + t1[CARR_LENGTH-1] = 'x'; + char16_t r1[CARR_LENGTH]{}; + + ctx.createSerializer().text<2>(t1); + ctx.createDeserializer().text<2>(r1); + + EXPECT_THAT(ctx.getBufferSize(), Eq(ctx.containerSizeSerializedBytesCount(CARR_LENGTH) + + (CARR_LENGTH - 1) * 2)); + EXPECT_THAT(r1[CARR_LENGTH-1], Eq(0)); } \ No newline at end of file diff --git a/tests/serializer_values.cpp b/tests/serializer_values.cpp index 6dde056..a13e575 100644 --- a/tests/serializer_values.cpp +++ b/tests/serializer_values.cpp @@ -1,73 +1,112 @@ -//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. - -#include -#include "serialization_test_utils.h" - -using testing::Eq; - -template -bool SerializeDeserializeValue(const T& v) { - T res{}; - SerializationContext ctx; - ctx.createSerializer().value(v); - ctx.createDeserializer().value(res); - return v == res; -} - -TEST(SerializeValues, IntegerTypes) { - EXPECT_THAT(SerializeDeserializeValue(-449874), Eq(true)); - EXPECT_THAT(SerializeDeserializeValue(34u), Eq(true)); -} - -TEST(SerializeValues, EnumTypes) { - enum E1{ - A1,B1,C1,D1 - }; - EXPECT_THAT(SerializeDeserializeValue(E1::C1), Eq(true)); - enum class E2 { - A2,B2,C2,D2 - }; - EXPECT_THAT(SerializeDeserializeValue(E2::B2), Eq(true)); - enum class E3:short { - A3, B3, C3=4568, D3 - }; - EXPECT_THAT(SerializeDeserializeValue(E3::C3), Eq(true)); -} - -TEST(SerializeValues, FloatingPointTypes) { - EXPECT_THAT(SerializeDeserializeValue(-484.465), Eq(true)); - EXPECT_THAT(SerializeDeserializeValue(0.00000015f), Eq(true)); -} - -TEST(SerializeValues, ExplicitTypeSize) { - int v{23472}; - int 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(ctx.getBufferSize())); -} +//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. + +#include +#include "serialization_test_utils.h" + +using testing::Eq; + +template +bool SerializeDeserializeValue(const T& v) { + T res{}; + SerializationContext ctx; + ctx.createSerializer().value(v); + ctx.createDeserializer().value(res); + return v == res; +} + +TEST(SerializeValues, IntegerTypes) { + EXPECT_THAT(SerializeDeserializeValue(-449874), Eq(true)); + EXPECT_THAT(SerializeDeserializeValue(34u), Eq(true)); +} + +TEST(SerializeValues, EnumTypes) { + enum E1{ + A1,B1,C1,D1 + }; + EXPECT_THAT(SerializeDeserializeValue(E1::C1), Eq(true)); + enum class E2 { + A2,B2,C2,D2 + }; + EXPECT_THAT(SerializeDeserializeValue(E2::B2), Eq(true)); + enum class E3:short { + A3, B3, C3=4568, D3 + }; + EXPECT_THAT(SerializeDeserializeValue(E3::C3), Eq(true)); +} + +TEST(SerializeValues, FloatingPointTypes) { + EXPECT_THAT(SerializeDeserializeValue(-484.465), Eq(true)); + EXPECT_THAT(SerializeDeserializeValue(0.00000015f), Eq(true)); +} + +TEST(SerializeValues, ValueSizeOverload1Byte) { + int8_t v{54}; + int8_t res; + constexpr size_t TSIZE = sizeof(v); + + SerializationContext ctx; + ctx.createSerializer().value1(v); + ctx.createDeserializer().value1(res); + + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize())); +} + +TEST(SerializeValues, ValueSizeOverload2Byte) { + int16_t v{54}; + int16_t res; + constexpr size_t TSIZE = sizeof(v); + + SerializationContext ctx; + ctx.createSerializer().value2(v); + ctx.createDeserializer().value2(res); + + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize())); +} + +TEST(SerializeValues, ValueSizeOverload4Byte) { + float v{54.498}; + float res; + constexpr size_t TSIZE = sizeof(v); + + SerializationContext ctx; + ctx.createSerializer().value4(v); + ctx.createDeserializer().value4(res); + + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize())); +} + +TEST(SerializeValues, ValueSizeOverload8Byte) { + int64_t v{54}; + int64_t res; + constexpr size_t TSIZE = sizeof(v); + + SerializationContext ctx; + ctx.createSerializer().value8(v); + ctx.createDeserializer().value8(res); + + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize())); +}