From 3e02d0ca445d1a77f0bfdefa4db6939f0424061a Mon Sep 17 00:00:00 2001 From: Mindaugas Vinkelis Date: Thu, 1 Dec 2022 13:50:03 +0200 Subject: [PATCH] format code base in Mozilla style --- .clang-format | 192 +++ examples/basic_usage.cpp | 78 +- examples/bit_packing.cpp | 96 +- examples/brief_syntax.cpp | 68 +- examples/composite_types.cpp | 163 +-- examples/context_usage.cpp | 151 ++- examples/file_stream.cpp | 93 +- examples/forward_backward_compatibility.cpp | 164 +-- examples/inheritance.cpp | 166 ++- examples/non_default_constructible.cpp | 94 +- examples/raw_pointers.cpp | 255 ++-- examples/smart_pointers_with_polymorphism.cpp | 438 ++++--- format.sh | 3 + include/bitsery/adapter/buffer.h | 442 ++++--- include/bitsery/adapter/measure_size.h | 124 +- include/bitsery/adapter/stream.h | 548 ++++---- include/bitsery/bitsery.h | 51 +- include/bitsery/brief_syntax.h | 172 +-- include/bitsery/brief_syntax/array.h | 49 +- include/bitsery/brief_syntax/atomic.h | 46 +- include/bitsery/brief_syntax/chrono.h | 58 +- include/bitsery/brief_syntax/deque.h | 49 +- include/bitsery/brief_syntax/forward_list.h | 49 +- include/bitsery/brief_syntax/list.h | 49 +- include/bitsery/brief_syntax/map.h | 87 +- include/bitsery/brief_syntax/memory.h | 70 +- include/bitsery/brief_syntax/queue.h | 61 +- include/bitsery/brief_syntax/set.h | 63 +- include/bitsery/brief_syntax/stack.h | 49 +- include/bitsery/brief_syntax/string.h | 49 +- include/bitsery/brief_syntax/tuple.h | 46 +- include/bitsery/brief_syntax/unordered_map.h | 87 +- include/bitsery/brief_syntax/unordered_set.h | 69 +- include/bitsery/brief_syntax/variant.h | 46 +- include/bitsery/brief_syntax/vector.h | 49 +- include/bitsery/common.h | 70 +- include/bitsery/deserializer.h | 1011 ++++++++------- include/bitsery/details/adapter_bit_packing.h | 699 ++++++----- include/bitsery/details/adapter_common.h | 745 ++++++----- include/bitsery/details/brief_syntax_common.h | 316 +++-- include/bitsery/details/not_defined_type.h | 125 +- .../bitsery/details/serialization_common.h | 819 ++++++------ include/bitsery/ext/compact_value.h | 346 +++--- include/bitsery/ext/entropy.h | 176 +-- include/bitsery/ext/growable.h | 128 +- include/bitsery/ext/inheritance.h | 283 ++--- include/bitsery/ext/pointer.h | 370 +++--- include/bitsery/ext/std_atomic.h | 96 +- include/bitsery/ext/std_bitset.h | 264 ++-- include/bitsery/ext/std_chrono.h | 171 +-- include/bitsery/ext/std_map.h | 176 +-- include/bitsery/ext/std_optional.h | 163 +-- include/bitsery/ext/std_queue.h | 200 +-- include/bitsery/ext/std_set.h | 162 +-- include/bitsery/ext/std_smart_ptr.h | 349 +++--- include/bitsery/ext/std_stack.h | 129 +- include/bitsery/ext/std_tuple.h | 120 +- include/bitsery/ext/std_variant.h | 168 +-- .../ext/utils/composite_type_overloads.h | 245 ++-- include/bitsery/ext/utils/memory_resource.h | 289 +++-- include/bitsery/ext/utils/pointer_utils.h | 1077 +++++++++------- .../bitsery/ext/utils/polymorphism_utils.h | 586 +++++---- include/bitsery/ext/utils/rtti_utils.h | 88 +- include/bitsery/ext/value_range.h | 445 ++++--- include/bitsery/serializer.h | 968 +++++++++------ include/bitsery/traits/array.h | 57 +- include/bitsery/traits/core/std_defaults.h | 180 +-- include/bitsery/traits/core/traits.h | 330 ++--- include/bitsery/traits/deque.h | 51 +- include/bitsery/traits/forward_list.h | 114 +- include/bitsery/traits/list.h | 51 +- include/bitsery/traits/string.h | 107 +- include/bitsery/traits/vector.h | 69 +- tests/adapter.cpp | 876 ++++++------- tests/brief_syntax.cpp | 675 +++++----- tests/data_endianness.cpp | 315 ++--- tests/data_operations.cpp | 693 ++++++----- tests/data_writing.cpp | 166 +-- tests/not_default_constructible.cpp | 569 +++++---- tests/serialization.cpp | 74 +- tests/serialization_bool.cpp | 133 +- tests/serialization_container.cpp | 415 ++++--- tests/serialization_context.cpp | 178 +-- tests/serialization_ext_compact_value.cpp | 396 +++--- tests/serialization_ext_entropy.cpp | 323 ++--- tests/serialization_ext_growable.cpp | 431 +++---- tests/serialization_ext_inheritance.cpp | 596 +++++---- tests/serialization_ext_pointer.cpp | 934 +++++++------- ...lization_ext_pointer_polymorphic_types.cpp | 495 ++++---- ...rialization_ext_pointer_with_allocator.cpp | 547 ++++---- tests/serialization_ext_std_bitset.cpp | 180 +-- tests/serialization_ext_std_chrono.cpp | 108 +- tests/serialization_ext_std_map.cpp | 200 +-- tests/serialization_ext_std_optional.cpp | 167 +-- tests/serialization_ext_std_queue.cpp | 147 +-- tests/serialization_ext_std_set.cpp | 110 +- tests/serialization_ext_std_smart_ptr.cpp | 1100 +++++++++-------- tests/serialization_ext_std_stack.cpp | 82 +- tests/serialization_ext_std_tuple.cpp | 183 +-- tests/serialization_ext_std_variant.cpp | 254 ++-- tests/serialization_ext_value_range.cpp | 300 +++-- tests/serialization_objects.cpp | 198 +-- tests/serialization_size.cpp | 100 +- tests/serialization_test_utils.h | 267 ++-- tests/serialization_text.cpp | 191 +-- tests/serialization_values.cpp | 181 +-- 106 files changed, 15083 insertions(+), 12518 deletions(-) create mode 100644 .clang-format create mode 100755 format.sh diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..38773ba --- /dev/null +++ b/.clang-format @@ -0,0 +1,192 @@ +--- +Language: Cpp +# BasedOnStyle: Mozilla +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: TopLevel +AlwaysBreakAfterReturnType: TopLevel +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: Never + AfterEnum: true + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: false + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Mozilla +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeComma +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +QualifierAlignment: Leave +CompactNamespaces: false +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: false +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +PackConstructorInitializers: BinPack +BasedOnStyle: '' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllConstructorInitializersOnNextLine: true +FixNamespaceComments: false +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseLabels: true +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: false +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Left +PPIndentWidth: -1 +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + BeforeNonEmptyParentheses: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... + diff --git a/examples/basic_usage.cpp b/examples/basic_usage.cpp index b85134b..866485c 100644 --- a/examples/basic_usage.cpp +++ b/examples/basic_usage.cpp @@ -1,48 +1,62 @@ -//include bitsery.h to get serialization and deserialization classes +// include bitsery.h to get serialization and deserialization classes #include -//in ordered to serialize/deserialize data to buffer, include buffer adapter +// in ordered to serialize/deserialize data to buffer, include buffer adapter #include -//bitsery itself doesn't is lightweight, and doesnt include any unnessessary files, -//traits helps library to know how to use types correctly, -//in this case we'll be using vector both, to serialize/deserialize data and to store use as a buffer. +// bitsery itself doesn't is lightweight, and doesnt include any unnessessary +// files, traits helps library to know how to use types correctly, in this case +// we'll be using vector both, to serialize/deserialize data and to store use as +// a buffer. #include -enum class MyEnum:uint16_t { V1,V2,V3 }; -struct MyStruct { - uint32_t i; - MyEnum e; - std::vector fs; +enum class MyEnum : uint16_t +{ + V1, + V2, + V3 +}; +struct MyStruct +{ + uint32_t i; + MyEnum e; + std::vector fs; }; -//define how object should be serialized/deserialized -template -void serialize(S& s, MyStruct& o) { - s.value4b(o.i);//fundamental types (ints, floats, enums) of size 4b - s.value2b(o.e); - s.container4b(o.fs, 10);//resizable containers also requires maxSize, to make it safe from buffer-overflow attacks +// define how object should be serialized/deserialized +template +void +serialize(S& s, MyStruct& o) +{ + s.value4b(o.i); // fundamental types (ints, floats, enums) of size 4b + s.value2b(o.e); + s.container4b(o.fs, 10); // resizable containers also requires maxSize, to + // make it safe from buffer-overflow attacks } -//some helper types +// some helper types using Buffer = std::vector; using OutputAdapter = bitsery::OutputBufferAdapter; using InputAdapter = bitsery::InputBufferAdapter; -int main() { - //set some random data - MyStruct data{8941, MyEnum::V2, {15.0f, -8.5f, 0.045f}}; - MyStruct res{}; +int +main() +{ + // set some random data + MyStruct data{ 8941, MyEnum::V2, { 15.0f, -8.5f, 0.045f } }; + MyStruct res{}; - //create buffer to store data - Buffer buffer; - //use quick serialization function, - //it will use default configuration to setup all the nesessary steps - //and serialize data to container - auto writtenSize = bitsery::quickSerialization(buffer, data); + // create buffer to store data + Buffer buffer; + // use quick serialization function, + // it will use default configuration to setup all the nesessary steps + // and serialize data to container + auto writtenSize = bitsery::quickSerialization(buffer, data); - //same as serialization, but returns deserialization state as a pair - //first = error code, second = is buffer was successfully read from begin to the end. - auto state = bitsery::quickDeserialization({buffer.begin(), writtenSize}, res); + // same as serialization, but returns deserialization state as a pair + // first = error code, second = is buffer was successfully read from begin to + // the end. + auto state = bitsery::quickDeserialization( + { buffer.begin(), writtenSize }, res); - assert(state.first == bitsery::ReaderError::NoError && state.second); - assert(data.fs == res.fs && data.i == res.i && data.e == res.e); + assert(state.first == bitsery::ReaderError::NoError && state.second); + assert(data.fs == res.fs && data.i == res.i && data.e == res.e); } diff --git a/examples/bit_packing.cpp b/examples/bit_packing.cpp index fb8cee8..5412ec1 100644 --- a/examples/bit_packing.cpp +++ b/examples/bit_packing.cpp @@ -1,62 +1,74 @@ -#include #include -//we'll be using std::array as a buffer type, so include traits for this +#include +// we'll be using std::array as a buffer type, so include traits for this #include #include #include -//include extension that will allow to compress our data +// include extension that will allow to compress our data #include namespace MyTypes { - struct Vec3 { float x, y, z; }; +struct Vec3 +{ + float x, y, z; +}; - struct Monster { - Vec3 pos; - std::vector path; - std::string name; - }; +struct Monster +{ + Vec3 pos; + std::vector path; + std::string name; +}; - template - void serialize(S& s, MyTypes::Vec3 &o) { - s.value4b(o.x); - s.value4b(o.y); - s.value4b(o.z); - } - - template - void serialize (S& s, Monster& o) { - s.text1b(o.name, 20); - s.object(o.pos); - //compress path in a range of -1.0 .. 1.0 with 0.01 precision - //enableBitPacking creates separate serializer/deserializer object, that contains bit packing operations - s.enableBitPacking([&o](typename S::BPEnabledType& sbp) { - sbp.container(o.path, 1000, [](typename S::BPEnabledType& sbp, Vec3& vec3) { - constexpr bitsery::ext::ValueRange range{-1.0f,1.0f, 0.01f}; - sbp.ext(vec3.x, range); - sbp.ext(vec3.y, range); - sbp.ext(vec3.z, range); - }); - }); - } +template +void +serialize(S& s, MyTypes::Vec3& o) +{ + s.value4b(o.x); + s.value4b(o.y); + s.value4b(o.z); } -//use fixed-size buffer +template +void +serialize(S& s, Monster& o) +{ + s.text1b(o.name, 20); + s.object(o.pos); + // compress path in a range of -1.0 .. 1.0 with 0.01 precision + // enableBitPacking creates separate serializer/deserializer object, that + // contains bit packing operations + s.enableBitPacking([&o](typename S::BPEnabledType& sbp) { + sbp.container(o.path, 1000, [](typename S::BPEnabledType& sbp, Vec3& vec3) { + constexpr bitsery::ext::ValueRange range{ -1.0f, 1.0f, 0.01f }; + sbp.ext(vec3.x, range); + sbp.ext(vec3.y, range); + sbp.ext(vec3.z, range); + }); + }); +} +} + +// use fixed-size buffer using Buffer = std::array; using OutputAdapter = bitsery::OutputBufferAdapter; using InputAdapter = bitsery::InputBufferAdapter; -int main() { - //set some random data - MyTypes::Monster data{}; - data.name = "lew"; +int +main() +{ + // set some random data + MyTypes::Monster data{}; + data.name = "lew"; - //create buffer to store data to - Buffer buffer{}; - auto writtenSize = bitsery::quickSerialization(buffer, data); + // create buffer to store data to + Buffer buffer{}; + auto writtenSize = bitsery::quickSerialization(buffer, data); - MyTypes::Monster res{}; - auto state = bitsery::quickDeserialization({buffer.begin(), writtenSize}, res); + MyTypes::Monster res{}; + auto state = bitsery::quickDeserialization( + { buffer.begin(), writtenSize }, res); - assert(state.first == bitsery::ReaderError::NoError && state.second); + assert(state.first == bitsery::ReaderError::NoError && state.second); } diff --git a/examples/brief_syntax.cpp b/examples/brief_syntax.cpp index 49e42c0..c9185f1 100644 --- a/examples/brief_syntax.cpp +++ b/examples/brief_syntax.cpp @@ -1,44 +1,54 @@ -#include #include -//to use brief syntax always include this header +#include +// to use brief syntax always include this header #include -//we also need additional traits to work with container types, -//instead of including for vector traits, now we also need traits to work with brief_syntax types. -//so include everything from instead of -//otherwise we'll get static assert error, saying to define serialize function. +// we also need additional traits to work with container types, +// instead of including for vector traits, now we also +// need traits to work with brief_syntax types. so include everything from +// instead of otherwise we'll +// get static assert error, saying to define serialize function. #include -enum class MyEnum:uint16_t { V1,V2,V3 }; -struct MyStruct { - uint32_t i; - MyEnum e; - std::vector fs; - - //define serialize function as usual - template - void serialize(S& s) { - //now we can use brief syntax with - s(i, e, fs); - } +enum class MyEnum : uint16_t +{ + V1, + V2, + V3 +}; +struct MyStruct +{ + uint32_t i; + MyEnum e; + std::vector fs; + // define serialize function as usual + template + void serialize(S& s) + { + // now we can use brief syntax with + s(i, e, fs); + } }; -//some helper types +// some helper types using Buffer = std::vector; using OutputAdapter = bitsery::OutputBufferAdapter; using InputAdapter = bitsery::InputBufferAdapter; -int main() { - //set some random data - MyStruct data{8941, MyEnum::V2, {15.0f, -8.5f, 0.045f}}; - MyStruct res{}; +int +main() +{ + // set some random data + MyStruct data{ 8941, MyEnum::V2, { 15.0f, -8.5f, 0.045f } }; + MyStruct res{}; - //serialization, deserialization flow is unchanged as in basic usage - Buffer buffer; - auto writtenSize = bitsery::quickSerialization(buffer, data); + // serialization, deserialization flow is unchanged as in basic usage + Buffer buffer; + auto writtenSize = bitsery::quickSerialization(buffer, data); - auto state = bitsery::quickDeserialization({buffer.begin(), writtenSize}, res); + auto state = bitsery::quickDeserialization( + { buffer.begin(), writtenSize }, res); - assert(state.first == bitsery::ReaderError::NoError && state.second); - assert(data.fs == res.fs && data.i == res.i && data.e == res.e); + assert(state.first == bitsery::ReaderError::NoError && state.second); + assert(data.fs == res.fs && data.i == res.i && data.e == res.e); } diff --git a/examples/composite_types.cpp b/examples/composite_types.cpp index 5de3d75..dbe2320 100644 --- a/examples/composite_types.cpp +++ b/examples/composite_types.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include // include extensions to work with tuples and variants // these extesions only work with C++17 @@ -10,101 +10,126 @@ // let's include this extension to make it more interesting :) #include -struct MyStruct { - std::vector v{}; - float f{}; +struct MyStruct +{ + std::vector v{}; + float f{}; - bool operator==(const MyStruct& rhs) const { - return v == rhs.v && f == rhs.f; - } + bool operator==(const MyStruct& rhs) const + { + return v == rhs.v && f == rhs.f; + } }; template -void serialize(S& s, MyStruct& o) { - s.container4b(o.v, 1000); - s.value4b(o.f); +void +serialize(S& s, MyStruct& o) +{ + s.container4b(o.v, 1000); + s.value4b(o.f); } // this will be the type that we want to serialize/deserialize using MyTuple = std::tuple; using MyVariant = std::variant; -// define default serialize function for MyVariant, so that we could use quickSerialization/Deserialization functions +// define default serialize function for MyVariant, so that we could use +// quickSerialization/Deserialization functions template -void serialize(S& s, MyVariant& o) { - // in order to serialize a variant, it needs to know how to do it for all types - // we can do this simply by providing any callable object, that accepts serializer and type as arguments - s.ext(o, bitsery::ext::StdVariant{ - // specify how to serialize tuple by creating a lambda - [](S& s, MyTuple& o) { - // StdTuple is used exactly the same as StdVariant - s.ext(o, bitsery::ext::StdTuple{ - // this is convenient callable object to specify integral value size - // it is different equivalent to lambda [](auto& s, float&o) { s.value4b(o);} - bitsery::ext::OverloadValue{}, - // it is not required to provide MyStruct overload, because it we have defined 'serialize' function for it - }); - }, - // this might also be useful if you want to overload using extension - bitsery::ext::OverloadExtValue{}, - // you can even go further and instead of writing lambda for MyTuple you can as well compose the same functionality - // with OverloadExtObject, like this: - // (comment out MyTuple lambda, and uncomment this) - // ext::OverloadExtObject>>{}, +void +serialize(S& s, MyVariant& o) +{ + // in order to serialize a variant, it needs to know how to do it for all + // types we can do this simply by providing any callable object, that accepts + // serializer and type as arguments + s.ext( + o, + bitsery::ext::StdVariant{ + // specify how to serialize tuple by creating a lambda + [](S& s, MyTuple& o) { + // StdTuple is used exactly the same as StdVariant + s.ext( + o, + bitsery::ext::StdTuple{ + // this is convenient callable object to specify integral value size + // it is different equivalent to lambda [](auto& s, float&o) { + // s.value4b(o);} + bitsery::ext::OverloadValue{}, + // it is not required to provide MyStruct overload, because it we + // have defined 'serialize' function for it + }); + }, + // this might also be useful if you want to overload using extension + bitsery::ext::OverloadExtValue{}, + // you can even go further and instead of writing lambda for MyTuple you + // can as well compose the same functionality + // with OverloadExtObject, like this: + // (comment out MyTuple lambda, and uncomment this) + // ext::OverloadExtObject>>{}, - // we can also override default 'serialize' function by creating an overloading for that type - [](S& s, MyStruct& o) { - s.value4b(o.f); - s.container(o.v, 1000, [](S& s, int32_t& v) { - s.ext4b(v, bitsery::ext::CompactValue{}); - }); - }, - // NOTE. - // it is possible to provide "auto" as type parameter - // this will allow you to override all default 'serialize' functions - // but in this case it will not be called, because we have explicitly provided overloads for all variant types - // also note, that first parameter (serializer) is also "auto", this is required, so that it would be least specialized case - // otherwise it will not compile if you any ext::Overload* helper defined, because it will have ambiguous definitions - // (ext::OverLoad* defines (templated_type& s, concrete_type& o) and lambda would be (concrete_type& s, templated_type& o)) - [](auto& , auto&) { - assert(false); - } - }); + // we can also override default 'serialize' function by creating an + // overloading for that type + [](S& s, MyStruct& o) { + s.value4b(o.f); + s.container(o.v, 1000, [](S& s, int32_t& v) { + s.ext4b(v, bitsery::ext::CompactValue{}); + }); + }, + // NOTE. + // it is possible to provide "auto" as type parameter + // this will allow you to override all default 'serialize' functions + // but in this case it will not be called, because we have explicitly + // provided overloads for all variant types + // also note, that first parameter (serializer) is also "auto", this is + // required, so that it would be least specialized case + // otherwise it will not compile if you any ext::Overload* helper defined, + // because it will have ambiguous definitions + // (ext::OverLoad* defines (templated_type& s, concrete_type& o) and + // lambda would be (concrete_type& s, templated_type& o)) + [](auto&, auto&) { assert(false); } }); } - -//some helper types +// some helper types using Buffer = std::vector; using OutputAdapter = bitsery::OutputBufferAdapter; using InputAdapter = bitsery::InputBufferAdapter; -int main() { +int +main() +{ - //set some random data - MyVariant data{ MyTuple{-7549, {{-451, 2, 968, 75, 4, 156, 49}, 874.4f}} }; - MyVariant res{}; + // set some random data + MyVariant data{ MyTuple{ -7549, + { { -451, 2, 968, 75, 4, 156, 49 }, 874.4f } } }; + MyVariant res{}; - //create buffer to store data - Buffer buffer; - //use quick serialization function, - //it will use default configuration to setup all the nesessary steps - //and serialize data to container - auto writtenSize = bitsery::quickSerialization(buffer, data); + // create buffer to store data + Buffer buffer; + // use quick serialization function, + // it will use default configuration to setup all the nesessary steps + // and serialize data to container + auto writtenSize = bitsery::quickSerialization(buffer, data); - //same as serialization, but returns deserialization state as a pair - //first = error code, second = is buffer was successfully read from begin to the end. - auto state = bitsery::quickDeserialization({ buffer.begin(), writtenSize }, res); + // same as serialization, but returns deserialization state as a pair + // first = error code, second = is buffer was successfully read from begin to + // the end. + auto state = bitsery::quickDeserialization( + { buffer.begin(), writtenSize }, res); - assert(state.first == bitsery::ReaderError::NoError && state.second); - assert(data == res); + assert(state.first == bitsery::ReaderError::NoError && state.second); + assert(data == res); } #else #if defined(_MSC_VER) -#pragma message("C++17 and /Zc:__cplusplus option is required to enable this example") +#pragma message( \ + "C++17 and /Zc:__cplusplus option is required to enable this example") #else #pragma message("C++17 is required to enable this example") #endif -int main() { - return 0; +int +main() +{ + return 0; } #endif \ No newline at end of file diff --git a/examples/context_usage.cpp b/examples/context_usage.cpp index 0f0bb19..3001622 100644 --- a/examples/context_usage.cpp +++ b/examples/context_usage.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include #include @@ -8,91 +8,106 @@ namespace MyTypes { - struct Monster { - Monster() = default; - Monster(std::string _name, uint32_t minDmg, uint32_t maxDmg) - :name{_name}, minDamage{minDmg}, maxDamage{maxDmg} {} +struct Monster +{ + Monster() = default; + Monster(std::string _name, uint32_t minDmg, uint32_t maxDmg) + : name{ _name } + , minDamage{ minDmg } + , maxDamage{ maxDmg } + { + } - std::string name{}; - uint32_t minDamage{}; - uint32_t maxDamage{}; - //... - }; + std::string name{}; + uint32_t minDamage{}; + uint32_t maxDamage{}; + //... +}; - struct GameState { - std::vector monsters; - }; +struct GameState +{ + std::vector monsters; +}; - //default flow for monster - template - void serialize (S& s, Monster& o) { - s.text1b(o.name, 20); - s.value4b(o.minDamage); - s.value4b(o.maxDamage); - } +// default flow for monster +template +void +serialize(S& s, Monster& o) +{ + s.text1b(o.name, 20); + s.value4b(o.minDamage); + s.value4b(o.maxDamage); +} - template - void serialize(S& s, GameState &o) { - //we can have multiple types in context with std::tuple - //if data type doesn't match then it will be compile time error - //NOTE: if context is optional then you can call contextOrNull, and it will return null if T doesn't exists - auto maxMonsters = s.template context(); - auto& dmgRange = s.template context>(); +template +void +serialize(S& s, GameState& o) +{ + // we can have multiple types in context with std::tuple + // if data type doesn't match then it will be compile time error + // NOTE: if context is optional then you can call contextOrNull, and it + // will return null if T doesn't exists + auto maxMonsters = s.template context(); + auto& dmgRange = s.template context>(); - s.container(o.monsters, maxMonsters, [&dmgRange] (S& s, Monster& m) { - s.text1b(m.name, 20); - //we know min/max damage range for monsters, so we can use this range instead of full value - bitsery::ext::ValueRange range{dmgRange.first, dmgRange.second}; - //enable bit packing - s.enableBitPacking([&m, &range](typename S::BPEnabledType& sbp) { - sbp.ext(m.minDamage, range); - sbp.ext(m.maxDamage, range); - }); - }); - } + s.container(o.monsters, maxMonsters, [&dmgRange](S& s, Monster& m) { + s.text1b(m.name, 20); + // we know min/max damage range for monsters, so we can use this range + // instead of full value + bitsery::ext::ValueRange range{ dmgRange.first, dmgRange.second }; + // enable bit packing + s.enableBitPacking([&m, &range](typename S::BPEnabledType& sbp) { + sbp.ext(m.minDamage, range); + sbp.ext(m.maxDamage, range); + }); + }); +} } -//context can contain multiple types by wrapping these types in std::tuple -//in serialization function we can get type that we need like this: -// s.template context(); -//this templated version also works if our context is the same as cast: -// struct MyContext {...}; -// ... -// s.template context(); -//NOTE: -// if your context has no additional usage outside of serialization flow, -// then you can create it internally via configuration (see inheritance.cpp) +// context can contain multiple types by wrapping these types in std::tuple +// in serialization function we can get type that we need like this: +// s.template context(); +// this templated version also works if our context is the same as cast: +// struct MyContext {...}; +// ... +// s.template context(); +// NOTE: +// if your context has no additional usage outside of serialization flow, +// then you can create it internally via configuration (see inheritance.cpp) using Context = std::tuple>; -//use fixed-size buffer +// use fixed-size buffer using Buffer = std::vector; // define adapter types, using OutputAdapter = bitsery::OutputBufferAdapter; using InputAdapter = bitsery::InputBufferAdapter; -int main() { +int +main() +{ - MyTypes::GameState data{}; - data.monsters.push_back({"weaksy", 100, 200}); - data.monsters.push_back({"bigsy", 500, 1000}); - data.monsters.push_back({"tootoo", 350, 750}); + MyTypes::GameState data{}; + data.monsters.push_back({ "weaksy", 100, 200 }); + data.monsters.push_back({ "bigsy", 500, 1000 }); + data.monsters.push_back({ "tootoo", 350, 750 }); - //set context - Context ctx{}; - //max monsters - std::get<0>(ctx) = 4; - //damage range - std::get<1>(ctx).first = 100; - std::get<1>(ctx).second = 1000; + // set context + Context ctx{}; + // max monsters + std::get<0>(ctx) = 4; + // damage range + std::get<1>(ctx).first = 100; + std::get<1>(ctx).second = 1000; + // create buffer to store data to + Buffer buffer{}; + auto writtenSize = + bitsery::quickSerialization(ctx, OutputAdapter{ buffer }, data); - //create buffer to store data to - Buffer buffer{}; - auto writtenSize = bitsery::quickSerialization(ctx, OutputAdapter{buffer}, data); + MyTypes::GameState res{}; + auto state = bitsery::quickDeserialization( + ctx, InputAdapter{ buffer.begin(), writtenSize }, res); - MyTypes::GameState res{}; - auto state = bitsery::quickDeserialization(ctx, InputAdapter{buffer.begin(), writtenSize}, res); - - assert(state.first == bitsery::ReaderError::NoError && state.second); + assert(state.first == bitsery::ReaderError::NoError && state.second); } diff --git a/examples/file_stream.cpp b/examples/file_stream.cpp index 8016690..a83858c 100644 --- a/examples/file_stream.cpp +++ b/examples/file_stream.cpp @@ -1,55 +1,68 @@ #include -//in order to work with streams include stream adapter +// in order to work with streams include stream adapter #include #include #include -enum class MyEnum:uint16_t { V1,V2,V3 }; -struct MyStruct { - uint32_t i; - MyEnum e; - double f; +enum class MyEnum : uint16_t +{ + V1, + V2, + V3 +}; +struct MyStruct +{ + uint32_t i; + MyEnum e; + double f; }; -//define how object should be serialized/deserialized -template -void serialize(S& s, MyStruct& o) { - s.value4b(o.i); - s.value2b(o.e); - s.value8b(o.f); +// define how object should be serialized/deserialized +template +void +serialize(S& s, MyStruct& o) +{ + s.value4b(o.i); + s.value2b(o.e); + s.value8b(o.f); } -int main() { - //set some random data - MyStruct data{8941, MyEnum::V2, 0.045}; - MyStruct res{}; +int +main() +{ + // set some random data + MyStruct data{ 8941, MyEnum::V2, 0.045 }; + MyStruct res{}; - //open file stream for writing and reading - auto fileName = "test_file.bin"; - std::fstream s{fileName, s.binary | s.trunc | s.out}; - if (!s.is_open()) { - std::cout << "cannot open " << fileName << " for writing\n"; - return 0; - } + // open file stream for writing and reading + auto fileName = "test_file.bin"; + std::fstream s{ fileName, s.binary | s.trunc | s.out }; + if (!s.is_open()) { + std::cout << "cannot open " << fileName << " for writing\n"; + return 0; + } - //we cannot use quick serialization function, because streams cannot use writtenBytesCount method - bitsery::Serializer ser{s}; - ser.object(data); - //flush to writer - ser.adapter().flush(); - s.close(); - //reopen for reading + // we cannot use quick serialization function, because streams cannot use + // writtenBytesCount method + bitsery::Serializer ser{ s }; + ser.object(data); + // flush to writer + ser.adapter().flush(); + s.close(); + // reopen for reading - s.open(fileName, s.binary | s.in); - if (!s.is_open()) { - std::cout << "cannot open " << fileName << " for reading\n"; - return 0; - } + s.open(fileName, s.binary | s.in); + if (!s.is_open()) { + std::cout << "cannot open " << fileName << " for reading\n"; + return 0; + } - //same as serialization, but returns deserialization state as a pair - //first = error code, second = is buffer was successfully read from begin to the end. - auto state = bitsery::quickDeserialization(s, res); + // same as serialization, but returns deserialization state as a pair + // first = error code, second = is buffer was successfully read from begin to + // the end. + auto state = + bitsery::quickDeserialization(s, res); - assert(state.first == bitsery::ReaderError::NoError && state.second); - assert(data.f == res.f && data.i == res.i && data.e == res.e); + assert(state.first == bitsery::ReaderError::NoError && state.second); + assert(data.f == res.f && data.i == res.i && data.e == res.e); } diff --git a/examples/forward_backward_compatibility.cpp b/examples/forward_backward_compatibility.cpp index 4ce2161..0ac9f57 100644 --- a/examples/forward_backward_compatibility.cpp +++ b/examples/forward_backward_compatibility.cpp @@ -1,92 +1,116 @@ -#include #include -//include traits for types, that we'll be using -#include +#include +// include traits for types, that we'll be using #include +#include #include -//include extension that will allow to have backward/forward compatibility +// include extension that will allow to have backward/forward compatibility #include namespace MyTypes { - //define data - enum Color:uint8_t { Red, Green, Blue }; +// define data +enum Color : uint8_t +{ + Red, + Green, + Blue +}; - struct Vec3 { float x, y, z; }; +struct Vec3 +{ + float x, y, z; +}; - struct Weapon { - std::string name{}; - int16_t damage{}; - Weapon() = default; - Weapon(const std::string& _name, int16_t dmg):name{_name}, damage{dmg} {} - private: - //define serialize function as private, and give access to bitsery - friend bitsery::Access; - template - void serialize (S& s) { - //forward/backward compatibility for monsters - s.ext(*this, bitsery::ext::Growable{}, [](S& s, Weapon& o1) { - s.text1b(o1.name, 20); - s.value2b(o1.damage); - }); - } - }; +struct Weapon +{ + std::string name{}; + int16_t damage{}; + Weapon() = default; + Weapon(const std::string& _name, int16_t dmg) + : name{ _name } + , damage{ dmg } + { + } - struct Monster { - Vec3 pos; - int16_t mana; - int16_t hp; - std::string name; - std::vector inventory; - Color color; - std::vector weapons; - Weapon equipped; - std::vector path; - }; +private: + // define serialize function as private, and give access to bitsery + friend bitsery::Access; + template + void serialize(S& s) + { + // forward/backward compatibility for monsters + s.ext(*this, bitsery::ext::Growable{}, [](S& s, Weapon& o1) { + s.text1b(o1.name, 20); + s.value2b(o1.damage); + }); + } +}; - template - void serialize(S& s, Vec3& o) { - s.value4b(o.x); - s.value4b(o.y); - s.value4b(o.z); - } +struct Monster +{ + Vec3 pos; + int16_t mana; + int16_t hp; + std::string name; + std::vector inventory; + Color color; + std::vector weapons; + Weapon equipped; + std::vector path; +}; - template - void serialize (S& s, Monster& o) { - //forward/backward compatibility for monsters - s.ext(o, bitsery::ext::Growable{}, [](S& s, Monster& o1) { - s.value1b(o1.color); - s.value2b(o1.mana); - s.value2b(o1.hp); - s.object(o1.equipped); - s.object(o1.pos); - s.container(o1.path, 1000); - s.container(o1.weapons, 100); - s.container1b(o1.inventory, 50); - s.text1b(o1.name, 20); - }); - } +template +void +serialize(S& s, Vec3& o) +{ + s.value4b(o.x); + s.value4b(o.y); + s.value4b(o.z); } -//use fixed-size buffer +template +void +serialize(S& s, Monster& o) +{ + // forward/backward compatibility for monsters + s.ext(o, bitsery::ext::Growable{}, [](S& s, Monster& o1) { + s.value1b(o1.color); + s.value2b(o1.mana); + s.value2b(o1.hp); + s.object(o1.equipped); + s.object(o1.pos); + s.container(o1.path, 1000); + s.container(o1.weapons, 100); + s.container1b(o1.inventory, 50); + s.text1b(o1.name, 20); + }); +} +} + +// use fixed-size buffer using Buffer = std::array; using OutputAdapter = bitsery::OutputBufferAdapter; using InputAdapter = bitsery::InputBufferAdapter; -int main() { - //set some random data - MyTypes::Monster data{}; - data.name = "lew"; - data.weapons.push_back(MyTypes::Weapon{"GoodWeapon", 100}); +int +main() +{ + // set some random data + MyTypes::Monster data{}; + data.name = "lew"; + data.weapons.push_back(MyTypes::Weapon{ "GoodWeapon", 100 }); - //create buffer to store data to - Buffer buffer{}; - //since we're using different configuration, we cannot use quickSerialization function. - auto writtenSize = bitsery::quickSerialization(buffer, data); + // create buffer to store data to + Buffer buffer{}; + // since we're using different configuration, we cannot use quickSerialization + // function. + auto writtenSize = bitsery::quickSerialization(buffer, data); - MyTypes::Monster res{}; - //deserialize - auto state = bitsery::quickDeserialization({buffer.begin(), writtenSize}, res); + MyTypes::Monster res{}; + // deserialize + auto state = bitsery::quickDeserialization( + { buffer.begin(), writtenSize }, res); - assert(state.first == bitsery::ReaderError::NoError && state.second); + assert(state.first == bitsery::ReaderError::NoError && state.second); } diff --git a/examples/inheritance.cpp b/examples/inheritance.cpp index 8d46b2f..4866a7c 100644 --- a/examples/inheritance.cpp +++ b/examples/inheritance.cpp @@ -1,104 +1,136 @@ // -//this example covers all the corner cases that can happen using inheritance -//in reality virtual inherintance is usually avoided, so your code would look much simpler. +// this example covers all the corner cases that can happen using inheritance +// in reality virtual inherintance is usually avoided, so your code would look +// much simpler. // -#include #include +#include #include -//include inheritance extension -//this header contains two extensions, that specifies inheritance type of base class -// BaseClass - normal inheritance -// VirtualBaseClass - when virtual inheritance is used -//in order for virtual inheritance to work, InheritanceContext is required. for normal inheritance it is not required +// include inheritance extension +// this header contains two extensions, that specifies inheritance type of base +// class +// BaseClass - normal inheritance +// VirtualBaseClass - when virtual inheritance is used +// in order for virtual inheritance to work, InheritanceContext is required. for +// normal inheritance it is not required #include using bitsery::ext::BaseClass; using bitsery::ext::VirtualBaseClass; -struct Base { - uint8_t x{}; - //Base doesn't have to be polymorphic class, inheritance works at compile-time. +struct Base +{ + uint8_t x{}; + // Base doesn't have to be polymorphic class, inheritance works at + // compile-time. }; -template -void serialize(S& s, Base& o) { - s.value1b(o.x); +template +void +serialize(S& s, Base& o) +{ + s.value1b(o.x); } -struct Derive1:virtual Base {// virtually inherits from base - uint8_t y1{}; +struct Derive1 : virtual Base +{ // virtually inherits from base + uint8_t y1{}; }; -template -void serialize(S& s, Derive1& o) { - //define virtual inheritance, it will not compile if InheritanceContext is not defined in serializer/deserializer - s.ext(o, VirtualBaseClass{}); - s.value1b(o.y1); +template +void +serialize(S& s, Derive1& o) +{ + // define virtual inheritance, it will not compile if InheritanceContext is + // not defined in serializer/deserializer + s.ext(o, VirtualBaseClass{}); + s.value1b(o.y1); } -//to make it more interesting, serialize private member -struct Derived2:virtual Base { - explicit Derived2(uint8_t y):y2{y} {} +// to make it more interesting, serialize private member +struct Derived2 : virtual Base +{ + explicit Derived2(uint8_t y) + : y2{ y } + { + } + + uint8_t getY2() const { return y2; }; - uint8_t getY2() const { - return y2; - }; private: - friend bitsery::Access; - uint8_t y2{}; - template - void serialize(S& s) { - //notice virtual inheritance - s.ext(*this, VirtualBaseClass{}); - s.value1b(y2); - } + friend bitsery::Access; + uint8_t y2{}; + template + void serialize(S& s) + { + // notice virtual inheritance + s.ext(*this, VirtualBaseClass{}); + s.value1b(y2); + } }; -struct MultipleInheritance: Derive1, Derived2 { - explicit MultipleInheritance(uint8_t y2):Derived2{y2} {} - uint8_t z{}; +struct MultipleInheritance + : Derive1 + , Derived2 +{ + explicit MultipleInheritance(uint8_t y2) + : Derived2{ y2 } + { + } + uint8_t z{}; }; -template -void serialize(S& s, MultipleInheritance& o) { - //has two bases, serialize them separately - s.ext(o, BaseClass{}); - s.ext(o, BaseClass{}); - s.value1b(o.z); +template +void +serialize(S& s, MultipleInheritance& o) +{ + // has two bases, serialize them separately + s.ext(o, BaseClass{}); + s.ext(o, BaseClass{}); + s.value1b(o.z); } namespace bitsery { - // call to serialize function with Derived2 and MultipleInheritance is ambiguous, - // it matches two serialize functions: Base classes non-member fnc and Derived2 member fnc - // we need explicitly select which function to use - template <> - struct SelectSerializeFnc:UseMemberFnc {}; +// call to serialize function with Derived2 and MultipleInheritance is +// ambiguous, it matches two serialize functions: Base classes non-member fnc +// and Derived2 member fnc we need explicitly select which function to use +template<> +struct SelectSerializeFnc : UseMemberFnc +{ +}; - //multiple inheritance has non-member serialize function defined - template <> - struct SelectSerializeFnc:UseNonMemberFnc {}; +// multiple inheritance has non-member serialize function defined +template<> +struct SelectSerializeFnc : UseNonMemberFnc +{ +}; } -//some helper types +// some helper types using Buffer = std::vector; using Writer = bitsery::OutputBufferAdapter; using Reader = bitsery::InputBufferAdapter; -int main() { +int +main() +{ - MultipleInheritance data{98}; - data.x = 254; - data.y1 = 47; - data.z = 1; + MultipleInheritance data{ 98 }; + data.x = 254; + data.y1 = 47; + data.z = 1; - Buffer buf{}; + Buffer buf{}; - bitsery::ext::InheritanceContext ctx1; - auto writtenSize = bitsery::quickSerialization(ctx1, Writer{buf}, data); - assert(writtenSize == 4);//base is serialized once, because it is inherited virtually + bitsery::ext::InheritanceContext ctx1; + auto writtenSize = bitsery::quickSerialization(ctx1, Writer{ buf }, data); + assert(writtenSize == + 4); // base is serialized once, because it is inherited virtually - MultipleInheritance res{0}; - bitsery::ext::InheritanceContext ctx2; - auto state = bitsery::quickDeserialization(ctx2, Reader{buf.begin(), writtenSize}, res); - assert(state.first == bitsery::ReaderError::NoError && state.second); - assert(data.x == res.x && data.y1 == res.y1 && data.getY2() == res.getY2() && data.z == res.z); + MultipleInheritance res{ 0 }; + bitsery::ext::InheritanceContext ctx2; + auto state = bitsery::quickDeserialization( + ctx2, Reader{ buf.begin(), writtenSize }, res); + assert(state.first == bitsery::ReaderError::NoError && state.second); + assert(data.x == res.x && data.y1 == res.y1 && data.getY2() == res.getY2() && + data.z == res.z); } diff --git a/examples/non_default_constructible.cpp b/examples/non_default_constructible.cpp index f9379bf..f76773c 100644 --- a/examples/non_default_constructible.cpp +++ b/examples/non_default_constructible.cpp @@ -2,61 +2,73 @@ // example of how to deserialize non default constructible objects // -#include #include +#include #include -class MyData { - //define your private data - float _x{0}; - float _y{0}; - //make bitsery:Access friend - friend class bitsery::Access; - //create default constructor, don't worry about class invariant, it will be restored in deserialization - MyData() = default; - //define serialize function +class MyData +{ + // define your private data + float _x{ 0 }; + float _y{ 0 }; + // make bitsery:Access friend + friend class bitsery::Access; + // create default constructor, don't worry about class invariant, it will be + // restored in deserialization + MyData() = default; + // define serialize function + + template + void serialize(S& s) + { + s.value4b(_x); + s.value4b(_y); + } - template - void serialize(S& s) { - s.value4b(_x); - s.value4b(_y); - } public: - //define non default public constructor - MyData(float x, float y):_x{x}, _y{y} {} - //this is for convenience - bool operator ==(const MyData&rhs) const { - return _x == rhs._x && _y == rhs._y; - } + // define non default public constructor + MyData(float x, float y) + : _x{ x } + , _y{ y } + { + } + // this is for convenience + bool operator==(const MyData& rhs) const + { + return _x == rhs._x && _y == rhs._y; + } }; -//some helper types +// some helper types using Buffer = std::vector; using Writer = bitsery::OutputBufferAdapter; using Reader = bitsery::InputBufferAdapter; -int main() { +int +main() +{ - //initialize our data - std::vector data{}; - data.emplace_back(145.4f, 84.48f); - std::vector res{}; + // initialize our data + std::vector data{}; + data.emplace_back(145.4f, 84.48f); + std::vector res{}; - //create buffer - Buffer buffer{}; + // create buffer + Buffer buffer{}; - //we cant use quick (de)serialization helper methods, because we ant to serialize container directly - //create writer and serialize container - bitsery::Serializer ser{buffer}; - ser.container(data, 10); - ser.adapter().flush(); + // we cant use quick (de)serialization helper methods, because we ant to + // serialize container directly create writer and serialize container + bitsery::Serializer ser{ buffer }; + ser.container(data, 10); + ser.adapter().flush(); - //create reader and deserialize container - bitsery::Deserializer des{buffer.begin(), ser.adapter().writtenBytesCount()}; - des.container(res, 10); + // create reader and deserialize container + bitsery::Deserializer des{ buffer.begin(), + ser.adapter().writtenBytesCount() }; + des.container(res, 10); - //check if everything went ok - assert(des.adapter().error() == bitsery::ReaderError::NoError && des.adapter().isCompletedSuccessfully()); - assert(res == data); + // check if everything went ok + assert(des.adapter().error() == bitsery::ReaderError::NoError && + des.adapter().isCompletedSuccessfully()); + assert(res == data); } - diff --git a/examples/raw_pointers.cpp b/examples/raw_pointers.cpp index 0151ad3..d9357df 100644 --- a/examples/raw_pointers.cpp +++ b/examples/raw_pointers.cpp @@ -1,145 +1,166 @@ -#include #include +#include #include -//include pointers extension -//this header contains multiple extensions for different pointer types and pointer linking context, -//that validates pointer ownership and checks if there are and no dangling pointers after serialization/deserialization. -//dangling pointer in this context means, that non-owning pointer points to data, that was not serialized. +// include pointers extension +// this header contains multiple extensions for different pointer types and +// pointer linking context, that validates pointer ownership and checks if there +// are and no dangling pointers after serialization/deserialization. dangling +// pointer in this context means, that non-owning pointer points to data, that +// was not serialized. #include -using bitsery::ext::ReferencedByPointer; using bitsery::ext::PointerObserver; using bitsery::ext::PointerOwner; -using bitsery::ext::PointerType ; +using bitsery::ext::PointerType; +using bitsery::ext::ReferencedByPointer; -enum class MyEnum:uint16_t { V1,V2,V3 }; -struct MyStruct { - MyStruct(uint32_t i_, MyEnum e_, std::vector fs_) - :i{i_}, - e{e_}, - fs{fs_} {} - MyStruct():MyStruct{0, MyEnum::V1, {}} {} - uint32_t i; - MyEnum e; - std::vector fs; +enum class MyEnum : uint16_t +{ + V1, + V2, + V3 +}; +struct MyStruct +{ + MyStruct(uint32_t i_, MyEnum e_, std::vector fs_) + : i{ i_ } + , e{ e_ } + , fs{ fs_ } + { + } + MyStruct() + : MyStruct{ 0, MyEnum::V1, {} } + { + } + uint32_t i; + MyEnum e; + std::vector fs; }; -template -void serialize(S& s, MyStruct& o) { - s.value4b(o.i); - s.value2b(o.e); - s.container4b(o.fs, 10); +template +void +serialize(S& s, MyStruct& o) +{ + s.value4b(o.i); + s.value2b(o.e); + s.container4b(o.fs, 10); } -//our test data -struct Test1Data { - //regular data, nothing fancy here - MyStruct o1; - int32_t i1; - //these container elements can be referenced by pointers - std::vector vdata; - //container that holds non owning pointers (observers), - std::vector vptr; - //treat it as is observer - MyStruct* po1; - //we treat this as owner (responsible for allocation/deallocation - int32_t* pi1; +// our test data +struct Test1Data +{ + // regular data, nothing fancy here + MyStruct o1; + int32_t i1; + // these container elements can be referenced by pointers + std::vector vdata; + // container that holds non owning pointers (observers), + std::vector vptr; + // treat it as is observer + MyStruct* po1; + // we treat this as owner (responsible for allocation/deallocation + int32_t* pi1; private: - friend bitsery::Access; + friend bitsery::Access; - template - void serialize(S& s) { - //just a regular fields - s.object(o1); - s.value4b(i1); + template + void serialize(S& s) + { + // just a regular fields + s.object(o1); + s.value4b(i1); - //set container elements to be candidates for non-owning pointers - s.container(vdata, 100, [](S& s, MyStruct& d){ - s.ext(d, ReferencedByPointer{}); - }); - //contains non owning pointers - // - //IMPORTANT !!! - //ALWAYS ACCEPT BY REFERENCE like this: T* (&obj) - //if using c++14, then auto& always works. - // - //you can also serialize non owning pointers first, pointer linking context will keep track on them - //and as soon as pointer owner data is deserialized, all non-owning pointers will be updated - s.container(vptr, 100, [](S& s, MyStruct* (&d)){ - s.ext(d, PointerObserver{}); - }); - //observer - s.ext(po1, PointerObserver{}); - //owner, mark it as not null - s.ext4b(pi1, PointerOwner{PointerType::NotNull}); - - } + // set container elements to be candidates for non-owning pointers + s.container( + vdata, 100, [](S& s, MyStruct& d) { s.ext(d, ReferencedByPointer{}); }); + // contains non owning pointers + // + // IMPORTANT !!! + // ALWAYS ACCEPT BY REFERENCE like this: T* (&obj) + // if using c++14, then auto& always works. + // + // you can also serialize non owning pointers first, pointer linking context + // will keep track on them and as soon as pointer owner data is + // deserialized, all non-owning pointers will be updated + s.container( + vptr, 100, [](S& s, MyStruct*(&d)) { s.ext(d, PointerObserver{}); }); + // observer + s.ext(po1, PointerObserver{}); + // owner, mark it as not null + s.ext4b(pi1, PointerOwner{ PointerType::NotNull }); + } }; -//some helper types +// some helper types using Buffer = std::vector; using Writer = bitsery::OutputBufferAdapter; using Reader = bitsery::InputBufferAdapter; -//we will need PointerLinkingContext to work with pointers -//if we would require additional context for our own custom flow, we can define it as tuple like this: -// std::tuple -//and other code will work as expected as long as it cast to proper type. -//see context_usage.cpp for usage example +// we will need PointerLinkingContext to work with pointers +// if we would require additional context for our own custom flow, we can define +// it as tuple like this: +// std::tuple +// and other code will work as expected as long as it cast to proper type. +// see context_usage.cpp for usage example -int main() { - //set some random data - Test1Data data{}; - data.vdata.emplace_back(8941, MyEnum::V1, std::vector{4.4f}); - data.vdata.emplace_back(15478, MyEnum::V2, std::vector{15.0f}); - data.vdata.emplace_back(59, MyEnum::V3, std::vector{-8.5f, 0.045f}); - //container of non owning pointers (observers) - data.vptr.emplace_back(nullptr); - data.vptr.emplace_back(std::addressof(data.vdata[0])); - data.vptr.emplace_back(std::addressof(data.vdata[2])); - //regular fields - data.o1 = MyStruct{4, MyEnum::V2, {57.078f}}; - data.i1 = 9455; - //observer - data.po1 = std::addressof(data.vdata[1]); - //owning pointer - data.pi1 = new int32_t{}; +int +main() +{ + // set some random data + Test1Data data{}; + data.vdata.emplace_back(8941, MyEnum::V1, std::vector{ 4.4f }); + data.vdata.emplace_back(15478, MyEnum::V2, std::vector{ 15.0f }); + data.vdata.emplace_back(59, MyEnum::V3, std::vector{ -8.5f, 0.045f }); + // container of non owning pointers (observers) + data.vptr.emplace_back(nullptr); + data.vptr.emplace_back(std::addressof(data.vdata[0])); + data.vptr.emplace_back(std::addressof(data.vdata[2])); + // regular fields + data.o1 = MyStruct{ 4, MyEnum::V2, { 57.078f } }; + data.i1 = 9455; + // observer + data.po1 = std::addressof(data.vdata[1]); + // owning pointer + data.pi1 = new int32_t{}; - //create buffer to store data - Buffer buffer{}; - size_t writtenSize{}; - //in order to use pointers, we need to pass pointer linking context serializer/deserializer - { - bitsery::ext::PointerLinkingContext ctx{}; - writtenSize = quickSerialization(ctx, Writer{buffer}, data); + // create buffer to store data + Buffer buffer{}; + size_t writtenSize{}; + // in order to use pointers, we need to pass pointer linking context + // serializer/deserializer + { + bitsery::ext::PointerLinkingContext ctx{}; + writtenSize = quickSerialization(ctx, Writer{ buffer }, data); - //make sure that pointer linking context is valid - //this ensures that all non-owning pointers points to data that has been serialized, - //so we can successfully reconstruct pointers after deserialization - assert(ctx.isValid()); - } + // make sure that pointer linking context is valid + // this ensures that all non-owning pointers points to data that has been + // serialized, so we can successfully reconstruct pointers after + // deserialization + assert(ctx.isValid()); + } - Test1Data res{}; - { - bitsery::ext::PointerLinkingContext ctx{}; - auto state = quickDeserialization(ctx, Reader{buffer.begin(), writtenSize}, res); - //check if everything went find - assert(state.first == bitsery::ReaderError::NoError && state.second); - //also check for dangling pointers, after deserialization - assert(ctx.isValid()); - } - //owning pointers owns data - assert(*res.pi1 == *data.pi1); - assert(res.pi1 != data.pi1); - //observers, points to other data - assert(res.vptr[0] == nullptr); - assert(res.vptr[1] == std::addressof(res.vdata[0])); - assert(res.vptr[2] == std::addressof(res.vdata[2])); - assert(res.po1 == std::addressof(res.vdata[1])); + Test1Data res{}; + { + bitsery::ext::PointerLinkingContext ctx{}; + auto state = + quickDeserialization(ctx, Reader{ buffer.begin(), writtenSize }, res); + // check if everything went find + assert(state.first == bitsery::ReaderError::NoError && state.second); + // also check for dangling pointers, after deserialization + assert(ctx.isValid()); + } + // owning pointers owns data + assert(*res.pi1 == *data.pi1); + assert(res.pi1 != data.pi1); + // observers, points to other data + assert(res.vptr[0] == nullptr); + assert(res.vptr[1] == std::addressof(res.vdata[0])); + assert(res.vptr[2] == std::addressof(res.vdata[2])); + assert(res.po1 == std::addressof(res.vdata[1])); - //delete raw owning pointers - delete data.pi1; - delete res.pi1; + // delete raw owning pointers + delete data.pi1; + delete res.pi1; } diff --git a/examples/smart_pointers_with_polymorphism.cpp b/examples/smart_pointers_with_polymorphism.cpp index db30249..6412cd7 100644 --- a/examples/smart_pointers_with_polymorphism.cpp +++ b/examples/smart_pointers_with_polymorphism.cpp @@ -1,269 +1,309 @@ // // Created by fraillt on 18.4.26. // +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -//in order to work with polymorphic types, we need to describe few steps: -// 1) describe relationships between base and derived types -// this will allow to know what are possible types reachable from base class -// 2) bind serializer to base class -// this will allow to iterate through all types, and add serialization functions, -// without this step compiler would simply remove functions that are not bound at compile-time even it we use type at runtime. +// in order to work with polymorphic types, we need to describe few steps: +// 1) describe relationships between base and derived types +// this will allow to know what are possible types reachable from base class +// 2) bind serializer to base class +// this will allow to iterate through all types, and add serialization +// functions, without this step compiler would simply remove functions that are +// not bound at compile-time even it we use type at runtime. using bitsery::ext::BaseClass; using bitsery::ext::PointerObserver; using bitsery::ext::StdSmartPtr; -//define our data structures -struct Color { - float r{}, g{}, b{}; - bool operator == (const Color& o) const { - return std::tie(r, g, b) == - std::tie(o.r, o.g, o.b); - } - +// define our data structures +struct Color +{ + float r{}, g{}, b{}; + bool operator==(const Color& o) const + { + return std::tie(r, g, b) == std::tie(o.r, o.g, o.b); + } }; -struct Shape { - Color clr{}; - virtual ~Shape() = 0; +struct Shape +{ + Color clr{}; + virtual ~Shape() = 0; }; Shape::~Shape() = default; -struct Circle : Shape { - int32_t radius{}; - bool operator == (const Circle& o) const { - return std::tie(radius, clr) == - std::tie(o.radius, o.clr); - } - +struct Circle : Shape +{ + int32_t radius{}; + bool operator==(const Circle& o) const + { + return std::tie(radius, clr) == std::tie(o.radius, o.clr); + } }; -struct Rectangle : Shape { - int32_t width{}; - int32_t height{}; - bool operator == (const Rectangle& o) const { - return std::tie(width, height, clr) == - std::tie(o.width, o.height, o.clr); - } +struct Rectangle : Shape +{ + int32_t width{}; + int32_t height{}; + bool operator==(const Rectangle& o) const + { + return std::tie(width, height, clr) == std::tie(o.width, o.height, o.clr); + } }; -struct RoundedRectangle : Rectangle { - int32_t radius{}; - bool operator == (const RoundedRectangle& o) const { - return std::tie(radius, static_cast(*this)) == - std::tie(o.radius, static_cast(o)); - } +struct RoundedRectangle : Rectangle +{ + int32_t radius{}; + bool operator==(const RoundedRectangle& o) const + { + return std::tie(radius, static_cast(*this)) == + std::tie(o.radius, static_cast(o)); + } }; -//define serialization functions +// define serialization functions template -void serialize(S &s, Color &o) { - //in real world scenario, it might be possible to serialize this using ValueRange, to map values in smaller space - //but for the sake of this example keep it simple - s.value4b(o.r); - s.value4b(o.g); - s.value4b(o.b); +void +serialize(S& s, Color& o) +{ + // in real world scenario, it might be possible to serialize this using + // ValueRange, to map values in smaller space but for the sake of this example + // keep it simple + s.value4b(o.r); + s.value4b(o.g); + s.value4b(o.b); } template -void serialize(S &s, Shape &o) { - s.object(o.clr); +void +serialize(S& s, Shape& o) +{ + s.object(o.clr); } template -void serialize(S &s, Circle &o) { - s.ext(o, bitsery::ext::BaseClass{}); - s.value4b(o.radius); +void +serialize(S& s, Circle& o) +{ + s.ext(o, bitsery::ext::BaseClass{}); + s.value4b(o.radius); } template -void serialize(S &s, Rectangle &o) { - s.ext(o, bitsery::ext::BaseClass{}); - s.value4b(o.width); - s.value4b(o.height); +void +serialize(S& s, Rectangle& o) +{ + s.ext(o, bitsery::ext::BaseClass{}); + s.value4b(o.width); + s.value4b(o.height); } template -void serialize(S &s, RoundedRectangle &o) { - s.ext(o, bitsery::ext::BaseClass{}); - s.value4b(o.radius); +void +serialize(S& s, RoundedRectangle& o) +{ + s.ext(o, bitsery::ext::BaseClass{}); + s.value4b(o.radius); } -//define our test structure -struct SomeShapes { - std::vector> sharedList; - std::unique_ptr uniquePtr; - //weak ptr and refPtr will point to sharedList - std::weak_ptr weakPtr; - Shape* refPtr; +// define our test structure +struct SomeShapes +{ + std::vector> sharedList; + std::unique_ptr uniquePtr; + // weak ptr and refPtr will point to sharedList + std::weak_ptr weakPtr; + Shape* refPtr; }; -//creates object, and populates some data -SomeShapes createData() { - SomeShapes data{}; - { - auto tmp = new RoundedRectangle{}; - tmp->height = 151572; - tmp->width = 488795; - tmp->radius = 898; - tmp->clr.r = 0.5f; - tmp->clr.g = 1.0f; - tmp->clr.b = 1.0f; - data.uniquePtr.reset(tmp); - } - { - auto tmp = new Circle{}; - tmp->radius = 75987; - tmp->clr.r = 0.5f; - tmp->clr.g = 0.0f; - tmp->clr.b = 1.0f; - data.sharedList.emplace_back(tmp); - } - { - auto tmp = new Rectangle{}; - tmp->height = 15157; - tmp->width = 48879; - tmp->clr.r = 1.0f; - tmp->clr.g = 0.0f; - tmp->clr.b = 0.0f; - data.sharedList.emplace_back(tmp); - } - data.weakPtr = data.sharedList[0]; - data.refPtr = data.sharedList[1].get(); +// creates object, and populates some data +SomeShapes +createData() +{ + SomeShapes data{}; + { + auto tmp = new RoundedRectangle{}; + tmp->height = 151572; + tmp->width = 488795; + tmp->radius = 898; + tmp->clr.r = 0.5f; + tmp->clr.g = 1.0f; + tmp->clr.b = 1.0f; + data.uniquePtr.reset(tmp); + } + { + auto tmp = new Circle{}; + tmp->radius = 75987; + tmp->clr.r = 0.5f; + tmp->clr.g = 0.0f; + tmp->clr.b = 1.0f; + data.sharedList.emplace_back(tmp); + } + { + auto tmp = new Rectangle{}; + tmp->height = 15157; + tmp->width = 48879; + tmp->clr.r = 1.0f; + tmp->clr.g = 0.0f; + tmp->clr.b = 0.0f; + data.sharedList.emplace_back(tmp); + } + data.weakPtr = data.sharedList[0]; + data.refPtr = data.sharedList[1].get(); - return data; + return data; } - template -void serialize(S &s, SomeShapes &o) { - s.ext(o.uniquePtr, StdSmartPtr{}); - // to make things more interesting first serialize weakPtr and refPtr, - // even though objects that weakPtr and refPtr is serialized later, - // bitsery will work regardless - s.ext(o.weakPtr, StdSmartPtr{}); - s.ext(o.refPtr, PointerObserver{}); - s.container(o.sharedList, 100, [](S& s, std::shared_ptr &item) { - s.ext(item, StdSmartPtr{}); - }); +void +serialize(S& s, SomeShapes& o) +{ + s.ext(o.uniquePtr, StdSmartPtr{}); + // to make things more interesting first serialize weakPtr and refPtr, + // even though objects that weakPtr and refPtr is serialized later, + // bitsery will work regardless + s.ext(o.weakPtr, StdSmartPtr{}); + s.ext(o.refPtr, PointerObserver{}); + s.container(o.sharedList, 100, [](S& s, std::shared_ptr& item) { + s.ext(item, StdSmartPtr{}); + }); } // STEP 1 // define relationships between base and derived classes namespace bitsery { - namespace ext { +namespace ext { - //for each base class define DIRECTLY derived classes - //e.g. PolymorphicBaseClass : PolymorphicDerivedClasses - // is incorrect, because RoundedRectangle does not directly derive from Shape - template<> - struct PolymorphicBaseClass : PolymorphicDerivedClasses { - }; +// for each base class define DIRECTLY derived classes +// e.g. PolymorphicBaseClass : PolymorphicDerivedClasses +// is incorrect, because RoundedRectangle does not directly derive from Shape +template<> +struct PolymorphicBaseClass + : PolymorphicDerivedClasses +{ +}; - template<> - struct PolymorphicBaseClass : PolymorphicDerivedClasses { - }; - } +template<> +struct PolymorphicBaseClass + : PolymorphicDerivedClasses +{ +}; +} } -// convenient type that stores all our types, so that we could easily register and -// also it automatically ensures, that classes is registered in the same order for serialization and deserialization -using MyPolymorphicClassesForRegistering = bitsery::ext::PolymorphicClassesList; +// convenient type that stores all our types, so that we could easily register +// and also it automatically ensures, that classes is registered in the same +// order for serialization and deserialization +using MyPolymorphicClassesForRegistering = + bitsery::ext::PolymorphicClassesList; -//some helper types +// some helper types using Buffer = std::vector; using Writer = bitsery::OutputBufferAdapter; using Reader = bitsery::InputBufferAdapter; -//we need to define few things in order to work with polymorphism -//1) we need pointer linking context to work with pointers -//2) we need polymorphic context to be able to work with polymorphic types -using TContext = std::tuple< - bitsery::ext::PointerLinkingContext, - bitsery::ext::PolymorphicContext>; -//NOTE: -// RTTI can be customizable, if you can't use dynamic_cast and typeid, and have 'custom' solution +// we need to define few things in order to work with polymorphism +// 1) we need pointer linking context to work with pointers +// 2) we need polymorphic context to be able to work with polymorphic types +using TContext = + std::tuple>; +// NOTE: +// RTTI can be customizable, if you can't use dynamic_cast and typeid, and have +// 'custom' solution using MySerializer = bitsery::Serializer; using MyDeserializer = bitsery::Deserializer; -//checks if deserialized data is equal -void assertSameShapes(const SomeShapes &data, const SomeShapes &res) { - { - auto d = dynamic_cast(data.uniquePtr.get()); - auto r = dynamic_cast(res.uniquePtr.get()); - assert(r != nullptr); - assert(*d == *r); - } - { - auto d = dynamic_cast(data.sharedList[0].get()); - auto r = dynamic_cast(res.sharedList[0].get()); - assert(r != nullptr); - assert(*d == *r); - } - { - auto d = dynamic_cast(data.sharedList[1].get()); - auto r = dynamic_cast(res.sharedList[1].get()); - assert(r != nullptr); - assert(*d == *r); - } - assert(res.weakPtr.lock().get() == res.sharedList[0].get()); - assert(res.refPtr == res.sharedList[1].get()); +// checks if deserialized data is equal +void +assertSameShapes(const SomeShapes& data, const SomeShapes& res) +{ + { + auto d = dynamic_cast(data.uniquePtr.get()); + auto r = dynamic_cast(res.uniquePtr.get()); + assert(r != nullptr); + assert(*d == *r); + } + { + auto d = dynamic_cast(data.sharedList[0].get()); + auto r = dynamic_cast(res.sharedList[0].get()); + assert(r != nullptr); + assert(*d == *r); + } + { + auto d = dynamic_cast(data.sharedList[1].get()); + auto r = dynamic_cast(res.sharedList[1].get()); + assert(r != nullptr); + assert(*d == *r); + } + assert(res.weakPtr.lock().get() == res.sharedList[0].get()); + assert(res.refPtr == res.sharedList[1].get()); } -int main() { +int +main() +{ - auto data = createData(); + auto data = createData(); - //create buffer to store data - Buffer buffer{}; - size_t writtenSize{}; - // we will not use quickSerialization/Deserialization functions to show, that we need to register polymorphic classes, explicitly - { + // create buffer to store data + Buffer buffer{}; + size_t writtenSize{}; + // we will not use quickSerialization/Deserialization functions to show, that + // we need to register polymorphic classes, explicitly + { - //STEP 2 - // before start serialization/deserialization, - // bind it with base polymorphic types, it will go through all reachable classes that is defined in first step. - // NOTE: you dont need to add Rectangle to reach for RoundedRectangle - TContext ctx{}; - std::get<1>(ctx).registerBasesList(MyPolymorphicClassesForRegistering{}); - //create writer and serialize - MySerializer ser{ctx, buffer}; - ser.object(data); - ser.adapter().flush(); - writtenSize = ser.adapter().writtenBytesCount(); + // STEP 2 + // before start serialization/deserialization, + // bind it with base polymorphic types, it will go through all reachable + // classes that is defined in first step. NOTE: you dont need to add + // Rectangle to reach for RoundedRectangle + TContext ctx{}; + std::get<1>(ctx).registerBasesList( + MyPolymorphicClassesForRegistering{}); + // create writer and serialize + MySerializer ser{ ctx, buffer }; + ser.object(data); + ser.adapter().flush(); + writtenSize = ser.adapter().writtenBytesCount(); - //make sure that pointer linking context is valid - //this ensures that all non-owning pointers points to data that has been serialized, - //so we can successfully reconstruct pointers after deserialization - assert(std::get<0>(ctx).isValid()); - } - SomeShapes res{}; - { - TContext ctx{}; - std::get<1>(ctx).registerBasesList(MyPolymorphicClassesForRegistering{}); - //deserialize our data - MyDeserializer des{ctx, buffer.begin(), writtenSize}; - des.object(res); - assert(des.adapter().error() == bitsery::ReaderError::NoError && des.adapter().isCompletedSuccessfully()); - //also check for dangling pointers, after deserialization - assert(std::get<0>(ctx).isValid()); - // clear shared state from pointer linking context, - // it is only required if there are any pointers that manage shared state, e.g. std::shared_ptr - assert(res.weakPtr.use_count() == 2);//one in sharedList and one in pointer linking context - std::get<0>(ctx).clearSharedState(); - assert(res.weakPtr.use_count() == 1); - } - assertSameShapes(data, res); - return 0; + // make sure that pointer linking context is valid + // this ensures that all non-owning pointers points to data that has been + // serialized, so we can successfully reconstruct pointers after + // deserialization + assert(std::get<0>(ctx).isValid()); + } + SomeShapes res{}; + { + TContext ctx{}; + std::get<1>(ctx).registerBasesList( + MyPolymorphicClassesForRegistering{}); + // deserialize our data + MyDeserializer des{ ctx, buffer.begin(), writtenSize }; + des.object(res); + assert(des.adapter().error() == bitsery::ReaderError::NoError && + des.adapter().isCompletedSuccessfully()); + // also check for dangling pointers, after deserialization + assert(std::get<0>(ctx).isValid()); + // clear shared state from pointer linking context, + // it is only required if there are any pointers that manage shared state, + // e.g. std::shared_ptr + assert(res.weakPtr.use_count() == + 2); // one in sharedList and one in pointer linking context + std::get<0>(ctx).clearSharedState(); + assert(res.weakPtr.use_count() == 1); + } + assertSameShapes(data, res); + return 0; } diff --git a/format.sh b/format.sh new file mode 100755 index 0000000..ec3df38 --- /dev/null +++ b/format.sh @@ -0,0 +1,3 @@ +find . -regex '.*\.\(cpp\|hpp\|cu\|c\|h\)' -exec clang-format -style=file -i {} \; + + diff --git a/include/bitsery/adapter/buffer.h b/include/bitsery/adapter/buffer.h index 05cd115..7dc8ae8 100644 --- a/include/bitsery/adapter/buffer.h +++ b/include/bitsery/adapter/buffer.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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_ADAPTER_BUFFER_H #define BITSERY_ADAPTER_BUFFER_H @@ -31,231 +31,265 @@ namespace bitsery { - template - class InputBufferAdapter: public details::InputAdapterBaseCRTP> { - public: - friend details::InputAdapterBaseCRTP>; +template +class InputBufferAdapter + : public details::InputAdapterBaseCRTP> +{ +public: + friend details::InputAdapterBaseCRTP>; - using BitPackingEnabled = details::InputAdapterBitPackingWrapper>; - using TConfig = Config; - using TIterator = typename traits::BufferAdapterTraits::type>::TConstIterator; - using TValue = typename traits::BufferAdapterTraits::type>::TValue; - static_assert(details::IsDefined::value, - "Please define BufferAdapterTraits or include from "); - static_assert(traits::ContainerTraits::type>::isContiguous, - "BufferAdapter only works with contiguous containers"); - static_assert(sizeof(TValue) == 1, "BufferAdapter underlying type must be 1byte."); + using BitPackingEnabled = + details::InputAdapterBitPackingWrapper>; + using TConfig = Config; + using TIterator = typename traits::BufferAdapterTraits< + typename std::remove_const::type>::TConstIterator; + using TValue = typename traits::BufferAdapterTraits< + typename std::remove_const::type>::TValue; + static_assert( + details::IsDefined::value, + "Please define BufferAdapterTraits or include from "); + static_assert(traits::ContainerTraits< + typename std::remove_const::type>::isContiguous, + "BufferAdapter only works with contiguous containers"); + static_assert(sizeof(TValue) == 1, + "BufferAdapter underlying type must be 1byte."); - InputBufferAdapter(TIterator beginIt, size_t size) - : _beginIt{beginIt}, - _currOffset{0}, - _endReadOffset{size}, - _bufferSize{size} { - }; + InputBufferAdapter(TIterator beginIt, size_t size) + : _beginIt{ beginIt } + , _currOffset{ 0 } + , _endReadOffset{ size } + , _bufferSize{ size } {}; - InputBufferAdapter(TIterator beginIt, TIterator endIt) - :InputBufferAdapter(beginIt, static_cast(std::distance(beginIt, endIt))) { - } + InputBufferAdapter(TIterator beginIt, TIterator endIt) + : InputBufferAdapter(beginIt, + static_cast(std::distance(beginIt, endIt))) + { + } - InputBufferAdapter(const InputBufferAdapter&) = delete; - InputBufferAdapter& operator=(const InputBufferAdapter&) = delete; + InputBufferAdapter(const InputBufferAdapter&) = delete; + InputBufferAdapter& operator=(const InputBufferAdapter&) = delete; - InputBufferAdapter(InputBufferAdapter&&) = default; - InputBufferAdapter& operator = (InputBufferAdapter&&) = default; + InputBufferAdapter(InputBufferAdapter&&) = default; + InputBufferAdapter& operator=(InputBufferAdapter&&) = default; - void currentReadPos(size_t pos) { - currentReadPosChecked(pos, std::integral_constant{}); - } + void currentReadPos(size_t pos) + { + currentReadPosChecked( + pos, std::integral_constant{}); + } - size_t currentReadPos() const { - return currentReadPosChecked(std::integral_constant{}); - } + size_t currentReadPos() const + { + return currentReadPosChecked( + std::integral_constant{}); + } - void currentReadEndPos(size_t pos) { - // assert that CheckAdapterErrors is enabled, otherwise it will simply will not work even if data and buffer is not corrupted - static_assert(Config::CheckAdapterErrors, "Please enable CheckAdapterErrors to use this functionality."); - if (_bufferSize >= pos && error() == ReaderError::NoError) { - _overflowOnReadEndPos = pos == 0; - if (pos == 0) - pos = _bufferSize; - _endReadOffset = pos; - } else { - error(ReaderError::DataOverflow); - } - } + void currentReadEndPos(size_t pos) + { + // assert that CheckAdapterErrors is enabled, otherwise it will simply will + // not work even if data and buffer is not corrupted + static_assert( + Config::CheckAdapterErrors, + "Please enable CheckAdapterErrors to use this functionality."); + if (_bufferSize >= pos && error() == ReaderError::NoError) { + _overflowOnReadEndPos = pos == 0; + if (pos == 0) + pos = _bufferSize; + _endReadOffset = pos; + } else { + error(ReaderError::DataOverflow); + } + } - size_t currentReadEndPos() const { - if (_overflowOnReadEndPos) - return 0; - return _endReadOffset; - } + size_t currentReadEndPos() const + { + if (_overflowOnReadEndPos) + return 0; + return _endReadOffset; + } - ReaderError error() const { - return _currOffset <= _endReadOffset - ? ReaderError::NoError - : static_cast(_currOffset - _endReadOffset); - } + ReaderError error() const + { + return _currOffset <= _endReadOffset + ? ReaderError::NoError + : static_cast(_currOffset - _endReadOffset); + } - void error(ReaderError error) { - if (_currOffset <= _endReadOffset) { - _endReadOffset = 0; - _bufferSize = 0; - _currOffset = static_cast(error); - } - } + void error(ReaderError error) + { + if (_currOffset <= _endReadOffset) { + _endReadOffset = 0; + _bufferSize = 0; + _currOffset = static_cast(error); + } + } - bool isCompletedSuccessfully() const { - return _currOffset == _bufferSize; - } + bool isCompletedSuccessfully() const { return _currOffset == _bufferSize; } - private: - using diff_t = typename std::iterator_traits::difference_type; +private: + using diff_t = typename std::iterator_traits::difference_type; - template - void readInternalValue(TValue *data) { - readInternalImpl(data, SIZE, std::integral_constant{}); - } + template + void readInternalValue(TValue* data) + { + readInternalImpl( + data, SIZE, std::integral_constant{}); + } - void readInternalBuffer(TValue *data, size_t size) { - readInternalImpl(data, size, std::integral_constant{}); - } + void readInternalBuffer(TValue* data, size_t size) + { + readInternalImpl( + data, size, std::integral_constant{}); + } - void readInternalImpl(TValue * data, size_t size, std::false_type) { - const size_t newOffset = _currOffset + size; - assert(newOffset <= _endReadOffset); - std::copy_n(_beginIt + static_cast(_currOffset), size, data); - _currOffset = newOffset; - } + void readInternalImpl(TValue* data, size_t size, std::false_type) + { + const size_t newOffset = _currOffset + size; + assert(newOffset <= _endReadOffset); + std::copy_n(_beginIt + static_cast(_currOffset), size, data); + _currOffset = newOffset; + } - void readInternalImpl(TValue *data, size_t size, std::true_type) { - const size_t newOffset = _currOffset + size; - if (newOffset <= _endReadOffset) { - std::copy_n(_beginIt + static_cast(_currOffset), size, data); - _currOffset = newOffset; - } else { - //set everything to zeros - std::memset(data, 0, size); - if (_overflowOnReadEndPos) - error(ReaderError::DataOverflow); - } - } + void readInternalImpl(TValue* data, size_t size, std::true_type) + { + const size_t newOffset = _currOffset + size; + if (newOffset <= _endReadOffset) { + std::copy_n(_beginIt + static_cast(_currOffset), size, data); + _currOffset = newOffset; + } else { + // set everything to zeros + std::memset(data, 0, size); + if (_overflowOnReadEndPos) + error(ReaderError::DataOverflow); + } + } - void currentReadPosChecked(size_t pos, std::true_type) { - if (_bufferSize >= pos && error() == ReaderError::NoError) { - _currOffset = pos; - } else { - error(ReaderError::DataOverflow); - } - } + void currentReadPosChecked(size_t pos, std::true_type) + { + if (_bufferSize >= pos && error() == ReaderError::NoError) { + _currOffset = pos; + } else { + error(ReaderError::DataOverflow); + } + } - void currentReadPosChecked(size_t pos, std::false_type) { - _currOffset = pos; - } + void currentReadPosChecked(size_t pos, std::false_type) { _currOffset = pos; } - size_t currentReadPosChecked(std::true_type) const { - return error() == ReaderError::NoError ? _currOffset : 0; - } + size_t currentReadPosChecked(std::true_type) const + { + return error() == ReaderError::NoError ? _currOffset : 0; + } - size_t currentReadPosChecked(std::false_type) const { - return _currOffset; - } + size_t currentReadPosChecked(std::false_type) const { return _currOffset; } + TIterator _beginIt; + size_t _currOffset; + size_t _endReadOffset; + size_t _bufferSize; + bool _overflowOnReadEndPos = true; +}; - TIterator _beginIt; - size_t _currOffset; - size_t _endReadOffset; - size_t _bufferSize; - bool _overflowOnReadEndPos = true; - }; +template +class OutputBufferAdapter + : public details::OutputAdapterBaseCRTP> +{ +public: + friend details::OutputAdapterBaseCRTP>; - template - class OutputBufferAdapter: public details::OutputAdapterBaseCRTP> { - public: - friend details::OutputAdapterBaseCRTP>; + using BitPackingEnabled = details::OutputAdapterBitPackingWrapper< + OutputBufferAdapter>; + using TConfig = Config; + using TIterator = typename traits::BufferAdapterTraits::TIterator; + using TValue = typename traits::BufferAdapterTraits::TValue; - using BitPackingEnabled = details::OutputAdapterBitPackingWrapper>; - using TConfig = Config; - using TIterator = typename traits::BufferAdapterTraits::TIterator; - using TValue = typename traits::BufferAdapterTraits::TValue; + static_assert( + details::IsDefined::value, + "Please define BufferAdapterTraits or include from "); + static_assert(traits::ContainerTraits::isContiguous, + "BufferAdapter only works with contiguous containers"); + static_assert(sizeof(TValue) == 1, + "BufferAdapter underlying type must be 1byte."); - static_assert(details::IsDefined::value, - "Please define BufferAdapterTraits or include from "); - static_assert(traits::ContainerTraits::isContiguous, - "BufferAdapter only works with contiguous containers"); - static_assert(sizeof(TValue) == 1, "BufferAdapter underlying type must be 1byte."); + OutputBufferAdapter(Buffer& buffer) + : _buffer{ std::addressof(buffer) } + , _beginIt{ std::begin(buffer) } + , _bufferSize{ traits::ContainerTraits::size(buffer) } + { + } - OutputBufferAdapter(Buffer &buffer) - : _buffer{std::addressof(buffer)}, - _beginIt{std::begin(buffer)}, - _bufferSize{traits::ContainerTraits::size(buffer)} { - } + OutputBufferAdapter(const OutputBufferAdapter&) = delete; + OutputBufferAdapter& operator=(const OutputBufferAdapter&) = delete; + OutputBufferAdapter(OutputBufferAdapter&&) = default; + OutputBufferAdapter& operator=(OutputBufferAdapter&&) = default; - OutputBufferAdapter(const OutputBufferAdapter&) = delete; - OutputBufferAdapter& operator=(const OutputBufferAdapter&) = delete; - OutputBufferAdapter(OutputBufferAdapter&&) = default; - OutputBufferAdapter& operator = (OutputBufferAdapter&&) = default; + void currentWritePos(size_t pos) + { + const auto maxPos = _currOffset > pos ? _currOffset : pos; + if (maxPos > _biggestCurrentPos) { + _biggestCurrentPos = maxPos; + } + maybeResize(pos, TResizable{}); + _currOffset = pos; + } - void currentWritePos(size_t pos) { - const auto maxPos = _currOffset > pos ? _currOffset : pos; - if (maxPos > _biggestCurrentPos) { - _biggestCurrentPos = maxPos; - } - maybeResize(pos, TResizable{}); - _currOffset = pos; - } + size_t currentWritePos() const { return _currOffset; } - size_t currentWritePos() const { - return _currOffset; - } + void flush() + { + // this function might be useful for stream adapters + } - void flush() { - //this function might be useful for stream adapters - } + size_t writtenBytesCount() const + { + return _currOffset > _biggestCurrentPos ? _currOffset : _biggestCurrentPos; + } - size_t writtenBytesCount() const { - return _currOffset > _biggestCurrentPos ? _currOffset : _biggestCurrentPos; - } +private: + using TResizable = + std::integral_constant::isResizable>; + using diff_t = typename std::iterator_traits::difference_type; - private: - using TResizable = std::integral_constant::isResizable>; - using diff_t = typename std::iterator_traits::difference_type; + template + void writeInternalValue(const TValue* data) + { + writeInternalImpl(data, SIZE); + } - template - void writeInternalValue(const TValue *data) { - writeInternalImpl(data, SIZE); - } + void writeInternalBuffer(const TValue* data, size_t size) + { + writeInternalImpl(data, size); + } - void writeInternalBuffer(const TValue *data, size_t size) { - writeInternalImpl(data, size); - } + Buffer* _buffer; + TIterator _beginIt; + size_t _currOffset{ 0 }; + size_t _bufferSize{ 0 }; + size_t _biggestCurrentPos{ 0 }; - Buffer* _buffer; - TIterator _beginIt; - size_t _currOffset{0}; - size_t _bufferSize{0}; - size_t _biggestCurrentPos{0}; + void maybeResize(size_t newOffset, std::true_type) + { + if (newOffset > _bufferSize) { + traits::BufferAdapterTraits::increaseBufferSize( + *_buffer, _currOffset, newOffset); + _beginIt = std::begin(*_buffer); + _bufferSize = traits::ContainerTraits::size(*_buffer); + } + } - void maybeResize(size_t newOffset, std::true_type) { - if (newOffset > _bufferSize) { - traits::BufferAdapterTraits::increaseBufferSize(*_buffer, _currOffset, newOffset); - _beginIt = std::begin(*_buffer); - _bufferSize = traits::ContainerTraits::size(*_buffer); - } - } + void maybeResize(size_t newOffset, std::false_type) + { + assert(newOffset <= _bufferSize); + } - void maybeResize(size_t newOffset, std::false_type) { - assert(newOffset <= _bufferSize); - } - - void writeInternalImpl(const TValue *data, size_t size) { - const size_t newOffset = _currOffset + size; - maybeResize(newOffset, TResizable{}); - std::copy_n(data, size, _beginIt + static_cast(_currOffset)); - _currOffset = newOffset; - } - - }; + void writeInternalImpl(const TValue* data, size_t size) + { + const size_t newOffset = _currOffset + size; + maybeResize(newOffset, TResizable{}); + std::copy_n(data, size, _beginIt + static_cast(_currOffset)); + _currOffset = newOffset; + } +}; } -#endif //BITSERY_ADAPTER_BUFFER_H +#endif // BITSERY_ADAPTER_BUFFER_H diff --git a/include/bitsery/adapter/measure_size.h b/include/bitsery/adapter/measure_size.h index 3f6ef68..4c0d9c3 100644 --- a/include/bitsery/adapter/measure_size.h +++ b/include/bitsery/adapter/measure_size.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. +// 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_ADAPTER_MEASURE_SIZE_H #define BITSERY_ADAPTER_MEASURE_SIZE_H @@ -29,60 +29,60 @@ namespace bitsery { +template +class BasicMeasureSize +{ +public: + using BitPackingEnabled = + details::BasicMeasureSizeBitPackingWrapper>; + using TConfig = Config; + using TValue = void; - template - class BasicMeasureSize { - public: + template + void writeBytes(const T&) + { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); + _currPos += SIZE; + } - using BitPackingEnabled = details::BasicMeasureSizeBitPackingWrapper>; - using TConfig = Config; - using TValue = void; + template + void writeBuffer(const T*, size_t count) + { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); + _currPos += SIZE * count; + } - template - void writeBytes(const T&) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); - _currPos += SIZE; - } + void currentWritePos(size_t pos) + { + const auto maxPos = _currPos > pos ? _currPos : pos; + if (maxPos > _biggestCurrentPos) { + _biggestCurrentPos = maxPos; + } + _currPos = pos; + } - template - void writeBuffer(const T*, size_t count) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); - _currPos += SIZE * count; - } + size_t currentWritePos() const { return _currPos; } - void currentWritePos(size_t pos) { - const auto maxPos = _currPos > pos ? _currPos : pos; - if (maxPos > _biggestCurrentPos) { - _biggestCurrentPos = maxPos; - } - _currPos = pos; - } + void align() {} - size_t currentWritePos() const { - return _currPos; - } + void flush() {} - void align() { - } + // get size in bytes + size_t writtenBytesCount() const + { + return _currPos > _biggestCurrentPos ? _currPos : _biggestCurrentPos; + } - void flush() { - } +private: + size_t _biggestCurrentPos{}; + size_t _currPos{}; +}; - //get size in bytes - size_t writtenBytesCount() const { - return _currPos > _biggestCurrentPos ? _currPos : _biggestCurrentPos; - } - - private: - size_t _biggestCurrentPos{}; - size_t _currPos{}; - }; - - //helper type for default config - using MeasureSize = BasicMeasureSize; +// helper type for default config +using MeasureSize = BasicMeasureSize; } -#endif //BITSERY_ADAPTER_MEASURE_SIZE_H +#endif // BITSERY_ADAPTER_MEASURE_SIZE_H diff --git a/include/bitsery/adapter/stream.h b/include/bitsery/adapter/stream.h index 371bf92..4787d7d 100644 --- a/include/bitsery/adapter/stream.h +++ b/include/bitsery/adapter/stream.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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_ADAPTER_STREAM_H #define BITSERY_ADAPTER_STREAM_H @@ -32,273 +32,345 @@ namespace bitsery { - template - class BasicInputStreamAdapter: public details::InputAdapterBaseCRTP> { - public: - friend details::InputAdapterBaseCRTP>; +template +class BasicInputStreamAdapter + : public details::InputAdapterBaseCRTP< + BasicInputStreamAdapter> +{ +public: + friend details::InputAdapterBaseCRTP< + BasicInputStreamAdapter>; - using BitPackingEnabled = details::InputAdapterBitPackingWrapper>; - using TConfig = Config; - using TValue = TChar; + using BitPackingEnabled = details::InputAdapterBitPackingWrapper< + BasicInputStreamAdapter>; + using TConfig = Config; + using TValue = TChar; - BasicInputStreamAdapter(std::basic_ios& istream) - :_ios{std::addressof(istream)} {} + BasicInputStreamAdapter(std::basic_ios& istream) + : _ios{ std::addressof(istream) } + { + } - BasicInputStreamAdapter(const BasicInputStreamAdapter&) = delete; - BasicInputStreamAdapter& operator = (const BasicInputStreamAdapter&) = delete; + BasicInputStreamAdapter(const BasicInputStreamAdapter&) = delete; + BasicInputStreamAdapter& operator=(const BasicInputStreamAdapter&) = delete; - BasicInputStreamAdapter(BasicInputStreamAdapter&&) = default; - BasicInputStreamAdapter& operator = (BasicInputStreamAdapter&&) = default; + BasicInputStreamAdapter(BasicInputStreamAdapter&&) = default; + BasicInputStreamAdapter& operator=(BasicInputStreamAdapter&&) = default; - void currentReadPos(size_t ) { - static_assert(std::is_void::value, "setting read position is not supported with StreamAdapter"); - } + void currentReadPos(size_t) + { + static_assert(std::is_void::value, + "setting read position is not supported with StreamAdapter"); + } - size_t currentReadPos() const { - static_assert(std::is_void::value, "setting read position is not supported with StreamAdapter"); - return {}; - } + size_t currentReadPos() const + { + static_assert(std::is_void::value, + "setting read position is not supported with StreamAdapter"); + return {}; + } - void currentReadEndPos(size_t ) { - static_assert(std::is_void::value, "setting read position is not supported with StreamAdapter"); - } + void currentReadEndPos(size_t) + { + static_assert(std::is_void::value, + "setting read position is not supported with StreamAdapter"); + } - size_t currentReadEndPos() const { - static_assert(std::is_void::value, "setting read position is not supported with StreamAdapter"); - return {}; - } + size_t currentReadEndPos() const + { + static_assert(std::is_void::value, + "setting read position is not supported with StreamAdapter"); + return {}; + } - ReaderError error() const { - return _err; - } + ReaderError error() const { return _err; } - bool isCompletedSuccessfully() const { - if (error() == ReaderError::NoError) { - return _ios->rdbuf()->sgetc() == CharTraits::eof(); - } - return false; - } + bool isCompletedSuccessfully() const + { + if (error() == ReaderError::NoError) { + return _ios->rdbuf()->sgetc() == CharTraits::eof(); + } + return false; + } - void error(ReaderError error) { - if (_err == ReaderError::NoError) { - _err = error; - _zeroIfNoErrors = std::numeric_limits::max(); - } - } + void error(ReaderError error) + { + if (_err == ReaderError::NoError) { + _err = error; + _zeroIfNoErrors = std::numeric_limits::max(); + } + } - private: +private: + template + void readInternalValue(TValue* data) + { + readChecked( + data, SIZE, std::integral_constant{}); + } - template - void readInternalValue(TValue* data) { - readChecked(data, SIZE, std::integral_constant{}); - } + void readInternalBuffer(TValue* data, size_t size) + { + readChecked( + data, size, std::integral_constant{}); + } - void readInternalBuffer(TValue* data, size_t size) { - readChecked(data, size, std::integral_constant{}); - } + void readChecked(TValue* data, size_t size, std::true_type) + { + if (size - static_cast(_ios->rdbuf()->sgetn( + data, static_cast(size))) != + _zeroIfNoErrors) { + *data = {}; + if (_zeroIfNoErrors == 0) { + error(_ios->rdstate() == std::ios_base::badbit + ? ReaderError::ReadingError + : ReaderError::DataOverflow); + } + } + } - void readChecked(TValue* data, size_t size, std::true_type) { - if (size - static_cast(_ios->rdbuf()->sgetn(data, static_cast(size))) != _zeroIfNoErrors) { - *data = {}; - if (_zeroIfNoErrors == 0) { - error(_ios->rdstate() == std::ios_base::badbit - ? ReaderError::ReadingError - : ReaderError::DataOverflow); - } - } - } + void readChecked(TValue* data, size_t size, std::false_type) + { + _ios->rdbuf()->sgetn(data, static_cast(size)); + } - void readChecked(TValue* data, size_t size, std::false_type) { - _ios->rdbuf()->sgetn(data , static_cast(size)); - } + std::basic_ios* _ios; + size_t _zeroIfNoErrors{}; + ReaderError _err = ReaderError::NoError; +}; - std::basic_ios* _ios; - size_t _zeroIfNoErrors{}; - ReaderError _err = ReaderError::NoError; - }; +template +class BasicOutputStreamAdapter + : public details::OutputAdapterBaseCRTP< + BasicOutputStreamAdapter> +{ +public: + friend details::OutputAdapterBaseCRTP< + BasicOutputStreamAdapter>; - template - class BasicOutputStreamAdapter: public details::OutputAdapterBaseCRTP> { - public: - friend details::OutputAdapterBaseCRTP>; + using BitPackingEnabled = details::OutputAdapterBitPackingWrapper< + BasicOutputStreamAdapter>; + using TConfig = Config; + using TValue = TChar; - using BitPackingEnabled = details::OutputAdapterBitPackingWrapper>; - using TConfig = Config; - using TValue = TChar; + BasicOutputStreamAdapter(std::basic_ostream& ostream) + : _ostream{ std::addressof(ostream) } + { + } - BasicOutputStreamAdapter(std::basic_ostream& ostream) - :_ostream{std::addressof(ostream)} {} + void currentWritePos(size_t) + { + static_assert(std::is_void::value, + "setting write position is not supported with StreamAdapter"); + } - void currentWritePos(size_t ) { - static_assert(std::is_void::value, "setting write position is not supported with StreamAdapter"); - } + size_t currentWritePos() const + { + static_assert(std::is_void::value, + "setting write position is not supported with StreamAdapter"); + return {}; + } - size_t currentWritePos() const { - static_assert(std::is_void::value, "setting write position is not supported with StreamAdapter"); - return {}; - } + void flush() { _ostream->flush(); } - void flush() { - _ostream->flush(); - } + size_t writtenBytesCount() const + { + static_assert(std::is_void::value, + "`writtenBytesCount` cannot be used with stream adapter"); + // streaming doesn't return written bytes + return 0u; + } - size_t writtenBytesCount() const { - static_assert(std::is_void::value, "`writtenBytesCount` cannot be used with stream adapter"); - //streaming doesn't return written bytes - return 0u; - } +private: + template + void writeInternalValue(const TValue* data) + { + _ostream->rdbuf()->sputn(data, SIZE); + } - private: + void writeInternalBuffer(const TValue* data, size_t size) + { + _ostream->rdbuf()->sputn(data, size); + } - template - void writeInternalValue(const TValue* data) { - _ostream->rdbuf()->sputn( data , SIZE ); - } + std::basic_ostream* _ostream; +}; - void writeInternalBuffer(const TValue* data, size_t size) { - _ostream->rdbuf()->sputn( data , size ); - } +template> +class BasicBufferedOutputStreamAdapter + : public details::OutputAdapterBaseCRTP< + BasicBufferedOutputStreamAdapter> +{ +public: + friend details::OutputAdapterBaseCRTP< + BasicBufferedOutputStreamAdapter>; - std::basic_ostream* _ostream; - }; + using BitPackingEnabled = details::OutputAdapterBitPackingWrapper< + BasicBufferedOutputStreamAdapter>; + using TConfig = Config; + using Buffer = TBuffer; + using BufferIt = typename traits::BufferAdapterTraits::TIterator; + static_assert( + details::IsDefined::value, + "Please define BufferAdapterTraits or include from to " + "use as buffer for BasicBufferedOutputStreamAdapter"); + static_assert( + traits::ContainerTraits::isContiguous, + "BasicBufferedOutputStreamAdapter only works with contiguous containers"); + using TValue = TChar; - template > - class BasicBufferedOutputStreamAdapter: - public details::OutputAdapterBaseCRTP> { - public: - friend details::OutputAdapterBaseCRTP>; + // bufferSize is used when buffer is dynamically allocated + BasicBufferedOutputStreamAdapter( + std::basic_ostream& ostream, + size_t bufferSize = 256) + : _ostream(std::addressof(ostream)) + , _buf{} + , _beginIt{ std::begin(_buf) } + , _currOffset{ 0 } + { + init(bufferSize, TResizable{}); + // buffer size must be atleast 16, because writeIntervalValue expect that at + // least one value fits to buffer. + assert(_bufferSize >= 16); + } - using BitPackingEnabled = details::OutputAdapterBitPackingWrapper>; - using TConfig = Config; - using Buffer = TBuffer; - using BufferIt = typename traits::BufferAdapterTraits::TIterator; - static_assert(details::IsDefined::value, "Please define BufferAdapterTraits or include from to use as buffer for BasicBufferedOutputStreamAdapter"); - static_assert(traits::ContainerTraits::isContiguous, "BasicBufferedOutputStreamAdapter only works with contiguous containers"); - using TValue = TChar; + // we need to explicitly declare move logic, because after move buffer might + // be invalidated + BasicBufferedOutputStreamAdapter(const BasicBufferedOutputStreamAdapter&) = + delete; + BasicBufferedOutputStreamAdapter& operator=( + const BasicBufferedOutputStreamAdapter&) = delete; - //bufferSize is used when buffer is dynamically allocated - BasicBufferedOutputStreamAdapter(std::basic_ostream& ostream, size_t bufferSize = 256) - :_ostream(std::addressof(ostream)), - _buf{}, - _beginIt{std::begin(_buf)}, - _currOffset{0} - { - init(bufferSize, TResizable{}); - // buffer size must be atleast 16, because writeIntervalValue expect that at least one value fits to buffer. - assert(_bufferSize >= 16); - } + BasicBufferedOutputStreamAdapter(BasicBufferedOutputStreamAdapter&& rhs) + : _ostream{ rhs._ostream } + , _buf{ std::move(rhs._buf) } + , _beginIt{ std::begin(_buf) } + , _currOffset{ rhs._currOffset } + , _bufferSize{ rhs._bufferSize } {}; - //we need to explicitly declare move logic, because after move buffer might be invalidated - BasicBufferedOutputStreamAdapter(const BasicBufferedOutputStreamAdapter&) = delete; - BasicBufferedOutputStreamAdapter& operator = (const BasicBufferedOutputStreamAdapter&) = delete; + BasicBufferedOutputStreamAdapter& operator=( + BasicBufferedOutputStreamAdapter&& rhs) + { + _ostream = rhs._ostream; + _buf = std::move(rhs._buf); + _beginIt = std::begin(_buf); + _currOffset = rhs._currOffset; + _bufferSize = rhs._bufferSize; + return *this; + }; - BasicBufferedOutputStreamAdapter(BasicBufferedOutputStreamAdapter&& rhs) - : _ostream{rhs._ostream}, - _buf{std::move(rhs._buf)}, - _beginIt{std::begin(_buf)}, - _currOffset{rhs._currOffset}, - _bufferSize{rhs._bufferSize} - { - }; + void currentWritePos(size_t) + { + static_assert(std::is_void::value, + "setting write position is not supported with StreamAdapter"); + } - BasicBufferedOutputStreamAdapter& operator = (BasicBufferedOutputStreamAdapter&& rhs) { - _ostream = rhs._ostream; - _buf = std::move(rhs._buf); - _beginIt = std::begin(_buf); - _currOffset = rhs._currOffset; - _bufferSize = rhs._bufferSize; - return *this; - }; + size_t currentWritePos() const + { + static_assert(std::is_void::value, + "setting write position is not supported with StreamAdapter"); + return {}; + } - void currentWritePos(size_t ) { - static_assert(std::is_void::value, "setting write position is not supported with StreamAdapter"); - } + void flush() + { + writeBufferToStream(); + _ostream->flush(); + } - size_t currentWritePos() const { - static_assert(std::is_void::value, "setting write position is not supported with StreamAdapter"); - return {}; - } + size_t writtenBytesCount() const + { + static_assert(std::is_void::value, + "`writtenBytesCount` cannot be used with stream adapter"); + // streaming doesn't return written bytes + return 0u; + } - void flush() { - writeBufferToStream(); - _ostream->flush(); - } +private: + using TResizable = + std::integral_constant::isResizable>; + using diff_t = typename std::iterator_traits::difference_type; - size_t writtenBytesCount() const { - static_assert(std::is_void::value, "`writtenBytesCount` cannot be used with stream adapter"); - //streaming doesn't return written bytes - return 0u; - } + template + void writeInternalValue(const TValue* data) + { + writeInternalImpl(data, SIZE); + } - private: - using TResizable = std::integral_constant::isResizable>; - using diff_t = typename std::iterator_traits::difference_type; + void writeInternalBuffer(const TValue* data, size_t size) + { + writeInternalImpl(data, size); + } - template - void writeInternalValue(const TValue* data) { - writeInternalImpl(data, SIZE); - } + void writeInternalImpl(const TValue* data, size_t size) + { + const auto newOffset = _currOffset + size; + if (newOffset <= _bufferSize) { + std::copy_n(data, size, _beginIt + static_cast(_currOffset)); + _currOffset = newOffset; + } else { + writeBufferToStream(); + // write buffer directly to stream + _ostream->rdbuf()->sputn(data, static_cast(size)); + } + } - void writeInternalBuffer(const TValue* data, size_t size) { - writeInternalImpl(data, size); - } + void writeBufferToStream() + { + _ostream->rdbuf()->sputn(std::addressof(*_beginIt), + static_cast(_currOffset)); + _currOffset = 0; + } - void writeInternalImpl(const TValue* data, size_t size) { - const auto newOffset = _currOffset + size; - if (newOffset <= _bufferSize) { - std::copy_n(data, size, _beginIt + static_cast(_currOffset)); - _currOffset = newOffset; - } else { - writeBufferToStream(); - // write buffer directly to stream - _ostream->rdbuf()->sputn(data, static_cast(size)); - } - } + void init(size_t buffSize, std::true_type) + { + // resize buffer + _bufferSize = buffSize; + _buf.resize(_bufferSize); + _beginIt = std::begin(_buf); + } + void init(size_t, std::false_type) + { + // ignore buffer size parameter, and instead take actual buffer size + _bufferSize = traits::ContainerTraits::size(_buf); + } - void writeBufferToStream() { - _ostream->rdbuf()->sputn(std::addressof(*_beginIt), static_cast(_currOffset)); - _currOffset = 0; - } + std::basic_ostream* _ostream; + TBuffer _buf; + BufferIt _beginIt; + size_t _currOffset; + size_t _bufferSize{ 0 }; +}; - void init (size_t buffSize, std::true_type) { - // resize buffer - _bufferSize = buffSize; - _buf.resize(_bufferSize); - _beginIt = std::begin(_buf); - } - void init (size_t , std::false_type) { - // ignore buffer size parameter, and instead take actual buffer size - _bufferSize = traits::ContainerTraits::size(_buf); - } +template +class BasicIOStreamAdapter + : public BasicInputStreamAdapter + , public BasicOutputStreamAdapter +{ +public: + using TValue = TChar; - std::basic_ostream* _ostream; - TBuffer _buf; - BufferIt _beginIt; - size_t _currOffset; - size_t _bufferSize{0}; - }; + // both bases contain reference to same iostream, so no need to do anything + BasicIOStreamAdapter(std::basic_iostream& iostream) + : BasicInputStreamAdapter{ iostream } + , BasicOutputStreamAdapter{ iostream } + { + } +}; - template - class BasicIOStreamAdapter - : public BasicInputStreamAdapter - , public BasicOutputStreamAdapter - { - public: - using TValue = TChar; +// helper types for most common implementations for std streams +using OutputStreamAdapter = + BasicOutputStreamAdapter>; +using InputStreamAdapter = + BasicInputStreamAdapter>; +using IOStreamAdapter = + BasicIOStreamAdapter>; - //both bases contain reference to same iostream, so no need to do anything - BasicIOStreamAdapter(std::basic_iostream& iostream) - :BasicInputStreamAdapter{iostream} - ,BasicOutputStreamAdapter{iostream} - {} - }; - - //helper types for most common implementations for std streams - using OutputStreamAdapter = BasicOutputStreamAdapter>; - using InputStreamAdapter = BasicInputStreamAdapter>; - using IOStreamAdapter = BasicIOStreamAdapter>; - - using OutputBufferedStreamAdapter = BasicBufferedOutputStreamAdapter>; +using OutputBufferedStreamAdapter = + BasicBufferedOutputStreamAdapter>; } -#endif //BITSERY_ADAPTER_STREAM_H +#endif // BITSERY_ADAPTER_STREAM_H diff --git a/include/bitsery/bitsery.h b/include/bitsery/bitsery.h index 391804f..f3b443a 100644 --- a/include/bitsery/bitsery.h +++ b/include/bitsery/bitsery.h @@ -1,25 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_BITSERY_H #define BITSERY_BITSERY_H @@ -29,15 +28,15 @@ #define BITSERY_PATCH_VERSION 2 #define BITSERY_QUOTE_MACRO(name) #name -#define BITSERY_BUILD_VERSION_STR(major,minor, patch) \ -BITSERY_QUOTE_MACRO(major) "." \ -BITSERY_QUOTE_MACRO(minor) "." \ -BITSERY_QUOTE_MACRO(patch) +#define BITSERY_BUILD_VERSION_STR(major, minor, patch) \ + BITSERY_QUOTE_MACRO(major) \ + "." BITSERY_QUOTE_MACRO(minor) "." BITSERY_QUOTE_MACRO(patch) -#define BITSERY_VERSION \ -BITSERY_BUILD_VERSION_STR(BITSERY_MAJOR_VERSION, BITSERY_MINOR_VERSION, BITSERY_PATCH_VERSION) +#define BITSERY_VERSION \ + BITSERY_BUILD_VERSION_STR( \ + BITSERY_MAJOR_VERSION, BITSERY_MINOR_VERSION, BITSERY_PATCH_VERSION) -#include "serializer.h" #include "deserializer.h" +#include "serializer.h" -#endif //BITSERY_BITSERY_H +#endif // BITSERY_BITSERY_H diff --git a/include/bitsery/brief_syntax.h b/include/bitsery/brief_syntax.h index 736a2c7..5ebae4d 100644 --- a/include/bitsery/brief_syntax.h +++ b/include/bitsery/brief_syntax.h @@ -1,94 +1,126 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_BRIEF_SYNTAX_H #define BITSERY_BRIEF_SYNTAX_H -#include "details/serialization_common.h" #include "details/brief_syntax_common.h" +#include "details/serialization_common.h" namespace bitsery { - //define function that enables s(....) usage - template - void processBriefSyntax(S& s, T&& head) { - static_assert(std::is_lvalue_reference::value || std::is_base_of::value, - "Argument must be either lvalue or subclass of brief_syntax::ModFnc"); - s.object(head); - } +// define function that enables s(....) usage +template +void +processBriefSyntax(S& s, T&& head) +{ + static_assert( + std::is_lvalue_reference::value || + std::is_base_of::value, + "Argument must be either lvalue or subclass of brief_syntax::ModFnc"); + s.object(head); +} - //wrapper functions that enables to serialize as container or string - template - brief_syntax::CArray asText(T (& str)[N]) { - return {str}; - } +// wrapper functions that enables to serialize as container or string +template +brief_syntax::CArray +asText(T (&str)[N]) +{ + return { str }; +} - template - brief_syntax::CArray asContainer(T (& obj)[N]) { - return {obj}; - } +template +brief_syntax::CArray +asContainer(T (&obj)[N]) +{ + return { obj }; +} - template - brief_syntax::MaxSize maxSize(T& obj, size_t max) { - return {obj, max}; - } +template +brief_syntax::MaxSize +maxSize(T& obj, size_t max) +{ + return { obj, max }; +} -//define serialize function for fundamental types - template - void serialize(S& s, bool& v) { - s.boolValue(v); - } +// define serialize function for fundamental types +template +void +serialize(S& s, bool& v) +{ + s.boolValue(v); +} - template::value>::type * = nullptr> - void serialize(S& s, T& v) { - s.template value(v); - } +template::value>::type* = + nullptr> +void +serialize(S& s, T& v) +{ + s.template value(v); +} -//define serialization for c-style container +// define serialization for c-style container - //if array is integral type, specify explicitly how to process: as text or container - template::value>::type * = nullptr> - void serialize(S&, T (&)[N]) { - static_assert(N == 0, - "\nPlease use 'asText(obj)' or 'asContainer(obj)' when using c-style array with integral types\n"); - } +// if array is integral type, specify explicitly how to process: as text or +// container +template::value>::type* = nullptr> +void +serialize(S&, T (&)[N]) +{ + static_assert(N == 0, + "\nPlease use 'asText(obj)' or 'asContainer(obj)' when using " + "c-style array with integral types\n"); +} - template::value>::type * = nullptr> - void serialize(S& s, T (& obj)[N]) { - brief_syntax::processContainer(s, obj); - } +template::value>::type* = nullptr> +void +serialize(S& s, T (&obj)[N]) +{ + brief_syntax::processContainer(s, obj); +} - //this is a helper class that enforce fundamental type sizes, when used on multiple platforms - template - void assertFundamentalTypeSizes() { - //http://en.cppreference.com/w/cpp/language/types - static_assert(sizeof(short) == TShort, ""); - static_assert(sizeof(int) == TInt, ""); - static_assert(sizeof(long) == TLong, ""); - static_assert(sizeof(long long) == TLongLong, ""); - //for completion we also need pointer type size, but serializer doesn't support pointer serialization. - } +// this is a helper class that enforce fundamental type sizes, when used on +// multiple platforms +template +void +assertFundamentalTypeSizes() +{ + // http://en.cppreference.com/w/cpp/language/types + static_assert(sizeof(short) == TShort, ""); + static_assert(sizeof(int) == TInt, ""); + static_assert(sizeof(long) == TLong, ""); + static_assert(sizeof(long long) == TLongLong, ""); + // for completion we also need pointer type size, but serializer doesn't + // support pointer serialization. +} } -#endif //BITSERY_BRIEF_SYNTAX_H +#endif // BITSERY_BRIEF_SYNTAX_H diff --git a/include/bitsery/brief_syntax/array.h b/include/bitsery/brief_syntax/array.h index 5187bdf..46da943 100644 --- a/include/bitsery/brief_syntax/array.h +++ b/include/bitsery/brief_syntax/array.h @@ -1,37 +1,38 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_BRIEF_SYNTAX_TYPE_STD_ARRAY_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_ARRAY_H -#include "../traits/array.h" #include "../details/brief_syntax_common.h" +#include "../traits/array.h" namespace bitsery { - template - void serialize(S &s, std::array &obj) { - brief_syntax::processContainer(s, obj); - } +template +void +serialize(S& s, std::array& obj) +{ + brief_syntax::processContainer(s, obj); +} } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_ARRAY_H +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_ARRAY_H diff --git a/include/bitsery/brief_syntax/atomic.h b/include/bitsery/brief_syntax/atomic.h index 3960a60..d9e7856 100644 --- a/include/bitsery/brief_syntax/atomic.h +++ b/include/bitsery/brief_syntax/atomic.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2020 Nick Renieris +// Copyright (c) 2020 Nick Renieris // -//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: +// 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 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. +// 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_BRIEF_SYNTAX_TYPE_STD_ATOMIC_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_ATOMIC_H @@ -26,10 +26,12 @@ #include "../ext/std_atomic.h" namespace bitsery { - template - void serialize(S &s, std::atomic &obj) { - s.template ext(obj, ext::StdAtomic{}); - } +template +void +serialize(S& s, std::atomic& obj) +{ + s.template ext(obj, ext::StdAtomic{}); +} } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_ATOMIC_H +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_ATOMIC_H diff --git a/include/bitsery/brief_syntax/chrono.h b/include/bitsery/brief_syntax/chrono.h index cab0265..1c3f969 100644 --- a/include/bitsery/brief_syntax/chrono.h +++ b/include/bitsery/brief_syntax/chrono.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. +// 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_BRIEF_SYNTAX_TYPE_STD_CHRONO_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_CHRONO_H @@ -26,15 +26,19 @@ #include "../ext/std_chrono.h" namespace bitsery { - template - void serialize(S &s, std::chrono::duration &obj) { - s.template ext(obj, ext::StdDuration{}); - } - - template - void serialize(S &s, std::chrono::time_point> &obj) { - s.template ext(obj, ext::StdTimePoint{}); - } +template +void +serialize(S& s, std::chrono::duration& obj) +{ + s.template ext(obj, ext::StdDuration{}); } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_CHRONO_H +template +void +serialize(S& s, std::chrono::time_point>& obj) +{ + s.template ext(obj, ext::StdTimePoint{}); +} +} + +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_CHRONO_H diff --git a/include/bitsery/brief_syntax/deque.h b/include/bitsery/brief_syntax/deque.h index 5be94c5..a0efaf8 100644 --- a/include/bitsery/brief_syntax/deque.h +++ b/include/bitsery/brief_syntax/deque.h @@ -1,37 +1,38 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_BRIEF_SYNTAX_TYPE_STD_DEQUE_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_DEQUE_H -#include "../traits/deque.h" #include "../details/brief_syntax_common.h" +#include "../traits/deque.h" namespace bitsery { - template - void serialize(S &s, std::deque &obj) { - brief_syntax::processContainer(s, obj); - } +template +void +serialize(S& s, std::deque& obj) +{ + brief_syntax::processContainer(s, obj); +} } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_DEQUE_H +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_DEQUE_H diff --git a/include/bitsery/brief_syntax/forward_list.h b/include/bitsery/brief_syntax/forward_list.h index d7bb68f..97d6249 100644 --- a/include/bitsery/brief_syntax/forward_list.h +++ b/include/bitsery/brief_syntax/forward_list.h @@ -1,37 +1,38 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_BRIEF_SYNTAX_TYPE_STD_FORWARD_LIST_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_FORWARD_LIST_H -#include "../traits/forward_list.h" #include "../details/brief_syntax_common.h" +#include "../traits/forward_list.h" namespace bitsery { - template - void serialize(S &s, std::forward_list &obj) { - brief_syntax::processContainer(s, obj); - } +template +void +serialize(S& s, std::forward_list& obj) +{ + brief_syntax::processContainer(s, obj); +} } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_FORWARD_LIST_H +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_FORWARD_LIST_H diff --git a/include/bitsery/brief_syntax/list.h b/include/bitsery/brief_syntax/list.h index 2f21d1b..36dfd14 100644 --- a/include/bitsery/brief_syntax/list.h +++ b/include/bitsery/brief_syntax/list.h @@ -1,37 +1,38 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_BRIEF_SYNTAX_TYPE_STD_LIST_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_LIST_H -#include "../traits/list.h" #include "../details/brief_syntax_common.h" +#include "../traits/list.h" namespace bitsery { - template - void serialize(S &s, std::list &obj) { - brief_syntax::processContainer(s, obj); - } +template +void +serialize(S& s, std::list& obj) +{ + brief_syntax::processContainer(s, obj); +} } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_LIST_H +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_LIST_H diff --git a/include/bitsery/brief_syntax/map.h b/include/bitsery/brief_syntax/map.h index e67713f..7ff303b 100644 --- a/include/bitsery/brief_syntax/map.h +++ b/include/bitsery/brief_syntax/map.h @@ -1,51 +1,64 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_BRIEF_SYNTAX_TYPE_STD_MAP_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_MAP_H #include "../ext/std_map.h" -#include #include +#include namespace bitsery { - template - void serialize(S &s, std::map &obj, size_t maxSize = std::numeric_limits::max()) { - s.ext(obj, ext::StdMap{maxSize}, - [](S& s, Key& key, T& value) { - s.object(key); - s.object(value); - }); - } - - template - void serialize(S &s, std::multimap &obj, size_t maxSize = std::numeric_limits::max()) { - s.ext(obj, ext::StdMap{maxSize}, - [](S& s, Key& key, T& value) { - s.object(key); - s.object(value); - }); - } +template +void +serialize(S& s, + std::map& obj, + size_t maxSize = std::numeric_limits::max()) +{ + s.ext(obj, ext::StdMap{ maxSize }, [](S& s, Key& key, T& value) { + s.object(key); + s.object(value); + }); } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_MAP_H +template +void +serialize(S& s, + std::multimap& obj, + size_t maxSize = std::numeric_limits::max()) +{ + s.ext(obj, ext::StdMap{ maxSize }, [](S& s, Key& key, T& value) { + s.object(key); + s.object(value); + }); +} +} + +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_MAP_H diff --git a/include/bitsery/brief_syntax/memory.h b/include/bitsery/brief_syntax/memory.h index 12cca66..e82e803 100644 --- a/include/bitsery/brief_syntax/memory.h +++ b/include/bitsery/brief_syntax/memory.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2018 Mindaugas Vinkelis +// Copyright (c) 2018 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: +// 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 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. +// 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_BRIEF_SYNTAX_TYPE_STD_MEMORY_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_MEMORY_H @@ -26,20 +26,26 @@ #include "../ext/std_smart_ptr.h" namespace bitsery { - template - void serialize(S &s, std::unique_ptr &obj) { - s.ext(obj, ext::StdSmartPtr{}); - } - - template - void serialize(S &s, std::shared_ptr &obj) { - s.ext(obj, ext::StdSmartPtr{}); - } - - template - void serialize(S &s, std::weak_ptr &obj) { - s.ext(obj, ext::StdSmartPtr{}); - } +template +void +serialize(S& s, std::unique_ptr& obj) +{ + s.ext(obj, ext::StdSmartPtr{}); } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_MEMORY_H +template +void +serialize(S& s, std::shared_ptr& obj) +{ + s.ext(obj, ext::StdSmartPtr{}); +} + +template +void +serialize(S& s, std::weak_ptr& obj) +{ + s.ext(obj, ext::StdSmartPtr{}); +} +} + +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_MEMORY_H diff --git a/include/bitsery/brief_syntax/queue.h b/include/bitsery/brief_syntax/queue.h index af01b03..dbcf4f9 100644 --- a/include/bitsery/brief_syntax/queue.h +++ b/include/bitsery/brief_syntax/queue.h @@ -1,25 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_BRIEF_SYNTAX_TYPE_STD_QUEUE_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_QUEUE_H @@ -28,16 +27,24 @@ #include namespace bitsery { - template - void serialize(S &s, std::queue &obj, size_t maxSize = std::numeric_limits::max()) { - s.ext(obj, ext::StdQueue{maxSize}); - } +template +void +serialize(S& s, + std::queue& obj, + size_t maxSize = std::numeric_limits::max()) +{ + s.ext(obj, ext::StdQueue{ maxSize }); +} - template - void serialize(S &s, std::priority_queue &obj, size_t maxSize = std::numeric_limits::max()) { - s.ext(obj, ext::StdQueue{maxSize}); - } +template +void +serialize(S& s, + std::priority_queue& obj, + size_t maxSize = std::numeric_limits::max()) +{ + s.ext(obj, ext::StdQueue{ maxSize }); +} } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_QUEUE_H +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_QUEUE_H diff --git a/include/bitsery/brief_syntax/set.h b/include/bitsery/brief_syntax/set.h index dbcd190..2e4d865 100644 --- a/include/bitsery/brief_syntax/set.h +++ b/include/bitsery/brief_syntax/set.h @@ -1,44 +1,51 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_BRIEF_SYNTAX_TYPE_STD_SET_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_SET_H #include "../ext/std_set.h" -#include #include +#include namespace bitsery { - template - void serialize(S &s, std::set &obj, size_t maxSize = std::numeric_limits::max()) { - s.ext(obj, ext::StdSet{maxSize}); - } +template +void +serialize(S& s, + std::set& obj, + size_t maxSize = std::numeric_limits::max()) +{ + s.ext(obj, ext::StdSet{ maxSize }); +} - template - void serialize(S &s, std::multiset &obj, size_t maxSize = std::numeric_limits::max()) { - s.ext(obj, ext::StdSet{maxSize}); - } +template +void +serialize(S& s, + std::multiset& obj, + size_t maxSize = std::numeric_limits::max()) +{ + s.ext(obj, ext::StdSet{ maxSize }); +} } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_SET_H +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_SET_H diff --git a/include/bitsery/brief_syntax/stack.h b/include/bitsery/brief_syntax/stack.h index 621125a..61fab00 100644 --- a/include/bitsery/brief_syntax/stack.h +++ b/include/bitsery/brief_syntax/stack.h @@ -1,25 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_BRIEF_SYNTAX_TYPE_STD_STACK_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_STACK_H @@ -28,10 +27,14 @@ #include namespace bitsery { - template - void serialize(S &s, std::stack &obj, size_t maxSize = std::numeric_limits::max()) { - s.ext(obj, ext::StdStack{maxSize}); - } +template +void +serialize(S& s, + std::stack& obj, + size_t maxSize = std::numeric_limits::max()) +{ + s.ext(obj, ext::StdStack{ maxSize }); +} } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_STACK_H +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_STACK_H diff --git a/include/bitsery/brief_syntax/string.h b/include/bitsery/brief_syntax/string.h index 9068f3d..d9215d9 100644 --- a/include/bitsery/brief_syntax/string.h +++ b/include/bitsery/brief_syntax/string.h @@ -1,37 +1,38 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_BRIEF_SYNTAX_TYPE_STD_STRING_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_STRING_H -#include "../traits/string.h" #include "../details/brief_syntax_common.h" +#include "../traits/string.h" namespace bitsery { - template - void serialize(S &s, std::basic_string &str) { - brief_syntax::processContainer(s, str); - } +template +void +serialize(S& s, std::basic_string& str) +{ + brief_syntax::processContainer(s, str); +} } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_STRING_H +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_STRING_H diff --git a/include/bitsery/brief_syntax/tuple.h b/include/bitsery/brief_syntax/tuple.h index 9de268a..79edfd0 100644 --- a/include/bitsery/brief_syntax/tuple.h +++ b/include/bitsery/brief_syntax/tuple.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. +// 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_BRIEF_SYNTAX_TYPE_STD_TUPLE_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_TUPLE_H @@ -26,10 +26,12 @@ #include "../ext/std_tuple.h" namespace bitsery { - template - void serialize(S &s, std::tuple &obj) { - s.ext(obj, ext::StdTuple{}); - } +template +void +serialize(S& s, std::tuple& obj) +{ + s.ext(obj, ext::StdTuple{}); +} } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_TUPLE_H +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_TUPLE_H diff --git a/include/bitsery/brief_syntax/unordered_map.h b/include/bitsery/brief_syntax/unordered_map.h index 27ec3db..da05552 100644 --- a/include/bitsery/brief_syntax/unordered_map.h +++ b/include/bitsery/brief_syntax/unordered_map.h @@ -1,52 +1,67 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_BRIEF_SYNTAX_TYPE_STD_UNORDERED_MAP_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_UNORDERED_MAP_H #include "../ext/std_map.h" -#include #include +#include namespace bitsery { - template - void serialize(S &s, std::unordered_map &obj, size_t maxSize = std::numeric_limits::max()) { - s.ext(obj, ext::StdMap{maxSize}, - [](S& s, Key& key, T& value) { - s.object(key); - s.object(value); - }); - } +template +void +serialize(S& s, + std::unordered_map& obj, + size_t maxSize = std::numeric_limits::max()) +{ + s.ext(obj, ext::StdMap{ maxSize }, [](S& s, Key& key, T& value) { + s.object(key); + s.object(value); + }); +} - template - void serialize(S &s, std::unordered_multimap &obj, size_t maxSize = std::numeric_limits::max()) { - s.ext(obj, ext::StdMap{maxSize}, - [](S& s, Key& key, T& value) { - s.object(key); - s.object(value); - }); - } +template +void +serialize(S& s, + std::unordered_multimap& obj, + size_t maxSize = std::numeric_limits::max()) +{ + s.ext(obj, ext::StdMap{ maxSize }, [](S& s, Key& key, T& value) { + s.object(key); + s.object(value); + }); +} } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_UNORDERED_MAP_H +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_UNORDERED_MAP_H diff --git a/include/bitsery/brief_syntax/unordered_set.h b/include/bitsery/brief_syntax/unordered_set.h index dbfc04c..08dda02 100644 --- a/include/bitsery/brief_syntax/unordered_set.h +++ b/include/bitsery/brief_syntax/unordered_set.h @@ -1,25 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_BRIEF_SYNTAX_TYPE_STD_UNORDERED_SET_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_UNORDERED_SET_H @@ -29,16 +28,32 @@ #include namespace bitsery { - template - void serialize(S &s, std::unordered_set &obj, size_t maxSize = std::numeric_limits::max()) { - s.ext(obj, ext::StdSet{maxSize}); - } +template +void +serialize(S& s, + std::unordered_set& obj, + size_t maxSize = std::numeric_limits::max()) +{ + s.ext(obj, ext::StdSet{ maxSize }); +} - template - void serialize(S &s, std::unordered_multiset &obj, size_t maxSize = std::numeric_limits::max()) { - s.ext(obj, ext::StdSet{maxSize}); - } +template +void +serialize(S& s, + std::unordered_multiset& obj, + size_t maxSize = std::numeric_limits::max()) +{ + s.ext(obj, ext::StdSet{ maxSize }); +} } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_UNORDERED_SET_H +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_UNORDERED_SET_H diff --git a/include/bitsery/brief_syntax/variant.h b/include/bitsery/brief_syntax/variant.h index 572348a..71e324e 100644 --- a/include/bitsery/brief_syntax/variant.h +++ b/include/bitsery/brief_syntax/variant.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. +// 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_BRIEF_SYNTAX_TYPE_STD_VARIANT_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_VARIANT_H @@ -26,10 +26,12 @@ #include "../ext/std_variant.h" namespace bitsery { - template - void serialize(S &s, std::variant &obj) { - s.ext(obj, ext::StdVariant{}); - } +template +void +serialize(S& s, std::variant& obj) +{ + s.ext(obj, ext::StdVariant{}); +} } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_VARIANT_H +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_VARIANT_H diff --git a/include/bitsery/brief_syntax/vector.h b/include/bitsery/brief_syntax/vector.h index 2f744b1..b09cd6f 100644 --- a/include/bitsery/brief_syntax/vector.h +++ b/include/bitsery/brief_syntax/vector.h @@ -1,37 +1,38 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_BRIEF_SYNTAX_TYPE_STD_VECTOR_H #define BITSERY_BRIEF_SYNTAX_TYPE_STD_VECTOR_H -#include "../traits/vector.h" #include "../details/brief_syntax_common.h" +#include "../traits/vector.h" namespace bitsery { - template - void serialize(S &s, std::vector &obj) { - brief_syntax::processContainer(s, obj); - } +template +void +serialize(S& s, std::vector& obj) +{ + brief_syntax::processContainer(s, obj); +} } -#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_VECTOR_H +#endif // BITSERY_BRIEF_SYNTAX_TYPE_STD_VECTOR_H diff --git a/include/bitsery/common.h b/include/bitsery/common.h index 80a97bd..4905dd2 100644 --- a/include/bitsery/common.h +++ b/include/bitsery/common.h @@ -1,25 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. #ifndef BITSERY_COMMON_H #define BITSERY_COMMON_H @@ -29,22 +28,27 @@ namespace bitsery { /* * endianness */ - enum class EndiannessType { - LittleEndian, - BigEndian - }; +enum class EndiannessType +{ + LittleEndian, + BigEndian +}; - // default configuration for serialization and deserialization - struct DefaultConfig { - // defines endianness of data that is read from input adapter and written to output adapter. - static constexpr EndiannessType Endianness = EndiannessType::LittleEndian; - // these flags allow to improve deserialization performance if data is trusted - // enables/disables checks for buffer end or stream read errors in input adapter - static constexpr bool CheckAdapterErrors = true; - // enables/disables checks for other errors that can significantly affect performance - static constexpr bool CheckDataErrors = true; - }; +// default configuration for serialization and deserialization +struct DefaultConfig +{ + // defines endianness of data that is read from input adapter and written to + // output adapter. + static constexpr EndiannessType Endianness = EndiannessType::LittleEndian; + // these flags allow to improve deserialization performance if data is trusted + // enables/disables checks for buffer end or stream read errors in input + // adapter + static constexpr bool CheckAdapterErrors = true; + // enables/disables checks for other errors that can significantly affect + // performance + static constexpr bool CheckDataErrors = true; +}; } -#endif //BITSERY_COMMON_H +#endif // BITSERY_COMMON_H diff --git a/include/bitsery/deserializer.h b/include/bitsery/deserializer.h index 747824f..237fee0 100644 --- a/include/bitsery/deserializer.h +++ b/include/bitsery/deserializer.h @@ -1,25 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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 @@ -28,414 +27,578 @@ namespace bitsery { - template - class Deserializer: public details::AdapterAndContextRef { - public: - //helper type, that always returns bit-packing enabled type, useful inside deserialize function when enabling bitpacking - using BPEnabledType = Deserializer; - using TConfig = typename TInputAdapter::TConfig; - - using details::AdapterAndContextRef::AdapterAndContextRef; - - /* - * object function - */ - - template - void object(T &&obj) { - details::SerializeFunction::invoke(*this, std::forward(obj)); - } - - template - void object(T &&obj, Fnc &&fnc) { - fnc(*this, std::forward(obj)); - } - - /* - * functionality, that enables simpler serialization syntax, by including additional header - */ - - template - Deserializer &operator()(TArgs &&... args) { - archive(std::forward(args)...); - return *this; - } - - /* - * value - */ - - template - void value(T &v) { - static_assert(details::IsFundamentalType::value, "Value must be integral, float or enum type."); - using TValue = typename details::IntegralFromFundamental::TValue; - this->_adapter.template readBytes(reinterpret_cast(v)); - } - - /* - * enable bit-packing - */ - template - void enableBitPacking(Fnc&& fnc) { - procEnableBitPacking(std::forward(fnc), std::is_same{}); - } - - /* - * extension functions - */ - - template - void ext(T &obj, const Ext &extension, Fnc &&fnc) { - static_assert(details::IsExtensionTraitsDefined::value, "Please define ExtensionTraits"); - static_assert(traits::ExtensionTraits::SupportLambdaOverload, - "extension doesn't support overload with lambda"); - extension.deserialize(*this, obj, std::forward(fnc)); - } - - template - void ext(T &obj, const Ext &extension) { - static_assert(details::IsExtensionTraitsDefined::value, "Please define ExtensionTraits"); - static_assert(traits::ExtensionTraits::SupportValueOverload, - "extension doesn't support overload with `value`"); - using ExtVType = typename traits::ExtensionTraits::TValue; - using VType = typename std::conditional::value, details::DummyType, ExtVType>::type; - extension.deserialize(*this, obj, [](Deserializer& s, VType &v) { s.value(v);}); - } - - template - void ext(T &obj, const Ext &extension) { - static_assert(details::IsExtensionTraitsDefined::value, "Please define ExtensionTraits"); - static_assert(traits::ExtensionTraits::SupportObjectOverload, - "extension doesn't support overload with `object`"); - using ExtVType = typename traits::ExtensionTraits::TValue; - using VType = typename std::conditional::value, details::DummyType, ExtVType>::type; - extension.deserialize(*this, obj, [](Deserializer& s, VType &v) { s.object(v); }); - } - - /* - * boolValue - */ - void boolValue(bool &v) { - procBoolValue(v, - std::is_same{}, - std::integral_constant{}); - } - - /* - * text overloads - */ - - template - void text(T &str, size_t maxSize) { - static_assert(details::IsTextTraitsDefined::value, - "Please define TextTraits or include from "); - static_assert(traits::ContainerTraits::isResizable, - "use text(T&) overload without `maxSize` for static containers"); - size_t length; - readSize(length, maxSize); - traits::ContainerTraits::resize(str, length + (traits::TextTraits::addNUL ? 1u : 0u)); - procText(str, length); - } - - template - void text(T &str) { - static_assert(details::IsTextTraitsDefined::value, - "Please define TextTraits or include from "); - static_assert(!traits::ContainerTraits::isResizable, - "use text(T&, size_t) overload with `maxSize` for dynamic containers"); - size_t length; - readSize(length, traits::ContainerTraits::size(str)); - procText(str, length); - } - - /* - * container overloads - */ - - //dynamic size containers - - template - void container(T &obj, size_t maxSize, Fnc &&fnc) { - static_assert(details::IsContainerTraitsDefined::value, - "Please define ContainerTraits or include from "); - static_assert(traits::ContainerTraits::isResizable, - "use container(T&) overload without `maxSize` for static containers"); - size_t size{}; - readSize(size, maxSize); - traits::ContainerTraits::resize(obj, size); - procContainer(std::begin(obj), std::end(obj), std::forward(fnc)); - } - - template - void container(T &obj, size_t maxSize) { - static_assert(details::IsContainerTraitsDefined::value, - "Please define ContainerTraits or include from "); - static_assert(traits::ContainerTraits::isResizable, - "use container(T&) overload without `maxSize` for static containers"); - size_t size{}; - readSize(size, maxSize); - traits::ContainerTraits::resize(obj, size); - procContainer(std::begin(obj), std::end(obj), std::integral_constant::isContiguous>{}); - } - - template - void container(T &obj, size_t maxSize) { - static_assert(details::IsContainerTraitsDefined::value, - "Please define ContainerTraits or include from "); - static_assert(traits::ContainerTraits::isResizable, - "use container(T&) overload without `maxSize` for static containers"); - size_t size{}; - readSize(size, maxSize); - traits::ContainerTraits::resize(obj, size); - procContainer(std::begin(obj), std::end(obj)); - } - //fixed size containers - - template::value>::type * = nullptr> - void container(T &obj, Fnc &&fnc) { - static_assert(details::IsContainerTraitsDefined::value, - "Please define ContainerTraits or include from "); - static_assert(!traits::ContainerTraits::isResizable, - "use container(T&, size_t, Fnc) overload with `maxSize` for dynamic containers"); - procContainer(std::begin(obj), std::end(obj), std::forward(fnc)); - } - - template - void container(T &obj) { - static_assert(details::IsContainerTraitsDefined::value, - "Please define ContainerTraits or include from "); - static_assert(!traits::ContainerTraits::isResizable, - "use container(T&, size_t) overload with `maxSize` for dynamic containers"); - static_assert(VSIZE > 0, ""); - procContainer(std::begin(obj), std::end(obj), std::integral_constant::isContiguous>{}); - } - - template - void container(T &obj) { - static_assert(details::IsContainerTraitsDefined::value, - "Please define ContainerTraits or include from "); - static_assert(!traits::ContainerTraits::isResizable, - "use container(T&, size_t) overload with `maxSize` for dynamic containers"); - procContainer(std::begin(obj), std::end(obj)); - } - - //overloads for functions with explicit type size - - template - void value1b(T &&v) { value<1>(std::forward(v)); } - - template - void value2b(T &&v) { value<2>(std::forward(v)); } - - template - void value4b(T &&v) { value<4>(std::forward(v)); } - - template - void value8b(T &&v) { value<8>(std::forward(v)); } - - template - void value16b(T &&v) { value<16>(std::forward(v)); } - - template - void ext1b(T &v, Ext &&extension) { ext<1, T, Ext>(v, std::forward(extension)); } - - template - void ext2b(T &v, Ext &&extension) { ext<2, T, Ext>(v, std::forward(extension)); } - - template - void ext4b(T &v, Ext &&extension) { ext<4, T, Ext>(v, std::forward(extension)); } - - template - void ext8b(T &v, Ext &&extension) { ext<8, T, Ext>(v, std::forward(extension)); } - - template - void ext16b(T &v, Ext &&extension) { ext<16, T, Ext>(v, std::forward(extension)); } - - template - void text1b(T &str, size_t maxSize) { text<1>(str, maxSize); } - - template - void text2b(T &str, size_t maxSize) { text<2>(str, maxSize); } - - template - void text4b(T &str, size_t maxSize) { text<4>(str, maxSize); } - - template - void text1b(T &str) { text<1>(str); } - - template - void text2b(T &str) { text<2>(str); } - - template - void text4b(T &str) { text<4>(str); } - - template - void container1b(T &&obj, size_t maxSize) { container<1>(std::forward(obj), maxSize); } - - template - void container2b(T &&obj, size_t maxSize) { container<2>(std::forward(obj), maxSize); } - - template - void container4b(T &&obj, size_t maxSize) { container<4>(std::forward(obj), maxSize); } - - template - void container8b(T &&obj, size_t maxSize) { container<8>(std::forward(obj), maxSize); } - - template - void container16b(T &&obj, size_t maxSize) { container<16>(std::forward(obj), maxSize); } - - template - void container1b(T &&obj) { container<1>(std::forward(obj)); } - - template - void container2b(T &&obj) { container<2>(std::forward(obj)); } - - template - void container4b(T &&obj) { container<4>(std::forward(obj)); } - - template - void container8b(T &&obj) { container<8>(std::forward(obj)); } - - template - void container16b(T &&obj) { container<16>(std::forward(obj)); } - - private: - - void readSize(size_t& size, size_t maxSize) { - details::readSize(this->_adapter, size, maxSize, - std::integral_constant{}); - } - - //process value types - //false_type means that we must process all elements individually - template - void procContainer(It first, It last, std::false_type) { - for (; first != last; ++first) - value(*first); - } - - //process value types - //true_type means, that we can copy whole buffer - template - void procContainer(It first, It last, std::true_type) { - using TValue = typename std::decay::type; - using TIntegral = typename details::IntegralFromFundamental::TValue; - if (first != last){ - const auto distance = std::distance(first, last); - this->_adapter.template readBuffer(reinterpret_cast(&(*first)), static_cast(distance)); - } - } - - //process by calling functions - template - void procContainer(It first, It last, Fnc fnc) { - for (; first != last; ++first) - fnc(*this, *first); - } - - //process object types - template - void procContainer(It first, It last) { - for (; first != last; ++first) - object(*first); - } - - template - void procText(T& str, size_t length) { - auto begin = std::begin(str); - //end of string, not end of container - using diff_t = typename std::iterator_traits::difference_type; - auto end = std::next(begin, static_cast(length)); - procContainer(begin, end, std::integral_constant::isContiguous>{}); - //null terminated character at the end - if (traits::TextTraits::addNUL) - *end = {}; - } - - //proc bool writing bit or byte, depending on if BitPackingEnabled or not - template - void procBoolValue(bool &v, std::true_type, HandleDataErrors) { - uint8_t tmp{}; - this->_adapter.readBits(tmp, 1); - v = tmp == 1; - } - - void procBoolValue(bool &v, std::false_type, std::true_type) { - uint8_t tmp{}; - this->_adapter.template readBytes<1>(tmp); - if (tmp > 1) - this->_adapter.error(ReaderError::InvalidData); - v = tmp == 1; - } - - void procBoolValue(bool &v, std::false_type, std::false_type) { - uint8_t tmp{}; - this->_adapter.template readBytes<1>(tmp); - v = tmp > 0; - } - - //enable bit-packing or do nothing if it is already enabled - template - void procEnableBitPacking(const Fnc& fnc, std::true_type) { - fnc(*this); - } - - template - void procEnableBitPacking(const Fnc& fnc, std::false_type) { - auto des = createWithContext(std::integral_constant{}); - fnc(des); - } - - BPEnabledType createWithContext(std::true_type) { - return BPEnabledType{this->_context, this->_adapter}; - } - - BPEnabledType createWithContext(std::false_type) { - return BPEnabledType{this->_adapter}; - } - - - //these are dummy functions for extensions that have TValue = void - void object(details::DummyType&) { - - } - - template - void value(details::DummyType&) { - - } - - template - void archive(T &&head, TArgs &&... tail) { - //serialize object - details::BriefSyntaxFunction::invoke(*this, std::forward(head)); - //expand other elements - archive(std::forward(tail)...); - } - - //dummy function, that stops archive variadic arguments expansion - void archive() { - } - - }; - - //helper type - - //helper function that set ups all the basic steps and after deserialziation returns status - template - std::pair quickDeserialization(InputAdapter adapter, T& value) { - Deserializer des{std::move(adapter)}; - des.object(value); - return {des.adapter().error(), des.adapter().isCompletedSuccessfully()}; +template +class Deserializer + : public details::AdapterAndContextRef +{ +public: + // helper type, that always returns bit-packing enabled type, useful inside + // deserialize function when enabling bitpacking + using BPEnabledType = + Deserializer; + using TConfig = typename TInputAdapter::TConfig; + + using details::AdapterAndContextRef::AdapterAndContextRef; + + /* + * object function + */ + + template + void object(T&& obj) + { + details::SerializeFunction::invoke(*this, + std::forward(obj)); + } + + template + void object(T&& obj, Fnc&& fnc) + { + fnc(*this, std::forward(obj)); + } + + /* + * functionality, that enables simpler serialization syntax, by including + * additional header + */ + + template + Deserializer& operator()(TArgs&&... args) + { + archive(std::forward(args)...); + return *this; + } + + /* + * value + */ + + template + void value(T& v) + { + static_assert(details::IsFundamentalType::value, + "Value must be integral, float or enum type."); + using TValue = typename details::IntegralFromFundamental::TValue; + this->_adapter.template readBytes(reinterpret_cast(v)); + } + + /* + * enable bit-packing + */ + template + void enableBitPacking(Fnc&& fnc) + { + procEnableBitPacking( + std::forward(fnc), + std::is_same{}); + } + + /* + * extension functions + */ + + template + void ext(T& obj, const Ext& extension, Fnc&& fnc) + { + static_assert(details::IsExtensionTraitsDefined::value, + "Please define ExtensionTraits"); + static_assert(traits::ExtensionTraits::SupportLambdaOverload, + "extension doesn't support overload with lambda"); + extension.deserialize(*this, obj, std::forward(fnc)); + } + + template + void ext(T& obj, const Ext& extension) + { + static_assert(details::IsExtensionTraitsDefined::value, + "Please define ExtensionTraits"); + static_assert(traits::ExtensionTraits::SupportValueOverload, + "extension doesn't support overload with `value`"); + using ExtVType = typename traits::ExtensionTraits::TValue; + using VType = typename std::conditional::value, + details::DummyType, + ExtVType>::type; + extension.deserialize( + *this, obj, [](Deserializer& s, VType& v) { s.value(v); }); + } + + template + void ext(T& obj, const Ext& extension) + { + static_assert(details::IsExtensionTraitsDefined::value, + "Please define ExtensionTraits"); + static_assert(traits::ExtensionTraits::SupportObjectOverload, + "extension doesn't support overload with `object`"); + using ExtVType = typename traits::ExtensionTraits::TValue; + using VType = typename std::conditional::value, + details::DummyType, + ExtVType>::type; + extension.deserialize( + *this, obj, [](Deserializer& s, VType& v) { s.object(v); }); + } + + /* + * boolValue + */ + void boolValue(bool& v) + { + procBoolValue( + v, + std::is_same{}, + std::integral_constant{}); + } + + /* + * text overloads + */ + + template + void text(T& str, size_t maxSize) + { + static_assert( + details::IsTextTraitsDefined::value, + "Please define TextTraits or include from "); + static_assert( + traits::ContainerTraits::isResizable, + "use text(T&) overload without `maxSize` for static containers"); + size_t length; + readSize(length, maxSize); + traits::ContainerTraits::resize( + str, length + (traits::TextTraits::addNUL ? 1u : 0u)); + procText(str, length); + } + + template + void text(T& str) + { + static_assert( + details::IsTextTraitsDefined::value, + "Please define TextTraits or include from "); + static_assert( + !traits::ContainerTraits::isResizable, + "use text(T&, size_t) overload with `maxSize` for dynamic containers"); + size_t length; + readSize(length, traits::ContainerTraits::size(str)); + procText(str, length); + } + + /* + * container overloads + */ + + // dynamic size containers + + template + void container(T& obj, size_t maxSize, Fnc&& fnc) + { + static_assert( + details::IsContainerTraitsDefined::value, + "Please define ContainerTraits or include from "); + static_assert( + traits::ContainerTraits::isResizable, + "use container(T&) overload without `maxSize` for static containers"); + size_t size{}; + readSize(size, maxSize); + traits::ContainerTraits::resize(obj, size); + procContainer(std::begin(obj), std::end(obj), std::forward(fnc)); + } + + template + void container(T& obj, size_t maxSize) + { + static_assert( + details::IsContainerTraitsDefined::value, + "Please define ContainerTraits or include from "); + static_assert( + traits::ContainerTraits::isResizable, + "use container(T&) overload without `maxSize` for static containers"); + size_t size{}; + readSize(size, maxSize); + traits::ContainerTraits::resize(obj, size); + procContainer( + std::begin(obj), + std::end(obj), + std::integral_constant::isContiguous>{}); + } + + template + void container(T& obj, size_t maxSize) + { + static_assert( + details::IsContainerTraitsDefined::value, + "Please define ContainerTraits or include from "); + static_assert( + traits::ContainerTraits::isResizable, + "use container(T&) overload without `maxSize` for static containers"); + size_t size{}; + readSize(size, maxSize); + traits::ContainerTraits::resize(obj, size); + procContainer(std::begin(obj), std::end(obj)); + } + // fixed size containers + + template< + typename T, + typename Fnc, + typename std::enable_if::value>::type* = nullptr> + void container(T& obj, Fnc&& fnc) + { + static_assert( + details::IsContainerTraitsDefined::value, + "Please define ContainerTraits or include from "); + static_assert(!traits::ContainerTraits::isResizable, + "use container(T&, size_t, Fnc) overload with `maxSize` for " + "dynamic containers"); + procContainer(std::begin(obj), std::end(obj), std::forward(fnc)); + } + + template + void container(T& obj) + { + static_assert( + details::IsContainerTraitsDefined::value, + "Please define ContainerTraits or include from "); + static_assert(!traits::ContainerTraits::isResizable, + "use container(T&, size_t) overload with `maxSize` for " + "dynamic containers"); + static_assert(VSIZE > 0, ""); + procContainer( + std::begin(obj), + std::end(obj), + std::integral_constant::isContiguous>{}); + } + + template + void container(T& obj) + { + static_assert( + details::IsContainerTraitsDefined::value, + "Please define ContainerTraits or include from "); + static_assert(!traits::ContainerTraits::isResizable, + "use container(T&, size_t) overload with `maxSize` for " + "dynamic containers"); + procContainer(std::begin(obj), std::end(obj)); + } + + // overloads for functions with explicit type size + + template + void value1b(T&& v) + { + value<1>(std::forward(v)); + } + + template + void value2b(T&& v) + { + value<2>(std::forward(v)); + } + + template + void value4b(T&& v) + { + value<4>(std::forward(v)); + } + + template + void value8b(T&& v) + { + value<8>(std::forward(v)); + } + + template + void value16b(T&& v) + { + value<16>(std::forward(v)); + } + + template + void ext1b(T& v, Ext&& extension) + { + ext<1, T, Ext>(v, std::forward(extension)); + } + + template + void ext2b(T& v, Ext&& extension) + { + ext<2, T, Ext>(v, std::forward(extension)); + } + + template + void ext4b(T& v, Ext&& extension) + { + ext<4, T, Ext>(v, std::forward(extension)); + } + + template + void ext8b(T& v, Ext&& extension) + { + ext<8, T, Ext>(v, std::forward(extension)); + } + + template + void ext16b(T& v, Ext&& extension) + { + ext<16, T, Ext>(v, std::forward(extension)); + } + + template + void text1b(T& str, size_t maxSize) + { + text<1>(str, maxSize); + } + + template + void text2b(T& str, size_t maxSize) + { + text<2>(str, maxSize); + } + + template + void text4b(T& str, size_t maxSize) + { + text<4>(str, maxSize); + } + + template + void text1b(T& str) + { + text<1>(str); + } + + template + void text2b(T& str) + { + text<2>(str); + } + + template + void text4b(T& str) + { + text<4>(str); + } + + template + void container1b(T&& obj, size_t maxSize) + { + container<1>(std::forward(obj), maxSize); + } + + template + void container2b(T&& obj, size_t maxSize) + { + container<2>(std::forward(obj), maxSize); + } + + template + void container4b(T&& obj, size_t maxSize) + { + container<4>(std::forward(obj), maxSize); + } + + template + void container8b(T&& obj, size_t maxSize) + { + container<8>(std::forward(obj), maxSize); + } + + template + void container16b(T&& obj, size_t maxSize) + { + container<16>(std::forward(obj), maxSize); + } + + template + void container1b(T&& obj) + { + container<1>(std::forward(obj)); + } + + template + void container2b(T&& obj) + { + container<2>(std::forward(obj)); + } + + template + void container4b(T&& obj) + { + container<4>(std::forward(obj)); + } + + template + void container8b(T&& obj) + { + container<8>(std::forward(obj)); + } + + template + void container16b(T&& obj) + { + container<16>(std::forward(obj)); + } + +private: + void readSize(size_t& size, size_t maxSize) + { + details::readSize( + this->_adapter, + size, + maxSize, + std::integral_constant{}); + } + + // process value types + // false_type means that we must process all elements individually + template + void procContainer(It first, It last, std::false_type) + { + for (; first != last; ++first) + value(*first); + } + + // process value types + // true_type means, that we can copy whole buffer + template + void procContainer(It first, It last, std::true_type) + { + using TValue = typename std::decay::type; + using TIntegral = typename details::IntegralFromFundamental::TValue; + if (first != last) { + const auto distance = std::distance(first, last); + this->_adapter.template readBuffer( + reinterpret_cast(&(*first)), static_cast(distance)); } + } - template - std::pair quickDeserialization(Context& ctx, InputAdapter adapter, T& value) { - Deserializer des{ctx, std::move(adapter)}; - des.object(value); - return {des.adapter().error(), des.adapter().isCompletedSuccessfully()}; - } + // process by calling functions + template + void procContainer(It first, It last, Fnc fnc) + { + for (; first != last; ++first) + fnc(*this, *first); + } + + // process object types + template + void procContainer(It first, It last) + { + for (; first != last; ++first) + object(*first); + } + + template + void procText(T& str, size_t length) + { + auto begin = std::begin(str); + // end of string, not end of container + using diff_t = + typename std::iterator_traits::difference_type; + auto end = std::next(begin, static_cast(length)); + procContainer( + begin, + end, + std::integral_constant::isContiguous>{}); + // null terminated character at the end + if (traits::TextTraits::addNUL) + *end = {}; + } + + // proc bool writing bit or byte, depending on if BitPackingEnabled or not + template + void procBoolValue(bool& v, std::true_type, HandleDataErrors) + { + uint8_t tmp{}; + this->_adapter.readBits(tmp, 1); + v = tmp == 1; + } + + void procBoolValue(bool& v, std::false_type, std::true_type) + { + uint8_t tmp{}; + this->_adapter.template readBytes<1>(tmp); + if (tmp > 1) + this->_adapter.error(ReaderError::InvalidData); + v = tmp == 1; + } + + void procBoolValue(bool& v, std::false_type, std::false_type) + { + uint8_t tmp{}; + this->_adapter.template readBytes<1>(tmp); + v = tmp > 0; + } + + // enable bit-packing or do nothing if it is already enabled + template + void procEnableBitPacking(const Fnc& fnc, std::true_type) + { + fnc(*this); + } + + template + void procEnableBitPacking(const Fnc& fnc, std::false_type) + { + auto des = createWithContext( + std::integral_constant{}); + fnc(des); + } + + BPEnabledType createWithContext(std::true_type) + { + return BPEnabledType{ this->_context, this->_adapter }; + } + + BPEnabledType createWithContext(std::false_type) + { + return BPEnabledType{ this->_adapter }; + } + + // these are dummy functions for extensions that have TValue = void + void object(details::DummyType&) {} + + template + void value(details::DummyType&) + { + } + + template + void archive(T&& head, TArgs&&... tail) + { + // serialize object + details::BriefSyntaxFunction::invoke( + *this, std::forward(head)); + // expand other elements + archive(std::forward(tail)...); + } + + // dummy function, that stops archive variadic arguments expansion + void archive() {} +}; + +// helper type + +// helper function that set ups all the basic steps and after deserialziation +// returns status +template +std::pair +quickDeserialization(InputAdapter adapter, T& value) +{ + Deserializer des{ std::move(adapter) }; + des.object(value); + return { des.adapter().error(), des.adapter().isCompletedSuccessfully() }; +} + +template +std::pair +quickDeserialization(Context& ctx, InputAdapter adapter, T& value) +{ + Deserializer des{ ctx, std::move(adapter) }; + des.object(value); + return { des.adapter().error(), des.adapter().isCompletedSuccessfully() }; +} } -#endif //BITSERY_DESERIALIZER_H +#endif // BITSERY_DESERIALIZER_H diff --git a/include/bitsery/details/adapter_bit_packing.h b/include/bitsery/details/adapter_bit_packing.h index 9150c08..9729ed0 100644 --- a/include/bitsery/details/adapter_bit_packing.h +++ b/include/bitsery/details/adapter_bit_packing.h @@ -1,364 +1,379 @@ -//MIT License +// MIT License // -//Copyright (c) 2022 Mindaugas Vinkelis +// Copyright (c) 2022 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: +// 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 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. +// 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_DETAILS_ADAPTER_BIT_PACKING_H #define BITSERY_DETAILS_ADAPTER_BIT_PACKING_H -#include "not_defined_type.h" -#include "./adapter_common.h" #include "../common.h" +#include "./adapter_common.h" +#include "not_defined_type.h" #include - namespace bitsery { - namespace details { +namespace details { - template - class InputAdapterBitPackingWrapper { - public: - // in order to check if adapter is BP enabled, we use `std::is_same` - // so when current implementation is BP enabled, we always specify current class as BitPackingEnabled. - using BitPackingEnabled = InputAdapterBitPackingWrapper; - using TConfig = typename TAdapter::TConfig; - using TValue = typename TAdapter::TValue; +template +class InputAdapterBitPackingWrapper +{ +public: + // in order to check if adapter is BP enabled, we use `std::is_same` so when current implementation is BP + // enabled, we always specify current class as BitPackingEnabled. + using BitPackingEnabled = InputAdapterBitPackingWrapper; + using TConfig = typename TAdapter::TConfig; + using TValue = typename TAdapter::TValue; - InputAdapterBitPackingWrapper(TAdapter& adapter) - : _wrapped{adapter} - { - } + InputAdapterBitPackingWrapper(TAdapter& adapter) + : _wrapped{ adapter } + { + } - ~InputAdapterBitPackingWrapper() { - align(); - } + ~InputAdapterBitPackingWrapper() { align(); } - template - void readBytes(T &v) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); - using UT = typename std::make_unsigned::type; - if (!m_scratchBits) - this->_wrapped.template readBytes(v); - else - readBits(reinterpret_cast(v), details::BitsSize::value); - } + template + void readBytes(T& v) + { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); + using UT = typename std::make_unsigned::type; + if (!m_scratchBits) + this->_wrapped.template readBytes(v); + else + readBits(reinterpret_cast(v), details::BitsSize::value); + } - template - void readBuffer(T *buf, size_t count) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); + template + void readBuffer(T* buf, size_t count) + { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); - if (!m_scratchBits) { - this->_wrapped.template readBuffer(buf, count); - } else { - using UT = typename std::make_unsigned::type; - //todo improve implementation - const auto end = buf + count; - for (auto it = buf; it != end; ++it) - readBits(reinterpret_cast(*it), details::BitsSize::value); - } - } - - template - void readBits(T &v, size_t bitsCount) { - static_assert(std::is_integral() && std::is_unsigned(), ""); - readBitsInternal(v, bitsCount); - } - - void align() { - if (m_scratchBits) { - ScratchType tmp{}; - readBitsInternal(tmp, m_scratchBits); - handleAlignErrors(tmp, std::integral_constant{}); - } - } - - void currentReadPos(size_t pos) { - align(); - this->_wrapped.currentReadPos(pos); - } - - size_t currentReadPos() const { - return this->_wrapped.currentReadPos(); - } - - void currentReadEndPos(size_t pos) { - this->_wrapped.currentReadEndPos(pos); - } - - size_t currentReadEndPos() const { - return this->_wrapped.currentReadEndPos(); - } - - bool isCompletedSuccessfully() const { - return this->_wrapped.isCompletedSuccessfully(); - } - - ReaderError error() const { - return this->_wrapped.error(); - } - - void error(ReaderError error) { - this->_wrapped.error(error); - } - - private: - TAdapter& _wrapped; - using UnsignedValue = typename std::make_unsigned::type; - using ScratchType = typename details::ScratchType::type; - - ScratchType m_scratch{}; - size_t m_scratchBits{}; - - template - void readBitsInternal(T &v, size_t size) { - auto bitsLeft = size; - using TFast = typename FastType::type; - TFast res{}; - while (bitsLeft > 0) { - auto bits = (std::min)(bitsLeft, details::BitsSize::value); - if (m_scratchBits < bits) { - UnsignedValue tmp; - this->_wrapped.template readBytes(tmp); - m_scratch |= static_cast(tmp) << m_scratchBits; - m_scratchBits += details::BitsSize::value; - } - auto shiftedRes = - static_cast(m_scratch & ((static_cast(1) << bits) - 1)) << (size - bitsLeft); - res = static_cast(res | static_cast(shiftedRes)); - m_scratch >>= bits; - m_scratchBits -= bits; - bitsLeft -= bits; - } - v = static_cast(res); - } - - void handleAlignErrors(ScratchType value, std::true_type) { - if (value) - error(ReaderError::InvalidData); - } - - void handleAlignErrors(ScratchType, std::false_type) { - } - - }; - - - template - class BasicMeasureSizeBitPackingWrapper { - public: - using BitPackingEnabled = BasicMeasureSizeBitPackingWrapper; - using TConfig = typename TAdapter::TConfig; - using TValue = typename TAdapter::TValue; - - BasicMeasureSizeBitPackingWrapper(TAdapter& adapter) - : _wrapped{adapter} - { - } - - ~BasicMeasureSizeBitPackingWrapper() { - align(); - } - - template - void writeBytes(const T& value) { - _wrapped.template writeBytes(value); - } - - template - void writeBuffer(const T* buf, size_t count) { - _wrapped.template writeBuffer(buf, count); - } - - template - void writeBits(const T& , size_t bitsCount) { - _scratchBits += bitsCount; - while (_scratchBits >= 8) { - writeOneByte(); - _scratchBits -= 8; - } - } - - void align() { - if (_scratchBits > 0) { - _scratchBits = 0; - writeOneByte(); - } - } - - void currentWritePos(size_t pos) { - align(); - this->_wrapped.currentWritePos(pos); - } - - size_t currentWritePos() const { - return this->_wrapped.currentWritePos(); - } - - void flush() { - align(); - this->_wrapped.flush(); - } - - size_t writtenBytesCount() const { - return this->_wrapped.writtenBytesCount(); - } - - private: - void writeOneByte() { - _wrapped.template writeBytes<1>(uint8_t{}); - } - TAdapter& _wrapped; - size_t _scratchBits{}; - }; - - - template - class OutputAdapterBitPackingWrapper { - public: - // in order to check if adapter is BP enabled, we use `std::is_same` - // so when current implementation is BP enabled, we always specify current class as BitPackingEnabled. - using BitPackingEnabled = OutputAdapterBitPackingWrapper; - using TConfig = typename TAdapter::TConfig; - using TValue = typename TAdapter::TValue; - - OutputAdapterBitPackingWrapper(TAdapter& adapter) - : _wrapped{adapter} - { - } - - ~OutputAdapterBitPackingWrapper() { - align(); - } - - template - void writeBytes(const T &v) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); - - if (!_scratchBits) { - this->_wrapped.template writeBytes(v); - } else { - using UT = typename std::make_unsigned::type; - writeBitsInternal(reinterpret_cast(v), details::BitsSize::value); - } - } - - template - void writeBuffer(const T *buf, size_t count) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); - if (!_scratchBits) { - this->_wrapped.template writeBuffer(buf, count); - } else { - using UT = typename std::make_unsigned::type; - //todo improve implementation - const auto end = buf + count; - for (auto it = buf; it != end; ++it) - writeBitsInternal(reinterpret_cast(*it), details::BitsSize::value); - } - } - - template - void writeBits(const T &v, size_t bitsCount) { - static_assert(std::is_integral() && std::is_unsigned(), ""); - assert(0 < bitsCount && bitsCount <= details::BitsSize::value); - assert(v <= (bitsCount < 64 - ? (1ULL << bitsCount) - 1 - : (1ULL << (bitsCount-1)) + ((1ULL << (bitsCount-1)) -1))); - writeBitsInternal(v, bitsCount); - } - - void align() { - writeBitsInternal(UnsignedType{}, (details::BitsSize::value - _scratchBits) % 8); - } - - void currentWritePos(size_t pos) { - align(); - this->_wrapped.currentWritePos(pos); - } - - size_t currentWritePos() const { - return this->_wrapped.currentWritePos(); - } - - void flush() { - align(); - this->_wrapped.flush(); - } - - size_t writtenBytesCount() const { - return this->_wrapped.writtenBytesCount(); - } - - private: - TAdapter& _wrapped; - - using UnsignedType = typename std::make_unsigned::type; - using ScratchType = typename details::ScratchType::type; - static_assert(details::IsDefined::value, "Underlying adapter value type is not supported"); - - - template - void writeBitsInternal(const T &v, size_t size) { - constexpr size_t valueSize = details::BitsSize::value; - T value = v; - size_t bitsLeft = size; - while (bitsLeft > 0) { - auto bits = (std::min)(bitsLeft, valueSize); - _scratch |= static_cast( value ) << _scratchBits; - _scratchBits += bits; - if (_scratchBits >= valueSize) { - auto tmp = static_cast(_scratch & _MASK); - this->_wrapped.template writeBytes(tmp); - _scratch >>= valueSize; - _scratchBits -= valueSize; - - value = static_cast(value >> valueSize); - } - bitsLeft -= bits; - } - } - - //overload for TValue, for better performance - void writeBitsInternal(const UnsignedType &v, size_t size) { - if (size > 0) { - _scratch |= static_cast( v ) << _scratchBits; - _scratchBits += size; - if (_scratchBits >= details::BitsSize::value) { - auto tmp = static_cast(_scratch & _MASK); - this->_wrapped.template writeBytes(tmp); - _scratch >>= details::BitsSize::value; - _scratchBits -= details::BitsSize::value; - } - } - } - - const UnsignedType _MASK = (std::numeric_limits::max)(); - ScratchType _scratch{}; - size_t _scratchBits{}; - }; + if (!m_scratchBits) { + this->_wrapped.template readBuffer(buf, count); + } else { + using UT = typename std::make_unsigned::type; + // todo improve implementation + const auto end = buf + count; + for (auto it = buf; it != end; ++it) + readBits(reinterpret_cast(*it), details::BitsSize::value); } + } + + template + void readBits(T& v, size_t bitsCount) + { + static_assert(std::is_integral() && std::is_unsigned(), ""); + readBitsInternal(v, bitsCount); + } + + void align() + { + if (m_scratchBits) { + ScratchType tmp{}; + readBitsInternal(tmp, m_scratchBits); + handleAlignErrors( + tmp, std::integral_constant{}); + } + } + + void currentReadPos(size_t pos) + { + align(); + this->_wrapped.currentReadPos(pos); + } + + size_t currentReadPos() const { return this->_wrapped.currentReadPos(); } + + void currentReadEndPos(size_t pos) { this->_wrapped.currentReadEndPos(pos); } + + size_t currentReadEndPos() const + { + return this->_wrapped.currentReadEndPos(); + } + + bool isCompletedSuccessfully() const + { + return this->_wrapped.isCompletedSuccessfully(); + } + + ReaderError error() const { return this->_wrapped.error(); } + + void error(ReaderError error) { this->_wrapped.error(error); } + +private: + TAdapter& _wrapped; + using UnsignedValue = + typename std::make_unsigned::type; + using ScratchType = typename details::ScratchType::type; + + ScratchType m_scratch{}; + size_t m_scratchBits{}; + + template + void readBitsInternal(T& v, size_t size) + { + auto bitsLeft = size; + using TFast = typename FastType::type; + TFast res{}; + while (bitsLeft > 0) { + auto bits = (std::min)(bitsLeft, details::BitsSize::value); + if (m_scratchBits < bits) { + UnsignedValue tmp; + this->_wrapped.template readBytes( + tmp); + m_scratch |= static_cast(tmp) << m_scratchBits; + m_scratchBits += details::BitsSize::value; + } + auto shiftedRes = + static_cast(m_scratch & ((static_cast(1) << bits) - 1)) + << (size - bitsLeft); + res = static_cast(res | static_cast(shiftedRes)); + m_scratch >>= bits; + m_scratchBits -= bits; + bitsLeft -= bits; + } + v = static_cast(res); + } + + void handleAlignErrors(ScratchType value, std::true_type) + { + if (value) + error(ReaderError::InvalidData); + } + + void handleAlignErrors(ScratchType, std::false_type) {} +}; + +template +class BasicMeasureSizeBitPackingWrapper +{ +public: + using BitPackingEnabled = BasicMeasureSizeBitPackingWrapper; + using TConfig = typename TAdapter::TConfig; + using TValue = typename TAdapter::TValue; + + BasicMeasureSizeBitPackingWrapper(TAdapter& adapter) + : _wrapped{ adapter } + { + } + + ~BasicMeasureSizeBitPackingWrapper() { align(); } + + template + void writeBytes(const T& value) + { + _wrapped.template writeBytes(value); + } + + template + void writeBuffer(const T* buf, size_t count) + { + _wrapped.template writeBuffer(buf, count); + } + + template + void writeBits(const T&, size_t bitsCount) + { + _scratchBits += bitsCount; + while (_scratchBits >= 8) { + writeOneByte(); + _scratchBits -= 8; + } + } + + void align() + { + if (_scratchBits > 0) { + _scratchBits = 0; + writeOneByte(); + } + } + + void currentWritePos(size_t pos) + { + align(); + this->_wrapped.currentWritePos(pos); + } + + size_t currentWritePos() const { return this->_wrapped.currentWritePos(); } + + void flush() + { + align(); + this->_wrapped.flush(); + } + + size_t writtenBytesCount() const + { + return this->_wrapped.writtenBytesCount(); + } + +private: + void writeOneByte() { _wrapped.template writeBytes<1>(uint8_t{}); } + TAdapter& _wrapped; + size_t _scratchBits{}; +}; + +template +class OutputAdapterBitPackingWrapper +{ +public: + // in order to check if adapter is BP enabled, we use `std::is_same` so when current implementation is BP + // enabled, we always specify current class as BitPackingEnabled. + using BitPackingEnabled = OutputAdapterBitPackingWrapper; + using TConfig = typename TAdapter::TConfig; + using TValue = typename TAdapter::TValue; + + OutputAdapterBitPackingWrapper(TAdapter& adapter) + : _wrapped{ adapter } + { + } + + ~OutputAdapterBitPackingWrapper() { align(); } + + template + void writeBytes(const T& v) + { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); + + if (!_scratchBits) { + this->_wrapped.template writeBytes(v); + } else { + using UT = typename std::make_unsigned::type; + writeBitsInternal(reinterpret_cast(v), + details::BitsSize::value); + } + } + + template + void writeBuffer(const T* buf, size_t count) + { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); + if (!_scratchBits) { + this->_wrapped.template writeBuffer(buf, count); + } else { + using UT = typename std::make_unsigned::type; + // todo improve implementation + const auto end = buf + count; + for (auto it = buf; it != end; ++it) + writeBitsInternal(reinterpret_cast(*it), + details::BitsSize::value); + } + } + + template + void writeBits(const T& v, size_t bitsCount) + { + static_assert(std::is_integral() && std::is_unsigned(), ""); + assert(0 < bitsCount && bitsCount <= details::BitsSize::value); + assert(v <= (bitsCount < 64 ? (1ULL << bitsCount) - 1 + : (1ULL << (bitsCount - 1)) + + ((1ULL << (bitsCount - 1)) - 1))); + writeBitsInternal(v, bitsCount); + } + + void align() + { + writeBitsInternal(UnsignedType{}, + (details::BitsSize::value - _scratchBits) % + 8); + } + + void currentWritePos(size_t pos) + { + align(); + this->_wrapped.currentWritePos(pos); + } + + size_t currentWritePos() const { return this->_wrapped.currentWritePos(); } + + void flush() + { + align(); + this->_wrapped.flush(); + } + + size_t writtenBytesCount() const + { + return this->_wrapped.writtenBytesCount(); + } + +private: + TAdapter& _wrapped; + + using UnsignedType = + typename std::make_unsigned::type; + using ScratchType = typename details::ScratchType::type; + static_assert(details::IsDefined::value, + "Underlying adapter value type is not supported"); + + template + void writeBitsInternal(const T& v, size_t size) + { + constexpr size_t valueSize = details::BitsSize::value; + T value = v; + size_t bitsLeft = size; + while (bitsLeft > 0) { + auto bits = (std::min)(bitsLeft, valueSize); + _scratch |= static_cast(value) << _scratchBits; + _scratchBits += bits; + if (_scratchBits >= valueSize) { + auto tmp = static_cast(_scratch & _MASK); + this->_wrapped.template writeBytes( + tmp); + _scratch >>= valueSize; + _scratchBits -= valueSize; + + value = static_cast(value >> valueSize); + } + bitsLeft -= bits; + } + } + + // overload for TValue, for better performance + void writeBitsInternal(const UnsignedType& v, size_t size) + { + if (size > 0) { + _scratch |= static_cast(v) << _scratchBits; + _scratchBits += size; + if (_scratchBits >= details::BitsSize::value) { + auto tmp = static_cast(_scratch & _MASK); + this->_wrapped.template writeBytes( + tmp); + _scratch >>= details::BitsSize::value; + _scratchBits -= details::BitsSize::value; + } + } + } + + const UnsignedType _MASK = (std::numeric_limits::max)(); + ScratchType _scratch{}; + size_t _scratchBits{}; +}; +} } - -#endif //BITSERY_DETAILS_ADAPTER_BIT_PACKING_H +#endif // BITSERY_DETAILS_ADAPTER_BIT_PACKING_H diff --git a/include/bitsery/details/adapter_common.h b/include/bitsery/details/adapter_common.h index 5e06649..7f665d4 100644 --- a/include/bitsery/details/adapter_common.h +++ b/include/bitsery/details/adapter_common.h @@ -1,360 +1,427 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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_DETAILS_ADAPTER_COMMON_H #define BITSERY_DETAILS_ADAPTER_COMMON_H -#include "not_defined_type.h" #include "../common.h" +#include "not_defined_type.h" #include #include #include namespace bitsery { - enum class ReaderError { - NoError, - ReadingError, // this might be used with stream adapter - DataOverflow, - InvalidData, - InvalidPointer - }; +enum class ReaderError +{ + NoError, + ReadingError, // this might be used with stream adapter + DataOverflow, + InvalidData, + InvalidPointer +}; - namespace details { +namespace details { - /** - * size read/write functions - */ +/** + * size read/write functions + */ - template - void handleReadMaxSize(Reader& r, size_t& size, size_t maxSize, std::true_type) { - if (size > maxSize) { - r.error(ReaderError::InvalidData); - size = {}; - } - } - - template - void handleReadMaxSize(Reader&, size_t&, size_t, std::false_type) { - } - - template - void readSize(Reader& r, size_t& size, size_t maxSize, std::integral_constant checkMaxSize) { - uint8_t hb{}; - r.template readBytes<1>(hb); - if (hb < 0x80u) { - size = hb; - } else { - uint8_t lb{}; - r.template readBytes<1>(lb); - if (hb & 0x40u) { - uint16_t lw{}; - r.template readBytes<2>(lw); - size = ((((hb & 0x3Fu) << 8) | lb) << 16) | lw; - } else { - size = ((hb & 0x7Fu) << 8) | lb; - } - } - handleReadMaxSize(r, size, maxSize, checkMaxSize); - } - - template - void writeSize(Writer& w, const size_t size) { - if (size < 0x80u) { - w.template writeBytes<1>(static_cast(size)); - } else { - if (size < 0x4000u) { - w.template writeBytes<1>(static_cast((size >> 8) | 0x80u)); - w.template writeBytes<1>(static_cast(size)); - } else { - assert(size < 0x40000000u); - w.template writeBytes<1>(static_cast((size >> 24) | 0xC0u)); - w.template writeBytes<1>(static_cast(size >> 16)); - w.template writeBytes<2>(static_cast(size)); - } - } - } - - /** - * swap utils - */ - - //add swap functions to class, to avoid compilation warning about unused functions - struct SwapImpl { - static uint64_t exec(uint64_t value) { -#ifdef __GNUC__ - return __builtin_bswap64(value); -#else - value = ( value & 0x00000000FFFFFFFF ) << 32 | ( value & 0xFFFFFFFF00000000 ) >> 32; - value = ( value & 0x0000FFFF0000FFFF ) << 16 | ( value & 0xFFFF0000FFFF0000 ) >> 16; - value = ( value & 0x00FF00FF00FF00FF ) << 8 | ( value & 0xFF00FF00FF00FF00 ) >> 8; - return value; -#endif - } - - static uint32_t exec(uint32_t value) { -#ifdef __GNUC__ - return __builtin_bswap32(value); -#else - return ( value & 0x000000ff ) << 24 | ( value & 0x0000ff00 ) << 8 | ( value & 0x00ff0000 ) >> 8 | ( value & 0xff000000 ) >> 24; -#endif - } - - static uint16_t exec(uint16_t value) { - return static_cast((value & 0x00ff) << 8 | (value & 0xff00) >> 8); - } - - static uint8_t exec(uint8_t value) { - return value; - } - }; - - template - TValue swap(TValue value) { - constexpr size_t TSize = sizeof(TValue); - using UT = typename std::conditional::type>::type>::type; - return static_cast(SwapImpl::exec(static_cast(value))); - } - - /** - * endianness utils - */ - // add test data in separate struct, because some compilers only support constexpr functions with return-only body - // suppress msvc warnings. -#ifdef _MSC_VER - #pragma warning( disable : 4310 ) -#endif - struct EndiannessTestData { - static constexpr uint32_t _sample4Bytes = 0x01020304; - static constexpr uint8_t _sample1stByte = (const uint8_t &) _sample4Bytes; - }; -#ifdef _MSC_VER - #pragma warning( default : 4310 ) -#endif - - constexpr EndiannessType getSystemEndianness() { - static_assert(EndiannessTestData::_sample1stByte == 0x04 || EndiannessTestData::_sample1stByte == 0x01, - "system must be either little or big endian"); - return EndiannessTestData::_sample1stByte == 0x04 ? EndiannessType::LittleEndian - : EndiannessType::BigEndian; - } - - template - using ShouldSwap = std::integral_constant; - - /** - * helper types to work with bits - */ - template - struct BitsSize:public std::integral_constant { - static_assert(CHAR_BIT == 8, "only support systems with byte size of 8 bits"); - }; - - template - struct ScratchType { - using type = NotDefinedType; - }; - - template<> - struct ScratchType { - using type = uint_fast16_t; - }; - - template - struct FastType { - using type = T; - }; - - template<> - struct FastType { - using type = uint_fast8_t; - }; - - template<> - struct FastType { - using type = uint_fast16_t; - }; - - template<> - struct FastType { - using type = uint_fast32_t; - }; - - template<> - struct FastType { - using type = uint_fast64_t; - }; - - template<> - struct FastType { - using type = int_fast8_t; - }; - - template<> - struct FastType { - using type = int_fast16_t; - }; - - template<> - struct FastType { - using type = int_fast32_t; - }; - - template<> - struct FastType { - using type = int_fast64_t; - }; - - /** - * output/input adapter base that handles endianness - */ - - template - struct OutputAdapterBaseCRTP { - - template - void writeBytes(const T &v) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); - writeSwappedValue(&v, ShouldSwap{}); - } - - template - void writeBuffer(const T *buf, size_t count) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); - writeSwappedBuffer(buf, count, ShouldSwap{}); - } - - template - void writeBits(const T &, size_t ) { - static_assert(std::is_void::value, - "Bit-packing is not enabled.\nEnable by call to `enableBitPacking`) or create Serializer with bit packing enabled."); - } - - void align() { - - } - - OutputAdapterBaseCRTP() = default; - OutputAdapterBaseCRTP(const OutputAdapterBaseCRTP&) = delete; - OutputAdapterBaseCRTP& operator = (const OutputAdapterBaseCRTP&) = delete; - OutputAdapterBaseCRTP(OutputAdapterBaseCRTP&&) = default; - OutputAdapterBaseCRTP& operator = (OutputAdapterBaseCRTP&&) = default; - - private: - - template - void writeSwappedValue(const T *v, std::true_type) { - const auto res = details::swap(*v); - static_cast(this)->template writeInternalValue(reinterpret_cast(&res)); - } - - template - void writeSwappedValue(const T *v, std::false_type) { - static_cast(this)->template writeInternalValue(reinterpret_cast(v)); - } - - template - void writeSwappedBuffer(const T *v, size_t count, std::true_type) { - std::for_each(v, std::next(v, count), [this](const T &inner_v) { - const auto res = details::swap(inner_v); - static_cast(this)->template writeInternalValue(reinterpret_cast(&res)); - }); - } - - template - void writeSwappedBuffer(const T *v, size_t count, std::false_type) { - static_cast(this)->writeInternalBuffer(reinterpret_cast(v), count * sizeof(T)); - } - - }; - - - template - struct InputAdapterBaseCRTP { - - template - void readBytes(T& v) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); - static_cast(this)->template readInternalValue(reinterpret_cast(&v)); - swapDataBits(v, ShouldSwap{}); - } - - template - void readBuffer(T* buf, size_t count) { - static_assert(std::is_integral(), ""); - static_assert(sizeof(T) == SIZE, ""); - static_cast(this)->readInternalBuffer(reinterpret_cast(buf), sizeof(T) * count); - swapDataBits(buf, count, ShouldSwap{}); - } - - template - void readBits(T&, size_t) { - static_assert(std::is_void::value, - "Bit-packing is not enabled.\nEnable by call to `enableBitPacking`) or create Deserializer with bit packing enabled."); - } - - void align() { - - } - - InputAdapterBaseCRTP() = default; - InputAdapterBaseCRTP(const InputAdapterBaseCRTP&) = delete; - InputAdapterBaseCRTP& operator = (const InputAdapterBaseCRTP&) = delete; - - InputAdapterBaseCRTP(InputAdapterBaseCRTP&&) = default; - InputAdapterBaseCRTP& operator = (InputAdapterBaseCRTP&&) = default; - - virtual ~InputAdapterBaseCRTP() = default; - - private: - - template - void swapDataBits(T *v, size_t count, std::true_type) { - using diff_t = typename std::iterator_traits::difference_type; - std::for_each(v, std::next(v, static_cast(count)), [](T &x) { x = details::swap(x); }); - } - - template - void swapDataBits(T *, size_t , std::false_type) { - //empty function because no swap is required - } - - template - void swapDataBits(T &v, std::true_type) { - v = details::swap(v); - } - - template - void swapDataBits(T &, std::false_type) { - //empty function because no swap is required - } - }; - } +template +void +handleReadMaxSize(Reader& r, size_t& size, size_t maxSize, std::true_type) +{ + if (size > maxSize) { + r.error(ReaderError::InvalidData); + size = {}; + } } +template +void +handleReadMaxSize(Reader&, size_t&, size_t, std::false_type) +{ +} -#endif //BITSERY_DETAILS_ADAPTER_COMMON_H +template +void +readSize(Reader& r, + size_t& size, + size_t maxSize, + std::integral_constant checkMaxSize) +{ + uint8_t hb{}; + r.template readBytes<1>(hb); + if (hb < 0x80u) { + size = hb; + } else { + uint8_t lb{}; + r.template readBytes<1>(lb); + if (hb & 0x40u) { + uint16_t lw{}; + r.template readBytes<2>(lw); + size = ((((hb & 0x3Fu) << 8) | lb) << 16) | lw; + } else { + size = ((hb & 0x7Fu) << 8) | lb; + } + } + handleReadMaxSize(r, size, maxSize, checkMaxSize); +} + +template +void +writeSize(Writer& w, const size_t size) +{ + if (size < 0x80u) { + w.template writeBytes<1>(static_cast(size)); + } else { + if (size < 0x4000u) { + w.template writeBytes<1>(static_cast((size >> 8) | 0x80u)); + w.template writeBytes<1>(static_cast(size)); + } else { + assert(size < 0x40000000u); + w.template writeBytes<1>(static_cast((size >> 24) | 0xC0u)); + w.template writeBytes<1>(static_cast(size >> 16)); + w.template writeBytes<2>(static_cast(size)); + } + } +} + +/** + * swap utils + */ + +// add swap functions to class, to avoid compilation warning about unused +// functions +struct SwapImpl +{ + static uint64_t exec(uint64_t value) + { +#ifdef __GNUC__ + return __builtin_bswap64(value); +#else + value = + (value & 0x00000000FFFFFFFF) << 32 | (value & 0xFFFFFFFF00000000) >> 32; + value = + (value & 0x0000FFFF0000FFFF) << 16 | (value & 0xFFFF0000FFFF0000) >> 16; + value = + (value & 0x00FF00FF00FF00FF) << 8 | (value & 0xFF00FF00FF00FF00) >> 8; + return value; +#endif + } + + static uint32_t exec(uint32_t value) + { +#ifdef __GNUC__ + return __builtin_bswap32(value); +#else + return (value & 0x000000ff) << 24 | (value & 0x0000ff00) << 8 | + (value & 0x00ff0000) >> 8 | (value & 0xff000000) >> 24; +#endif + } + + static uint16_t exec(uint16_t value) + { + return static_cast((value & 0x00ff) << 8 | (value & 0xff00) >> 8); + } + + static uint8_t exec(uint8_t value) + { + return value; + } +}; + +template +TValue +swap(TValue value) +{ + constexpr size_t TSize = sizeof(TValue); + using UT = typename std::conditional< + TSize == 1, + uint8_t, + typename std::conditional< + TSize == 2, + uint16_t, + typename std::conditional::type>::type>:: + type; + return static_cast(SwapImpl::exec(static_cast(value))); +} + +/** + * endianness utils + */ +// add test data in separate struct, because some compilers only support +// constexpr functions with return-only body suppress msvc warnings. +#ifdef _MSC_VER +#pragma warning(disable : 4310) +#endif +struct EndiannessTestData +{ + static constexpr uint32_t _sample4Bytes = 0x01020304; + static constexpr uint8_t _sample1stByte = (const uint8_t&)_sample4Bytes; +}; +#ifdef _MSC_VER +#pragma warning(default : 4310) +#endif + +constexpr EndiannessType +getSystemEndianness() +{ + static_assert(EndiannessTestData::_sample1stByte == 0x04 || + EndiannessTestData::_sample1stByte == 0x01, + "system must be either little or big endian"); + return EndiannessTestData::_sample1stByte == 0x04 + ? EndiannessType::LittleEndian + : EndiannessType::BigEndian; +} + +template +using ShouldSwap = + std::integral_constant; + +/** + * helper types to work with bits + */ +template +struct BitsSize : public std::integral_constant +{ + static_assert(CHAR_BIT == 8, "only support systems with byte size of 8 bits"); +}; + +template +struct ScratchType +{ + using type = NotDefinedType; +}; + +template<> +struct ScratchType +{ + using type = uint_fast16_t; +}; + +template +struct FastType +{ + using type = T; +}; + +template<> +struct FastType +{ + using type = uint_fast8_t; +}; + +template<> +struct FastType +{ + using type = uint_fast16_t; +}; + +template<> +struct FastType +{ + using type = uint_fast32_t; +}; + +template<> +struct FastType +{ + using type = uint_fast64_t; +}; + +template<> +struct FastType +{ + using type = int_fast8_t; +}; + +template<> +struct FastType +{ + using type = int_fast16_t; +}; + +template<> +struct FastType +{ + using type = int_fast32_t; +}; + +template<> +struct FastType +{ + using type = int_fast64_t; +}; + +/** + * output/input adapter base that handles endianness + */ + +template +struct OutputAdapterBaseCRTP +{ + + template + void writeBytes(const T& v) + { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); + writeSwappedValue(&v, ShouldSwap{}); + } + + template + void writeBuffer(const T* buf, size_t count) + { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); + writeSwappedBuffer(buf, count, ShouldSwap{}); + } + + template + void writeBits(const T&, size_t) + { + static_assert( + std::is_void::value, + "Bit-packing is not enabled.\nEnable by call to `enableBitPacking`) or " + "create Serializer with bit packing enabled."); + } + + void align() {} + + OutputAdapterBaseCRTP() = default; + OutputAdapterBaseCRTP(const OutputAdapterBaseCRTP&) = delete; + OutputAdapterBaseCRTP& operator=(const OutputAdapterBaseCRTP&) = delete; + OutputAdapterBaseCRTP(OutputAdapterBaseCRTP&&) = default; + OutputAdapterBaseCRTP& operator=(OutputAdapterBaseCRTP&&) = default; + +private: + template + void writeSwappedValue(const T* v, std::true_type) + { + const auto res = details::swap(*v); + static_cast(this)->template writeInternalValue( + reinterpret_cast(&res)); + } + + template + void writeSwappedValue(const T* v, std::false_type) + { + static_cast(this)->template writeInternalValue( + reinterpret_cast(v)); + } + + template + void writeSwappedBuffer(const T* v, size_t count, std::true_type) + { + std::for_each(v, std::next(v, count), [this](const T& inner_v) { + const auto res = details::swap(inner_v); + static_cast(this)->template writeInternalValue( + reinterpret_cast(&res)); + }); + } + + template + void writeSwappedBuffer(const T* v, size_t count, std::false_type) + { + static_cast(this)->writeInternalBuffer( + reinterpret_cast(v), count * sizeof(T)); + } +}; + +template +struct InputAdapterBaseCRTP +{ + + template + void readBytes(T& v) + { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); + static_cast(this)->template readInternalValue( + reinterpret_cast(&v)); + swapDataBits(v, ShouldSwap{}); + } + + template + void readBuffer(T* buf, size_t count) + { + static_assert(std::is_integral(), ""); + static_assert(sizeof(T) == SIZE, ""); + static_cast(this)->readInternalBuffer( + reinterpret_cast(buf), sizeof(T) * count); + swapDataBits(buf, count, ShouldSwap{}); + } + + template + void readBits(T&, size_t) + { + static_assert( + std::is_void::value, + "Bit-packing is not enabled.\nEnable by call to `enableBitPacking`) or " + "create Deserializer with bit packing enabled."); + } + + void align() {} + + InputAdapterBaseCRTP() = default; + InputAdapterBaseCRTP(const InputAdapterBaseCRTP&) = delete; + InputAdapterBaseCRTP& operator=(const InputAdapterBaseCRTP&) = delete; + + InputAdapterBaseCRTP(InputAdapterBaseCRTP&&) = default; + InputAdapterBaseCRTP& operator=(InputAdapterBaseCRTP&&) = default; + + virtual ~InputAdapterBaseCRTP() = default; + +private: + template + void swapDataBits(T* v, size_t count, std::true_type) + { + using diff_t = typename std::iterator_traits::difference_type; + std::for_each(v, std::next(v, static_cast(count)), [](T& x) { + x = details::swap(x); + }); + } + + template + void swapDataBits(T*, size_t, std::false_type) + { + // empty function because no swap is required + } + + template + void swapDataBits(T& v, std::true_type) + { + v = details::swap(v); + } + + template + void swapDataBits(T&, std::false_type) + { + // empty function because no swap is required + } +}; +} +} + +#endif // BITSERY_DETAILS_ADAPTER_COMMON_H diff --git a/include/bitsery/details/brief_syntax_common.h b/include/bitsery/details/brief_syntax_common.h index 5fdbe0d..993dae6 100644 --- a/include/bitsery/details/brief_syntax_common.h +++ b/include/bitsery/details/brief_syntax_common.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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_DETAILS_BRIEF_SYNTAX_COMMON_H #define BITSERY_DETAILS_BRIEF_SYNTAX_COMMON_H @@ -28,123 +28,173 @@ #include namespace bitsery { - namespace brief_syntax { +namespace brief_syntax { - //these function overloads is required to apply maxSize, and optimize for fundamental types - //for contigous arrays of fundamenal types, memcpy will be applied +// these function overloads is required to apply maxSize, and optimize for +// fundamental types for contigous arrays of fundamenal types, memcpy will be +// applied - template::TValue>::value - && traits::ContainerTraits::isResizable - >::type * = nullptr> - void processContainer(S &s, T &c, size_t maxSize = std::numeric_limits::max()) { - using TValue = typename traits::ContainerTraits::TValue; - s.template container(c, maxSize); - } - - template::TValue>::value - && traits::ContainerTraits::isResizable - >::type * = nullptr> - void processContainer(S &s, T &c, size_t maxSize = std::numeric_limits::max()) { - s.container(c, maxSize); - } - - template::TValue>::value - && !traits::ContainerTraits::isResizable - >::type * = nullptr> - void processContainer(S &s, T &c) { - using TValue = typename traits::ContainerTraits::TValue; - s.template container(c); - } - - template::TValue>::value - && !traits::ContainerTraits::isResizable - >::type * = nullptr> - void processContainer(S &s, T &c) { - s.container(c); - } - - //overloads for text processing to apply maxSize - - template::isResizable>::type * = nullptr> - void processText(S &s, T &c, size_t maxSize = std::numeric_limits::max()) { - using TValue = typename traits::ContainerTraits::TValue; - s.template text(c, maxSize); - } - - template::isResizable>::type * = nullptr> - void processText(S &s, T &c) { - using TValue = typename traits::ContainerTraits::TValue; - s.template text(c); - } - - - //all wrapper functions, that modify behaviour, should inherit from this - struct ModFnc { - - }; - - //this type is used to differentiate between container and text behaviour - template - struct CArray : public ModFnc { - CArray(T (&data_)[N]) : data{data_} {}; - T (&data)[N]; - }; - - template - void serialize(S &s, CArray &str) { - processText(s, str.data); - } - - template - void serialize(S &s, CArray &obj) { - processContainer(s, obj.data); - } - - //used to set max container size - template - struct MaxSize : public ModFnc { - MaxSize(T &data_, size_t maxSize_) : data{data_}, maxSize{maxSize_} {}; - T &data; - size_t maxSize; - }; - - //if container, then call procesContainer, this memcpy for fundamental types contiguous container - template - void processMaxSize(S &s, T& data, size_t maxSize, std::true_type) { - processContainer(s, data, maxSize); - } - - //overload for const T& - template - void processMaxSize(S &s, const T& data, size_t maxSize, std::true_type) { - processContainer(s, const_cast(data), maxSize); - } - - - //try to call serialize overload with maxsize, extensions use this technique - template - void processMaxSize(S &s, T& data, size_t maxSize, std::false_type) { - serialize(s, data, maxSize); - } - - //overload for const T& - template - void processMaxSize(S &s, const T& data, size_t maxSize, std::false_type) { - serialize(s, const_cast(data), maxSize); - } - - template - void serialize(S &s, const MaxSize &ms) { - processMaxSize(s, ms.data, ms.maxSize, details::IsContainerTraitsDefined::type>{}); - } - - } +template::TValue>::value && + traits::ContainerTraits::isResizable>::type* = nullptr> +void +processContainer(S& s, + T& c, + size_t maxSize = std::numeric_limits::max()) +{ + using TValue = typename traits::ContainerTraits::TValue; + s.template container(c, maxSize); } -#endif //BITSERY_DETAILS_BRIEF_SYNTAX_COMMON_H +template::TValue>::value && + traits::ContainerTraits::isResizable>::type* = nullptr> +void +processContainer(S& s, + T& c, + size_t maxSize = std::numeric_limits::max()) +{ + s.container(c, maxSize); +} + +template::TValue>::value && + !traits::ContainerTraits::isResizable>::type* = nullptr> +void +processContainer(S& s, T& c) +{ + using TValue = typename traits::ContainerTraits::TValue; + s.template container(c); +} + +template::TValue>::value && + !traits::ContainerTraits::isResizable>::type* = nullptr> +void +processContainer(S& s, T& c) +{ + s.container(c); +} + +// overloads for text processing to apply maxSize + +template::isResizable>::type* = nullptr> +void +processText(S& s, T& c, size_t maxSize = std::numeric_limits::max()) +{ + using TValue = typename traits::ContainerTraits::TValue; + s.template text(c, maxSize); +} + +template::isResizable>::type* = nullptr> +void +processText(S& s, T& c) +{ + using TValue = typename traits::ContainerTraits::TValue; + s.template text(c); +} + +// all wrapper functions, that modify behaviour, should inherit from this +struct ModFnc +{}; + +// this type is used to differentiate between container and text behaviour +template +struct CArray : public ModFnc +{ + CArray(T (&data_)[N]) + : data{ data_ } {}; + T (&data)[N]; +}; + +template +void +serialize(S& s, CArray& str) +{ + processText(s, str.data); +} + +template +void +serialize(S& s, CArray& obj) +{ + processContainer(s, obj.data); +} + +// used to set max container size +template +struct MaxSize : public ModFnc +{ + MaxSize(T& data_, size_t maxSize_) + : data{ data_ } + , maxSize{ maxSize_ } {}; + T& data; + size_t maxSize; +}; + +// if container, then call procesContainer, this memcpy for fundamental types +// contiguous container +template +void +processMaxSize(S& s, T& data, size_t maxSize, std::true_type) +{ + processContainer(s, data, maxSize); +} + +// overload for const T& +template +void +processMaxSize(S& s, const T& data, size_t maxSize, std::true_type) +{ + processContainer(s, const_cast(data), maxSize); +} + +// try to call serialize overload with maxsize, extensions use this technique +template +void +processMaxSize(S& s, T& data, size_t maxSize, std::false_type) +{ + serialize(s, data, maxSize); +} + +// overload for const T& +template +void +processMaxSize(S& s, const T& data, size_t maxSize, std::false_type) +{ + serialize(s, const_cast(data), maxSize); +} + +template +void +serialize(S& s, const MaxSize& ms) +{ + processMaxSize( + s, + ms.data, + ms.maxSize, + details::IsContainerTraitsDefined::type>{}); +} + +} +} + +#endif // BITSERY_DETAILS_BRIEF_SYNTAX_COMMON_H diff --git a/include/bitsery/details/not_defined_type.h b/include/bitsery/details/not_defined_type.h index 346ba66..defe57f 100644 --- a/include/bitsery/details/not_defined_type.h +++ b/include/bitsery/details/not_defined_type.h @@ -1,25 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_DETAILS_NOT_DEFINED_TYPE_H #define BITSERY_DETAILS_NOT_DEFINED_TYPE_H @@ -27,53 +26,57 @@ #include namespace bitsery { - namespace details { - //this type is used to show clearer error messages - struct NotDefinedType { - //just swallow anything that is passed during creating - template - NotDefinedType(T&& ...){} - NotDefinedType() = default; - //define operators so that we also swallow deeper errors, to reduce error stack - //this time will be used as iterator, so define all operators necessary to work with iterators - friend bool operator == (const NotDefinedType&, const NotDefinedType&) { - return true; - } - friend bool operator != (const NotDefinedType&, const NotDefinedType&) { - return false; - } - NotDefinedType& operator += (int) { - return *this; - } - NotDefinedType& operator -= (int) { - return *this; - } +namespace details { +// this type is used to show clearer error messages +struct NotDefinedType +{ + // just swallow anything that is passed during creating + template + NotDefinedType(T&&...) + { + } + NotDefinedType() = default; + // define operators so that we also swallow deeper errors, to reduce error + // stack this time will be used as iterator, so define all operators necessary + // to work with iterators + friend bool operator==(const NotDefinedType&, const NotDefinedType&) + { + return true; + } + friend bool operator!=(const NotDefinedType&, const NotDefinedType&) + { + return false; + } + NotDefinedType& operator+=(int) { return *this; } + NotDefinedType& operator-=(int) { return *this; } - friend int operator - (const NotDefinedType&, const NotDefinedType&) { - return 0; - } + friend int operator-(const NotDefinedType&, const NotDefinedType&) + { + return 0; + } - int& operator*() { - return data; - } - int data{}; - }; + int& operator*() { return data; } + int data{}; +}; - template - struct IsDefined:public std::integral_constant::value> { - }; - } +template +struct IsDefined + : public std::integral_constant::value> +{ +}; +} } namespace std { - //define iterator traits to work with standart algorithms - template <> - struct iterator_traits { - using difference_type = int; - using value_type = int; - using pointer = int*; - using reference = int&; - using iterator_category = std::random_access_iterator_tag; - }; +// define iterator traits to work with standart algorithms +template<> +struct iterator_traits +{ + using difference_type = int; + using value_type = int; + using pointer = int*; + using reference = int&; + using iterator_category = std::random_access_iterator_tag; +}; } -#endif //BITSERY_DETAILS_NOT_DEFINED_TYPE_H +#endif // BITSERY_DETAILS_NOT_DEFINED_TYPE_H diff --git a/include/bitsery/details/serialization_common.h b/include/bitsery/details/serialization_common.h index 6edc288..b97ce1e 100644 --- a/include/bitsery/details/serialization_common.h +++ b/include/bitsery/details/serialization_common.h @@ -1,464 +1,563 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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_DETAILS_SERIALIZATION_COMMON_H #define BITSERY_DETAILS_SERIALIZATION_COMMON_H -#include "adapter_common.h" #include "../traits/core/traits.h" +#include "adapter_common.h" #include namespace bitsery { - //this allows to call private serialize method, and construct instance (if no default constructor is provided) for your type - //just make friend it in your class - class Access { - public: - template - static auto serialize(S &s, T &obj) -> decltype(obj.serialize(s)) { - obj.serialize(s); - } +// this allows to call private serialize method, and construct instance (if no +// default constructor is provided) for your type just make friend it in your +// class +class Access +{ +public: + template + static auto serialize(S& s, T& obj) -> decltype(obj.serialize(s)) + { + obj.serialize(s); + } - template - static T create() { - //if you get an error here, please create default constructor - return T{}; - } - template - static T* create(void* ptr) { - return new(ptr) T{}; - } + template + static T create() + { + // if you get an error here, please create default constructor + return T{}; + } + template + static T* create(void* ptr) + { + return new (ptr) T{}; + } +}; - }; +// convenient functors that can be passed as lambda to serializer/deserializer +// instead of writing lambda e.g. instead of writing this: s.container(c, 100, +// [](S& s, float& v) { s.ext4b(v, CompactValue{});}); you can write like this +// s.container(c, 100, FtorExtValue2b{}); +template +struct FtorExtValue : public Ext +{ + template + void operator()(S& s, T& v) const + { + s.template ext(v, static_cast(*this)); + } +}; +template +struct FtorExtValue1b : FtorExtValue<1, Ext> +{ +}; +template +struct FtorExtValue2b : FtorExtValue<2, Ext> +{ +}; +template +struct FtorExtValue4b : FtorExtValue<4, Ext> +{ +}; +template +struct FtorExtValue8b : FtorExtValue<8, Ext> +{ +}; +template +struct FtorExtValue16b : FtorExtValue<16, Ext> +{ +}; - // convenient functors that can be passed as lambda to serializer/deserializer instead of writing lambda - // e.g. instead of writing this: - // s.container(c, 100, [](S& s, float& v) { s.ext4b(v, CompactValue{});}); - // you can write like this - // s.container(c, 100, FtorExtValue2b{}); - template - struct FtorExtValue : public Ext { - template - void operator()(S& s, T& v) const { - s.template ext(v, static_cast(*this)); - } - }; +template +struct FtorExtObject : public Ext +{ + template + void operator()(S& s, T& v) const + { + s.ext(v, static_cast(*this)); + } +}; - template - struct FtorExtValue1b: FtorExtValue<1, Ext> {}; - template - struct FtorExtValue2b: FtorExtValue<2, Ext> {}; - template - struct FtorExtValue4b: FtorExtValue<4, Ext> {}; - template - struct FtorExtValue8b: FtorExtValue<8, Ext> {}; - template - struct FtorExtValue16b: FtorExtValue<16, Ext> {}; +// when call to serialize function is ambiguous (member and non-member serialize +// function exists for a type) specialize this class by inheriting from either +// UseNonMemberFnc or UseMemberFnc e.g. template <> struct +// SelectSerializeFnc:UseMemberFnc {}; +template +struct SelectSerializeFnc : std::integral_constant +{ +}; - template - struct FtorExtObject : public Ext { - template - void operator()(S& s, T& v) const { - s.ext(v, static_cast(*this)); - } - }; +// types you need to inherit from when specializing SelectSerializeFnc class +struct UseNonMemberFnc : std::integral_constant +{}; +struct UseMemberFnc : std::integral_constant +{}; +namespace details { - //when call to serialize function is ambiguous (member and non-member serialize function exists for a type) - //specialize this class by inheriting from either UseNonMemberFnc or UseMemberFnc - //e.g. - //template <> struct SelectSerializeFnc:UseMemberFnc {}; - template - struct SelectSerializeFnc : std::integral_constant { - }; +// helper types for error handling +template +struct IsContainerTraitsDefined + : public IsDefined::TValue> +{ +}; - //types you need to inherit from when specializing SelectSerializeFnc class - struct UseNonMemberFnc : std::integral_constant { - }; - struct UseMemberFnc : std::integral_constant { - }; +template +struct IsTextTraitsDefined + : public IsDefined::TValue> +{ +}; - namespace details { - - //helper types for error handling - template - struct IsContainerTraitsDefined : public IsDefined::TValue> { - }; - - template - struct IsTextTraitsDefined : public IsDefined::TValue> { - }; - - template - struct IsExtensionTraitsDefined : public IsDefined::TValue> { - }; +template +struct IsExtensionTraitsDefined + : public IsDefined::TValue> +{ +}; #ifdef _MSC_VER - //helper types for HasSerializeFunction - template - using TrySerializeFunction = decltype(serialize(std::declval(), std::declval())); +// helper types for HasSerializeFunction +template +using TrySerializeFunction = + decltype(serialize(std::declval(), std::declval())); - template - struct HasSerializeFunctionHelper { - template > - static std::true_type tester(Q&&, R&&); - static std::false_type tester(...); - using type = decltype(tester(std::declval(), std::declval())); - }; - template - struct HasSerializeFunction :HasSerializeFunctionHelper::type {}; +template +struct HasSerializeFunctionHelper +{ + template> + static std::true_type tester(Q&&, R&&); + static std::false_type tester(...); + using type = decltype(tester(std::declval(), std::declval())); +}; +template +struct HasSerializeFunction : HasSerializeFunctionHelper::type +{ +}; - //helper types for HasSerializeMethod - template - using TrySerializeMethod = decltype(Access::serialize(std::declval(), std::declval())); +// helper types for HasSerializeMethod +template +using TrySerializeMethod = + decltype(Access::serialize(std::declval(), std::declval())); - template - struct HasSerializeMethodHelper { - template > - static std::true_type tester(Q&&, R&&); - static std::false_type tester(...); - using type = decltype(tester(std::declval(), std::declval())); - }; - template - struct HasSerializeMethod :HasSerializeMethodHelper::type {}; +template +struct HasSerializeMethodHelper +{ + template> + static std::true_type tester(Q&&, R&&); + static std::false_type tester(...); + using type = decltype(tester(std::declval(), std::declval())); +}; +template +struct HasSerializeMethod : HasSerializeMethodHelper::type +{ +}; - //helper types for IsBriefSyntaxIncluded - template - using TryProcessBriefSyntax = decltype(processBriefSyntax(std::declval(), std::declval())); +// helper types for IsBriefSyntaxIncluded +template +using TryProcessBriefSyntax = + decltype(processBriefSyntax(std::declval(), std::declval())); - template - struct IsBriefSyntaxIncludedHelper { - template > - static std::true_type tester(Q&&, R&&); - static std::false_type tester(...); - using type = decltype(tester(std::declval(), std::declval())); - }; +template +struct IsBriefSyntaxIncludedHelper +{ + template> + static std::true_type tester(Q&&, R&&); + static std::false_type tester(...); + using type = decltype(tester(std::declval(), std::declval())); +}; - template - struct IsBriefSyntaxIncluded :IsBriefSyntaxIncludedHelper::type {}; +template +struct IsBriefSyntaxIncluded : IsBriefSyntaxIncludedHelper::type +{ +}; #else - //helper metafunction, that is added to c++17 - template - struct make_void { - typedef void type; - }; - template - using void_t = typename make_void::type; +// helper metafunction, that is added to c++17 +template +struct make_void +{ + typedef void type; +}; +template +using void_t = typename make_void::type; - template - struct HasSerializeFunction : std::false_type { - }; +template +struct HasSerializeFunction : std::false_type +{ +}; - template - struct HasSerializeFunction(), std::declval()))> - > : std::true_type { - }; +template +struct HasSerializeFunction< + S, + T, + void_t(), std::declval()))>> + : std::true_type +{ +}; +template +struct HasSerializeMethod : std::false_type +{ +}; - template - struct HasSerializeMethod : std::false_type { - }; +template +struct HasSerializeMethod< + S, + T, + void_t(), std::declval()))>> + : std::true_type +{ +}; - template - struct HasSerializeMethod(), std::declval()))> - > : std::true_type { - }; +// this solution doesn't work with visual studio, but is more elegant +template +struct IsBriefSyntaxIncluded : std::false_type +{ +}; - //this solution doesn't work with visual studio, but is more elegant - template - struct IsBriefSyntaxIncluded : std::false_type { - }; - - template - struct IsBriefSyntaxIncluded(), std::declval()))> - > : std::true_type { - }; +template +struct IsBriefSyntaxIncluded< + S, + T, + void_t(), std::declval()))>> + : std::true_type +{ +}; #endif - - //used for extensions when extension TValue = void - struct DummyType { - }; +// used for extensions when extension TValue = void +struct DummyType +{}; /* * this includes all integral types, floats and enums(except bool) */ - template - struct IsFundamentalType : std::integral_constant::value - || std::is_floating_point::value - || std::is_integral::value> { - }; +template +struct IsFundamentalType + : std::integral_constant::value || + std::is_floating_point::value || + std::is_integral::value> +{ +}; - template - struct IntegralFromFundamental { - using TValue = T; - }; +template +struct IntegralFromFundamental +{ + using TValue = T; +}; - template - struct IntegralFromFundamental::value>::type> { - using TValue = typename std::underlying_type::type; - }; +template +struct IntegralFromFundamental< + T, + typename std::enable_if::value>::type> +{ + using TValue = typename std::underlying_type::type; +}; - template - struct IntegralFromFundamental::value>::type> { - using TValue = typename std::conditional::value, uint32_t, uint64_t>::type; - }; +template +struct IntegralFromFundamental< + T, + typename std::enable_if::value>::type> +{ + using TValue = typename std:: + conditional::value, uint32_t, uint64_t>::type; +}; - template - struct UnsignedFromFundamental { - using type = typename std::make_unsigned::TValue>::type; - }; - - template - using SameSizeUnsigned = typename UnsignedFromFundamental::type; +template +struct UnsignedFromFundamental +{ + using type = typename std::make_unsigned< + typename IntegralFromFundamental::TValue>::type; +}; +template +using SameSizeUnsigned = typename UnsignedFromFundamental::type; /* * functions for object serialization */ - template - struct SerializeFunction { +template +struct SerializeFunction +{ - static void invoke(S &s, T &v) { - static_assert(HasSerializeFunction::value || HasSerializeMethod::value, - "\nPlease define 'serialize' function for your type (inside or outside of class):\n" - " template\n" - " void serialize(S& s)\n" - " {\n" - " ...\n" - " }\n"); - using TDecayed = typename std::decay::type; - selectSerializeFnc(s, v, SelectSerializeFnc{}); - } + static void invoke(S& s, T& v) + { + static_assert(HasSerializeFunction::value || + HasSerializeMethod::value, + "\nPlease define 'serialize' function for your type (inside " + "or outside of class):\n" + " template\n" + " void serialize(S& s)\n" + " {\n" + " ...\n" + " }\n"); + using TDecayed = typename std::decay::type; + selectSerializeFnc(s, v, SelectSerializeFnc{}); + } - static constexpr bool isDefined() { - return HasSerializeFunction::value || HasSerializeMethod::value; - } + static constexpr bool isDefined() + { + return HasSerializeFunction::value || HasSerializeMethod::value; + } - private: - static void selectSerializeFnc(S &s, T &v, std::integral_constant) { - static_assert(!(HasSerializeFunction::value && HasSerializeMethod::value), - "\nPlease define only one 'serialize' function (member OR free).\n" - "If serialization function is inherited from base class, then explicitly select correct function for your type e.g.:\n" - " template <>\n" - " struct SelectSerializeFnc:UseMemberFnc {};\n"); - selectSerializeFnc(s, v, std::integral_constant::value ? 1 : 2>{}); - } +private: + static void selectSerializeFnc(S& s, T& v, std::integral_constant) + { + static_assert( + !(HasSerializeFunction::value && HasSerializeMethod::value), + "\nPlease define only one 'serialize' function (member OR free).\n" + "If serialization function is inherited from base class, then explicitly " + "select correct function for your type e.g.:\n" + " template <>\n" + " struct SelectSerializeFnc:UseMemberFnc {};\n"); + selectSerializeFnc(s, + v, + std::integral_constant < int, + HasSerializeFunction::value ? 1 : 2 > {}); + } - static void selectSerializeFnc(S &s, T &v, std::integral_constant) { - serialize(s, v); - } + static void selectSerializeFnc(S& s, T& v, std::integral_constant) + { + serialize(s, v); + } - static void selectSerializeFnc(S &s, T &v, std::integral_constant) { - Access::serialize(s, v); - } - }; + static void selectSerializeFnc(S& s, T& v, std::integral_constant) + { + Access::serialize(s, v); + } +}; /* * functions for object serialization */ - template - struct BriefSyntaxFunction { +template +struct BriefSyntaxFunction +{ - static void invoke(S &s, T &&obj) { - static_assert(IsBriefSyntaxIncluded::value, - "\nPlease include '' to use operator():\n"); + static void invoke(S& s, T&& obj) + { + static_assert( + IsBriefSyntaxIncluded::value, + "\nPlease include '' to use operator():\n"); - processBriefSyntax(s, std::forward(obj)); - } - }; + processBriefSyntax(s, std::forward(obj)); + } +}; - /* - * helper function for getting context from serializer/deserializer - */ +/* + * helper function for getting context from serializer/deserializer + */ - template - struct FindIndex : std::integral_constant {}; +template +struct FindIndex : std::integral_constant +{ +}; - template - struct FindIndex : - std::conditional, FindIndex>::type - {}; +template +struct FindIndex + : std::conditional, + FindIndex>::type +{ +}; - template - struct GetConvertibleTypeIndexFromTuple; +template +struct GetConvertibleTypeIndexFromTuple; - template - struct GetConvertibleTypeIndexFromTuple> : FindIndex<0, std::is_convertible...> {}; +template +struct GetConvertibleTypeIndexFromTuple> + : FindIndex<0, std::is_convertible...> +{ +}; +template +struct IsExistsConvertibleTupleType; - template - struct IsExistsConvertibleTupleType; +template +struct IsExistsConvertibleTupleType> + : std::integral_constant< + bool, + GetConvertibleTypeIndexFromTuple>::value != + sizeof...(Us)> +{ +}; - template - struct IsExistsConvertibleTupleType> : - std::integral_constant>::value != sizeof...(Us)> {}; +/* + * get context from internal or external, and check if it's convertible or not + */ +template +TCast* +getDirectlyIfExists(TContext& ctx, std::true_type) +{ + return &static_cast(ctx); +} - /* - * get context from internal or external, and check if it's convertible or not - */ +template +TCast* +getDirectlyIfExists(TContext&, std::false_type) +{ + // TCast cannot be convertible from provided context + static_assert( + !AssertExists, + "Invalid context cast. Context type doesn't exists.\nSome functionality " + "requires (de)seserializer to have specific context."); + return nullptr; +} +template +TCast* +getFromTupleIfExists(std::tuple& ctx, std::true_type) +{ + using TupleIndex = + GetConvertibleTypeIndexFromTuple>; + return &static_cast(std::get(ctx)); +} - template - TCast* getDirectlyIfExists(TContext& ctx, std::true_type) { - return &static_cast(ctx); - } +template +TCast* +getFromTupleIfExists(std::tuple&, std::false_type) +{ + // TCast cannot be convertible from provided context + static_assert( + !AssertExists, + "Invalid context cast. Context type doesn't exists.\nSome functionality " + "requires (de)seserializer to have specific context."); + return nullptr; +} - template - TCast* getDirectlyIfExists(TContext& , std::false_type) { - // TCast cannot be convertible from provided context - static_assert(!AssertExists, - "Invalid context cast. Context type doesn't exists.\nSome functionality requires (de)seserializer to have specific context."); - return nullptr; - } +// non tuple context +template +TCast* +getContext(TContext& ctx) +{ + return getDirectlyIfExists( + ctx, std::is_convertible{}); +} +// tuple context +template +TCast* +getContext(std::tuple& ctx) +{ + return getFromTupleIfExists( + ctx, IsExistsConvertibleTupleType>{}); +} - template - TCast* getFromTupleIfExists(std::tuple& ctx, std::true_type) { - using TupleIndex = GetConvertibleTypeIndexFromTuple>; - return &static_cast(std::get(ctx)); - } +template +class AdapterAndContextRef +{ +public: + static constexpr bool HasContext = true; + using Config = typename Adapter::TConfig; - template - TCast* getFromTupleIfExists(std::tuple& , std::false_type) { - // TCast cannot be convertible from provided context - static_assert(!AssertExists, - "Invalid context cast. Context type doesn't exists.\nSome functionality requires (de)seserializer to have specific context."); - return nullptr; - } + // constructing adapter in place is important, + // because enableBitPacking might create instance with bit write/read enabled + // adapter wrapper, which has non trivial destructor + template + explicit AdapterAndContextRef(Context& ctx, TArgs&&... args) + : _adapter{ std::forward(args)... } + , _context{ ctx } + { + } - //non tuple context - template - TCast* getContext(TContext& ctx) { - return getDirectlyIfExists(ctx, std::is_convertible{}); - } + /* + * get serialization context. + * this is optional, but might be required for some specific serialization + * flows. + */ - //tuple context - template - TCast* getContext(std::tuple& ctx) { - return getFromTupleIfExists(ctx, IsExistsConvertibleTupleType>{}); - } + template + T& context() + { + return *getContext(_context); + } - template - class AdapterAndContextRef { - public: - static constexpr bool HasContext = true; - using Config = typename Adapter::TConfig; + template + T* contextOrNull() + { + return getContext(_context); + } - // constructing adapter in place is important, - // because enableBitPacking might create instance with bit write/read enabled adapter wrapper, - // which has non trivial destructor - template - explicit AdapterAndContextRef(Context& ctx, TArgs&& ... args) - : _adapter{std::forward(args)...}, - _context{ctx} - { - } + Adapter& adapter() & { return _adapter; } - /* - * get serialization context. - * this is optional, but might be required for some specific serialization flows. - */ + Adapter adapter() && { return std::move(_adapter); } - template - T& context() { - return *getContext(_context); - } +protected: + Adapter _adapter; + Context& _context; +}; - template - T* contextOrNull() { - return getContext(_context); - } +template +class AdapterAndContextRef +{ +public: + static constexpr bool HasContext = false; + using Config = typename Adapter::TConfig; - Adapter& adapter() & { - return _adapter; - } + template + explicit AdapterAndContextRef(TArgs&&... args) + : _adapter{ std::forward(args)... } + { + } - Adapter adapter() && { - return std::move(_adapter); - } + template + T& context() + { + static_assert(std::is_void::value, "Context is not defined (is void)."); + } - protected: - Adapter _adapter; - Context& _context; - }; + template + T* contextOrNull() + { + return nullptr; + } - template - class AdapterAndContextRef { - public: - static constexpr bool HasContext = false; - using Config = typename Adapter::TConfig; + Adapter& adapter() & { return _adapter; } - template - explicit AdapterAndContextRef(TArgs&& ... args) - : _adapter{std::forward(args)...} - { - } + Adapter adapter() && { return std::move(_adapter); } - template - T& context() { - static_assert(std::is_void::value, "Context is not defined (is void)."); - } - - template - T* contextOrNull() { - return nullptr; - } - - Adapter& adapter() & { - return _adapter; - } - - Adapter adapter() && { - return std::move(_adapter); - } - - protected: - Adapter _adapter; - }; +protected: + Adapter _adapter; +}; /** * other helper meta-functions */ - template class Template> - struct IsSpecializationOf : std::false_type { - }; +template class Template> +struct IsSpecializationOf : std::false_type +{ +}; - template class Template, typename... Args> - struct IsSpecializationOf, Template> : std::true_type { - }; +template class Template, typename... Args> +struct IsSpecializationOf, Template> : std::true_type +{ +}; - } +} } -#endif //BITSERY_DETAILS_SERIALIZATION_COMMON_H - +#endif // BITSERY_DETAILS_SERIALIZATION_COMMON_H diff --git a/include/bitsery/ext/compact_value.h b/include/bitsery/ext/compact_value.h index 34baee2..0f5daab 100644 --- a/include/bitsery/ext/compact_value.h +++ b/include/bitsery/ext/compact_value.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2018 Mindaugas Vinkelis +// Copyright (c) 2018 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: +// 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 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. +// 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_EXT_COMPACT_VALUE_H #define BITSERY_EXT_COMPACT_VALUE_H @@ -27,162 +27,194 @@ namespace bitsery { - namespace details { +namespace details { - template - class CompactValueImpl { - public: +template +class CompactValueImpl +{ +public: + template + void serialize(Ser& s, const T& v, Fnc&&) const + { + static_assert(std::is_integral::value || std::is_enum::value, ""); + using TValue = typename IntegralFromFundamental::TValue; + serializeImpl(s.adapter(), + reinterpret_cast(v), + std::integral_constant{}); + } - template - void serialize(Ser &s, const T &v, Fnc &&) const { - static_assert(std::is_integral::value || std::is_enum::value, ""); - using TValue = typename IntegralFromFundamental::TValue; - serializeImpl(s.adapter(), reinterpret_cast(v), std::integral_constant{}); - } + template + void deserialize(Des& d, T& v, Fnc&&) const + { + static_assert(std::is_integral::value || std::is_enum::value, ""); + using TValue = typename IntegralFromFundamental::TValue; + deserializeImpl(d.adapter(), + reinterpret_cast(v), + std::integral_constant{}); + } - template - void deserialize(Des &d, T &v, Fnc &&) const { - static_assert(std::is_integral::value || std::is_enum::value, ""); - using TValue = typename IntegralFromFundamental::TValue; - deserializeImpl(d.adapter(), reinterpret_cast(v), std::integral_constant{}); - } +private: + // if value is 1byte size, just serialize/ deserialize whole value + template + void serializeImpl(Writer& writer, const T& v, std::false_type) const + { + writer.template writeBytes<1>(v); + } - private: + template + void deserializeImpl(Reader& reader, T& v, std::false_type) const + { + reader.template readBytes<1>(v); + } - // if value is 1byte size, just serialize/ deserialize whole value - template - void serializeImpl(Writer &writer, const T &v, std::false_type) const { - writer.template writeBytes<1>(v); - } + // when value is bigger than 1byte size, + template + void serializeImpl(Writer& writer, const T& v, std::true_type) const + { + auto val = zigZagEncode( + v, std::is_signed::TValue>{}); + writeBytes(writer, val); + } - template - void deserializeImpl(Reader &reader, T &v, std::false_type) const { - reader.template readBytes<1>(v); - } + template + void deserializeImpl(Reader& reader, T& v, std::true_type) const + { + using TUnsigned = SameSizeUnsigned; + TUnsigned res{}; + readBytes(reader, res); + v = zigZagDecode( + res, std::is_signed::TValue>{}); + } - // when value is bigger than 1byte size, - template - void serializeImpl(Writer &writer, const T &v, std::true_type) const { - auto val = zigZagEncode(v, std::is_signed::TValue>{}); - writeBytes(writer, val); - } + // zigzag encode signed types + template + const SameSizeUnsigned& zigZagEncode(const T& v, std::false_type) const + { + return v; + } + template + const TResult& zigZagDecode(const TUnsigned& v, std::false_type) const + { + return v; + } - template - void deserializeImpl(Reader &reader, T &v, std::true_type) const { - using TUnsigned = SameSizeUnsigned; - TUnsigned res{}; - readBytes(reader, res); - v = zigZagDecode(res, std::is_signed::TValue>{}); - } + template + SameSizeUnsigned zigZagEncode(const T& v, std::true_type) const + { + return static_cast>((v << 1) ^ + (v >> (BitsSize::value - 1))); + } - // zigzag encode signed types - template - const SameSizeUnsigned &zigZagEncode(const T &v, std::false_type) const { - return v; - } - - template - const TResult &zigZagDecode(const TUnsigned &v, std::false_type) const{ - return v; - } - - template - SameSizeUnsigned zigZagEncode(const T &v, std::true_type) const { - return static_cast>((v << 1) ^ (v >> (BitsSize::value - 1))); - } - - template - TResult zigZagDecode(TUnsigned v, std::true_type) const { - return static_cast((v >> 1) ^ (~(v & 1) + 1)); // same as -(v & 1), but no warning on VisualStudio - } - - // write/read bytes one by one - template - void writeBytes(Writer &w, const T &v) const { - using TFast = typename FastType::type; - auto val= static_cast(v); - while(val > 0x7Fu) { - w.template writeBytes<1>(static_cast(val | 0x80u)); - val >>=7u; - } - w.template writeBytes<1>(static_cast(val)); - } - - template - void readBytes(Reader &r, T &v) const { - using TFast = typename FastType::type; - constexpr auto TBITS = sizeof(T)*8; - uint8_t b1{0x80u}; - auto i = 0u; - TFast tmp={}; - for (;i < TBITS && b1 > 0x7Fu; i +=7u) { - r.template readBytes<1>(b1); - tmp += static_cast(b1 & 0x7Fu) << i; - } - v = static_cast(tmp); - handleReadOverflow(r, i, b1, - std::integral_constant{}); - } - template - void handleReadOverflow(Reader& r, unsigned shiftedBy, uint8_t remainder, std::true_type) const { - constexpr auto TBITS = sizeof(T)*8; - if (shiftedBy > TBITS && remainder >> (TBITS + 7 - shiftedBy)) { - r.error(bitsery::ReaderError::InvalidData); - } - } - - template - void handleReadOverflow(Reader &, unsigned , uint8_t , std::false_type) const { - - } - - }; + template + TResult zigZagDecode(TUnsigned v, std::true_type) const + { + return static_cast( + (v >> 1) ^ + (~(v & 1) + 1)); // same as -(v & 1), but no warning on VisualStudio + } + // write/read bytes one by one + template + void writeBytes(Writer& w, const T& v) const + { + using TFast = typename FastType::type; + auto val = static_cast(v); + while (val > 0x7Fu) { + w.template writeBytes<1>(static_cast(val | 0x80u)); + val >>= 7u; } + w.template writeBytes<1>(static_cast(val)); + } - namespace ext { - - // this type will use value overload, and do not check if type is sufficiently large during deserialization - class CompactValue: public details::CompactValueImpl {}; - - // this type will enable object overload, and set DataOverflow if value doesn't fit in type, during deserialization - class CompactValueAsObject: public details::CompactValueImpl {}; - + template + void readBytes(Reader& r, T& v) const + { + using TFast = typename FastType::type; + constexpr auto TBITS = sizeof(T) * 8; + uint8_t b1{ 0x80u }; + auto i = 0u; + TFast tmp = {}; + for (; i < TBITS && b1 > 0x7Fu; i += 7u) { + r.template readBytes<1>(b1); + tmp += static_cast(b1 & 0x7Fu) << i; } - - namespace traits { - - template - struct ExtensionTraits { - using TValue = T; - static constexpr bool SupportValueOverload = true; - // disable object overload, because we don't have implemented serialization function for fundamental types - static constexpr bool SupportObjectOverload = false; - static constexpr bool SupportLambdaOverload = false; - }; - - template - struct ExtensionTraits { - // use dummy implemenations for value and object overload - using TValue = void; - // only enable object overload - static constexpr bool SupportValueOverload = false; - static constexpr bool SupportObjectOverload = true; - static constexpr bool SupportLambdaOverload = false; - }; - - template - struct ExtensionTraits, T> { - using TValue = T; - static constexpr bool SupportValueOverload = !Check; - static constexpr bool SupportObjectOverload = Check; - static constexpr bool SupportLambdaOverload = false; - }; - + v = static_cast(tmp); + handleReadOverflow(r, + i, + b1, + std::integral_constant < bool, + CheckOverflow&& CheckErrors > {}); + } + template + void handleReadOverflow(Reader& r, + unsigned shiftedBy, + uint8_t remainder, + std::true_type) const + { + constexpr auto TBITS = sizeof(T) * 8; + if (shiftedBy > TBITS && remainder >> (TBITS + 7 - shiftedBy)) { + r.error(bitsery::ReaderError::InvalidData); } + } + + template + void handleReadOverflow(Reader&, unsigned, uint8_t, std::false_type) const + { + } +}; } +namespace ext { -#endif //BITSERY_EXT_COMPACT_VALUE_H +// this type will use value overload, and do not check if type is sufficiently +// large during deserialization +class CompactValue : public details::CompactValueImpl +{}; + +// this type will enable object overload, and set DataOverflow if value doesn't +// fit in type, during deserialization +class CompactValueAsObject : public details::CompactValueImpl +{}; + +} + +namespace traits { + +template +struct ExtensionTraits +{ + using TValue = T; + static constexpr bool SupportValueOverload = true; + // disable object overload, because we don't have implemented serialization + // function for fundamental types + static constexpr bool SupportObjectOverload = false; + static constexpr bool SupportLambdaOverload = false; +}; + +template +struct ExtensionTraits +{ + // use dummy implemenations for value and object overload + using TValue = void; + // only enable object overload + static constexpr bool SupportValueOverload = false; + static constexpr bool SupportObjectOverload = true; + static constexpr bool SupportLambdaOverload = false; +}; + +template +struct ExtensionTraits, T> +{ + using TValue = T; + static constexpr bool SupportValueOverload = !Check; + static constexpr bool SupportObjectOverload = Check; + static constexpr bool SupportLambdaOverload = false; +}; + +} + +} + +#endif // BITSERY_EXT_COMPACT_VALUE_H diff --git a/include/bitsery/ext/entropy.h b/include/bitsery/ext/entropy.h index 348531d..79a03ba 100644 --- a/include/bitsery/ext/entropy.h +++ b/include/bitsery/ext/entropy.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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_EXT_ENTROPY_H #define BITSERY_EXT_ENTROPY_H @@ -27,78 +27,88 @@ namespace bitsery { - namespace details { - template - size_t findEntropyIndex(const TValue &v, const TContainer &defValues) { - size_t index{1u}; - for (auto &d:defValues) { - if (d == v) - return index; - ++index; - } - return 0u; - } - } +namespace details { +template +size_t +findEntropyIndex(const TValue& v, const TContainer& defValues) +{ + size_t index{ 1u }; + for (auto& d : defValues) { + if (d == v) + return index; + ++index; + } + return 0u; +} +} - namespace ext { +namespace ext { - template - class Entropy { - public: +template +class Entropy +{ +public: + /** + * Allows entropy-encoding technique, by writing few bits for most common + * values + * @param values list of most common values + * @param alignBeforeData only makes sense when bit-packing enabled, by + * default aligns after writing bits for index + */ + constexpr Entropy(TContainer& values, bool alignBeforeData = true) + : _values{ values } + , _alignBeforeData{ alignBeforeData } {}; - /** - * Allows entropy-encoding technique, by writing few bits for most common values - * @param values list of most common values - * @param alignBeforeData only makes sense when bit-packing enabled, by default aligns after writing bits for index - */ - constexpr Entropy(TContainer& values, bool alignBeforeData=true) - : _values{values}, - _alignBeforeData{alignBeforeData} { - }; + template + void serialize(Ser& s, const T& obj, Fnc&& fnc) const + { + assert(traits::ContainerTraits::size(_values) > 0); + auto index = details::findEntropyIndex(obj, _values); + s.ext(index, + ext::ValueRange{ + 0u, traits::ContainerTraits::size(_values) }); + if (_alignBeforeData) + s.adapter().align(); + if (!index) + fnc(s, const_cast(obj)); + } - template - void serialize(Ser &s, const T &obj, Fnc &&fnc) const { - assert(traits::ContainerTraits::size(_values) > 0); - auto index = details::findEntropyIndex(obj, _values); - s.ext(index, ext::ValueRange{0u, traits::ContainerTraits::size(_values)}); - if (_alignBeforeData) - s.adapter().align(); - if (!index) - fnc(s, const_cast(obj)); - } + template + void deserialize(Des& d, T& obj, Fnc&& fnc) const + { + assert(traits::ContainerTraits::size(_values) > 0); + size_t index{}; + d.ext(index, + ext::ValueRange{ + 0u, traits::ContainerTraits::size(_values) }); + if (_alignBeforeData) + d.adapter().align(); + if (index) { + using TDiff = typename std::iterator_traits::difference_type; + obj = static_cast( + *std::next(std::begin(_values), static_cast(index - 1))); + } else + fnc(d, obj); + } - template - void deserialize(Des &d, T &obj, Fnc &&fnc) const { - assert(traits::ContainerTraits::size(_values) > 0); - size_t index{}; - d.ext(index, ext::ValueRange{0u, traits::ContainerTraits::size(_values)}); - if (_alignBeforeData) - d.adapter().align(); - if (index) { - using TDiff = typename std::iterator_traits::difference_type; - obj = static_cast(*std::next(std::begin(_values), static_cast(index-1))); - } - else - fnc(d, obj); - } +private: + TContainer& _values; + bool _alignBeforeData; +}; +} - private: - TContainer& _values; - bool _alignBeforeData; - }; - } - - namespace traits { - template - struct ExtensionTraits, T> { - using TValue = T; - static constexpr bool SupportValueOverload = true; - static constexpr bool SupportObjectOverload = true; - static constexpr bool SupportLambdaOverload = true; - }; - } +namespace traits { +template +struct ExtensionTraits, T> +{ + using TValue = T; + static constexpr bool SupportValueOverload = true; + static constexpr bool SupportObjectOverload = true; + static constexpr bool SupportLambdaOverload = true; +}; +} } - -#endif //BITSERY_EXT_ENTROPY_H +#endif // BITSERY_EXT_ENTROPY_H diff --git a/include/bitsery/ext/growable.h b/include/bitsery/ext/growable.h index eb8619a..1266a92 100644 --- a/include/bitsery/ext/growable.h +++ b/include/bitsery/ext/growable.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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_EXT_GROWABLE_H #define BITSERY_EXT_GROWABLE_H @@ -27,58 +27,62 @@ namespace bitsery { - namespace ext { +namespace ext { - /* - * enables forward and backward compatibility, by allowing to append additional data at the end of serialization - * old deserialization method will ignore additional data by jumping through it at the end of deserialization flow - * new deserialization method will read all 0 for new fields if there is no data for it - */ - class Growable { - public: +/* + * enables forward and backward compatibility, by allowing to append additional + * data at the end of serialization old deserialization method will ignore + * additional data by jumping through it at the end of deserialization flow new + * deserialization method will read all 0 for new fields if there is no data for + * it + */ +class Growable +{ +public: + template + void serialize(Ser& ser, const T& obj, Fnc&& fnc) const + { + auto& writer = ser.adapter(); + const auto startPos = writer.currentWritePos(); + writer.template writeBytes<4>(static_cast(0)); - template - void serialize(Ser &ser, const T &obj, Fnc &&fnc) const { - auto& writer = ser.adapter(); - const auto startPos = writer.currentWritePos(); - writer.template writeBytes<4>(static_cast(0)); + fnc(ser, const_cast(obj)); - fnc(ser, const_cast(obj)); + const auto endPos = writer.currentWritePos(); + writer.currentWritePos(startPos); + writer.template writeBytes<4>(static_cast(endPos - startPos)); + writer.currentWritePos(endPos); + } - const auto endPos = writer.currentWritePos(); - writer.currentWritePos(startPos); - writer.template writeBytes<4>(static_cast(endPos - startPos)); - writer.currentWritePos(endPos); - } + template + void deserialize(Des& des, T& obj, Fnc&& fnc) const + { + auto& reader = des.adapter(); + uint32_t size{}; + const auto readEndPos = reader.currentReadEndPos(); + const auto startPos = reader.currentReadPos(); + reader.template readBytes<4>(size); + reader.currentReadEndPos(startPos + size); - template - void deserialize(Des &des, T &obj, Fnc &&fnc) const { - auto& reader = des.adapter(); - uint32_t size{}; - const auto readEndPos = reader.currentReadEndPos(); - const auto startPos = reader.currentReadPos(); - reader.template readBytes<4>(size); - reader.currentReadEndPos(startPos + size); + fnc(des, obj); - fnc(des, obj); + reader.currentReadPos(startPos + size); + reader.currentReadEndPos(readEndPos); + } +}; +} - reader.currentReadPos(startPos + size); - reader.currentReadEndPos(readEndPos); - } - }; - } - - namespace traits { - template - struct ExtensionTraits { - using TValue = T; - static constexpr bool SupportValueOverload = false; - static constexpr bool SupportObjectOverload = true; - static constexpr bool SupportLambdaOverload = true; - }; - } +namespace traits { +template +struct ExtensionTraits +{ + using TValue = T; + static constexpr bool SupportValueOverload = false; + static constexpr bool SupportObjectOverload = true; + static constexpr bool SupportLambdaOverload = true; +}; +} } - -#endif //BITSERY_EXT_GROWABLE_H +#endif // BITSERY_EXT_GROWABLE_H diff --git a/include/bitsery/ext/inheritance.h b/include/bitsery/ext/inheritance.h index 803e244..841bf7b 100644 --- a/include/bitsery/ext/inheritance.h +++ b/include/bitsery/ext/inheritance.h @@ -1,162 +1,169 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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_EXT_INHERITANCE_H #define BITSERY_EXT_INHERITANCE_H -#include "../traits/core/traits.h" #include "../ext/utils/memory_resource.h" +#include "../traits/core/traits.h" #include namespace bitsery { - namespace ext { +namespace ext { - //required when virtual inheritance (ext::VirtualBaseClass) exists in serialization flow. - //for standard inheritance (ext::BaseClass) it is optional. - class InheritanceContext { - public: - explicit InheritanceContext(MemResourceBase* memResource = nullptr) - :_virtualBases{pointer_utils::StdPolyAlloc{memResource}} - {} - InheritanceContext(const InheritanceContext&) = delete; - InheritanceContext&operator = (const InheritanceContext&) = delete; - InheritanceContext(InheritanceContext&&) = default; - InheritanceContext& operator = (InheritanceContext&&) = default; - - template - void beginBase(const TDerived &derived, const TBase &) { - if (_depth == 0) { - const void* ptr = std::addressof(derived); - if ( _parentPtr != ptr) - _virtualBases.clear(); - _parentPtr = ptr; - } - ++_depth; - } - - template - bool beginVirtualBase(const TDerived &derived, const TBase &base) { - beginBase(derived, base); - return _virtualBases.emplace(std::addressof(base)).second; - } - - void end() { - --_depth; - } - - private: - //these members are required to know when we can clear _virtualBases - size_t _depth{}; - const void* _parentPtr{}; - //add virtual bases to the list, as long as we're on the same parent - std::unordered_set, std::equal_to, - pointer_utils::StdPolyAlloc - > _virtualBases; - }; - - template - class BaseClass { - public: - - template - void serialize(Ser &ser, const T &obj, Fnc &&fnc) const { - auto& resObj = static_cast(obj); - if (auto ctx = ser.template contextOrNull()) { - ctx->beginBase(obj, resObj); - fnc(ser, const_cast(resObj)); - ctx->end(); - } else { - fnc(ser, const_cast(resObj)); - } - } - - template - void deserialize(Des &des, T &obj, Fnc &&fnc) const { - auto& resObj = static_cast(obj); - if (auto ctx = des.template contextOrNull()) { - ctx->beginBase(obj, resObj); - fnc(des, resObj); - ctx->end(); - } else { - fnc(des, resObj); - } - } - - }; - - //requires InheritanceContext - template - class VirtualBaseClass { - public: - - template - void serialize(Ser &ser, const T &obj, Fnc &&fnc) const { - auto& ctx = ser.template context(); - auto& resObj = static_cast(obj); - if (ctx.beginVirtualBase(obj, resObj)) - fnc(ser, const_cast(resObj)); - ctx.end(); - } - - template - void deserialize(Des &des, T &obj, Fnc &&fnc) const { - auto& ctx = des.template context(); - auto& resObj = static_cast(obj); - if (ctx.beginVirtualBase(obj, resObj)) - fnc(des, resObj); - ctx.end(); - } - - }; +// required when virtual inheritance (ext::VirtualBaseClass) exists in +// serialization flow. for standard inheritance (ext::BaseClass) it is optional. +class InheritanceContext +{ +public: + explicit InheritanceContext(MemResourceBase* memResource = nullptr) + : _virtualBases{ pointer_utils::StdPolyAlloc{ memResource } } + { + } + InheritanceContext(const InheritanceContext&) = delete; + InheritanceContext& operator=(const InheritanceContext&) = delete; + InheritanceContext(InheritanceContext&&) = default; + InheritanceContext& operator=(InheritanceContext&&) = default; + template + void beginBase(const TDerived& derived, const TBase&) + { + if (_depth == 0) { + const void* ptr = std::addressof(derived); + if (_parentPtr != ptr) + _virtualBases.clear(); + _parentPtr = ptr; } + ++_depth; + } - namespace traits { - template - struct ExtensionTraits, T> { - static_assert(std::is_base_of::value, "Invalid base class"); + template + bool beginVirtualBase(const TDerived& derived, const TBase& base) + { + beginBase(derived, base); + return _virtualBases.emplace(std::addressof(base)).second; + } - using TValue = TBase; - static constexpr bool SupportValueOverload = false; - static constexpr bool SupportObjectOverload = true; - static constexpr bool SupportLambdaOverload = true; - }; + void end() { --_depth; } - template - struct ExtensionTraits, T> { - static_assert(std::is_base_of::value, "Invalid base class"); +private: + // these members are required to know when we can clear _virtualBases + size_t _depth{}; + const void* _parentPtr{}; + // add virtual bases to the list, as long as we're on the same parent + std::unordered_set, + std::equal_to, + pointer_utils::StdPolyAlloc> + _virtualBases; +}; - using TValue = TBase; - static constexpr bool SupportValueOverload = false; - static constexpr bool SupportObjectOverload = true; - //disable lambda overload, when serializing virtually inherited base class. - //Only one instance of virtual base will be serialized, when using multiple inheritance - //and it will be undefined behaviour if derived classes would have different virtual base class serialization flow. - static constexpr bool SupportLambdaOverload = false; - }; +template +class BaseClass +{ +public: + template + void serialize(Ser& ser, const T& obj, Fnc&& fnc) const + { + auto& resObj = static_cast(obj); + if (auto ctx = ser.template contextOrNull()) { + ctx->beginBase(obj, resObj); + fnc(ser, const_cast(resObj)); + ctx->end(); + } else { + fnc(ser, const_cast(resObj)); } + } + + template + void deserialize(Des& des, T& obj, Fnc&& fnc) const + { + auto& resObj = static_cast(obj); + if (auto ctx = des.template contextOrNull()) { + ctx->beginBase(obj, resObj); + fnc(des, resObj); + ctx->end(); + } else { + fnc(des, resObj); + } + } +}; + +// requires InheritanceContext +template +class VirtualBaseClass +{ +public: + template + void serialize(Ser& ser, const T& obj, Fnc&& fnc) const + { + auto& ctx = ser.template context(); + auto& resObj = static_cast(obj); + if (ctx.beginVirtualBase(obj, resObj)) + fnc(ser, const_cast(resObj)); + ctx.end(); + } + + template + void deserialize(Des& des, T& obj, Fnc&& fnc) const + { + auto& ctx = des.template context(); + auto& resObj = static_cast(obj); + if (ctx.beginVirtualBase(obj, resObj)) + fnc(des, resObj); + ctx.end(); + } +}; + } +namespace traits { +template +struct ExtensionTraits, T> +{ + static_assert(std::is_base_of::value, "Invalid base class"); -#endif //BITSERY_EXT_INHERITANCE_H + using TValue = TBase; + static constexpr bool SupportValueOverload = false; + static constexpr bool SupportObjectOverload = true; + static constexpr bool SupportLambdaOverload = true; +}; + +template +struct ExtensionTraits, T> +{ + static_assert(std::is_base_of::value, "Invalid base class"); + + using TValue = TBase; + static constexpr bool SupportValueOverload = false; + static constexpr bool SupportObjectOverload = true; + // disable lambda overload, when serializing virtually inherited base class. + // Only one instance of virtual base will be serialized, when using multiple + // inheritance and it will be undefined behaviour if derived classes would + // have different virtual base class serialization flow. + static constexpr bool SupportLambdaOverload = false; +}; +} +} + +#endif // BITSERY_EXT_INHERITANCE_H diff --git a/include/bitsery/ext/pointer.h b/include/bitsery/ext/pointer.h index 16cd3ce..3c56244 100644 --- a/include/bitsery/ext/pointer.h +++ b/include/bitsery/ext/pointer.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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_EXT_POINTER_H #define BITSERY_EXT_POINTER_H @@ -31,190 +31,218 @@ namespace bitsery { - namespace ext { +namespace ext { - namespace pointer_details { +namespace pointer_details { - template - struct PtrOwnerManager { - static_assert(std::is_pointer::value, ""); +template +struct PtrOwnerManager +{ + static_assert(std::is_pointer::value, ""); - using TElement = typename std::remove_pointer::type; + using TElement = typename std::remove_pointer::type; - static TElement* getPtr(T& obj) { - return obj; - } + static TElement* getPtr(T& obj) { return obj; } - static constexpr PointerOwnershipType getOwnership() { - return PointerOwnershipType::Owner; - } + static constexpr PointerOwnershipType getOwnership() + { + return PointerOwnershipType::Owner; + } - static void create(T& obj, pointer_utils::PolyAllocWithTypeId alloc, size_t typeId) { - obj = alloc.newObject(typeId); - } + static void create(T& obj, + pointer_utils::PolyAllocWithTypeId alloc, + size_t typeId) + { + obj = alloc.newObject(typeId); + } - static void createPolymorphic(T& obj, pointer_utils::PolyAllocWithTypeId alloc, - const std::shared_ptr& handler) { - obj = static_cast(handler->create(alloc)); - } + static void createPolymorphic( + T& obj, + pointer_utils::PolyAllocWithTypeId alloc, + const std::shared_ptr& handler) + { + obj = static_cast(handler->create(alloc)); + } - static void destroy(T& obj, pointer_utils::PolyAllocWithTypeId alloc, size_t typeId) { - alloc.deleteObject(obj, typeId); - obj = nullptr; - } + static void destroy(T& obj, + pointer_utils::PolyAllocWithTypeId alloc, + size_t typeId) + { + alloc.deleteObject(obj, typeId); + obj = nullptr; + } - static void destroyPolymorphic(T& obj, pointer_utils::PolyAllocWithTypeId alloc, - const std::shared_ptr& handler) { - handler->destroy(alloc, obj); - obj = nullptr; - } + static void destroyPolymorphic( + T& obj, + pointer_utils::PolyAllocWithTypeId alloc, + const std::shared_ptr& handler) + { + handler->destroy(alloc, obj); + obj = nullptr; + } +}; - }; +template +struct PtrObserverManager +{ + static_assert(std::is_pointer::value, ""); - template - struct PtrObserverManager { - static_assert(std::is_pointer::value, ""); + using TElement = typename std::remove_pointer::type; - using TElement = typename std::remove_pointer::type; + static TElement* getPtr(T& obj) { return obj; } - static TElement* getPtr(T& obj) { - return obj; - } + static constexpr PointerOwnershipType getOwnership() + { + return PointerOwnershipType::Observer; + } - static constexpr PointerOwnershipType getOwnership() { - return PointerOwnershipType::Observer; - } + // pure observer doesn't have create/createPolymorphic methods, but instead + // returns reference to pointer which gets updated later + static TElement*& getPtrRef(T& obj) { return obj; } - //pure observer doesn't have create/createPolymorphic methods, but instead returns reference to pointer - //which gets updated later - static TElement*& getPtrRef(T& obj) { - return obj; - } + static void destroy(T& obj, MemResourceBase*, size_t) { obj = nullptr; } - static void destroy(T& obj, MemResourceBase* , size_t ) { - obj = nullptr; - } + static void destroyPolymorphic(T& obj, + MemResourceBase*, + PolymorphicHandlerBase&) + { + obj = nullptr; + } +}; - static void destroyPolymorphic(T& obj, MemResourceBase* , PolymorphicHandlerBase& ) { - obj = nullptr; - } +template +struct NonPtrManager +{ - }; + static_assert(!std::is_pointer::value, ""); - template - struct NonPtrManager { + using TElement = T; - static_assert(!std::is_pointer::value, ""); + static TElement* getPtr(T& obj) { return &obj; } - using TElement = T; + static constexpr PointerOwnershipType getOwnership() + { + return PointerOwnershipType::Owner; + } - static TElement* getPtr(T& obj) { - return &obj; - } + // this code is unreachable for reference type, but is necessary to compile + // LCOV_EXCL_START - static constexpr PointerOwnershipType getOwnership() { - return PointerOwnershipType::Owner; - } + static void create(T&, MemResourceBase*, size_t) {} - // this code is unreachable for reference type, but is necessary to compile - // LCOV_EXCL_START + static void createPolymorphic(T&, MemResourceBase*, PolymorphicHandlerBase&) + { + } - static void create(T& , MemResourceBase* , size_t ) { + static void destroy(T&, MemResourceBase*, size_t) {} - } + static void destroyPolymorphic(T&, MemResourceBase*, PolymorphicHandlerBase&) + { + } + // LCOV_EXCL_STOP +}; - static void createPolymorphic(T& , MemResourceBase* , PolymorphicHandlerBase& ) { +// this class is used by NonPtrManager +struct NoRTTI +{ + template + static size_t get(TBase&) + { + return 0; + } - } + template + static constexpr size_t get() + { + return 0; + } - static void destroy(T& , MemResourceBase* , size_t ) { + template + static constexpr TDerived* cast(TBase* obj) + { + static_assert(!std::is_pointer::value, ""); + return dynamic_cast(obj); + } - } - - static void destroyPolymorphic(T& , MemResourceBase* , PolymorphicHandlerBase& ) { - - } - // LCOV_EXCL_STOP - - }; - - // this class is used by NonPtrManager - struct NoRTTI { - template - static size_t get(TBase&) { - return 0; - } - - template - static constexpr size_t get() { - return 0; - } - - template - static constexpr TDerived* cast(TBase* obj) { - static_assert(!std::is_pointer::value, ""); - return dynamic_cast(obj); - } - - template - static constexpr bool isPolymorphic() { - return false; - } - }; - - } - - template - using PointerOwnerBase = pointer_utils::PointerObjectExtensionBase< - pointer_details::PtrOwnerManager, PolymorphicContext, RTTI>; - - using PointerOwner = PointerOwnerBase; - - using PointerObserver = pointer_utils::PointerObjectExtensionBase< - pointer_details::PtrObserverManager, PolymorphicContext, pointer_details::NoRTTI>; - - //inherit from PointerObjectExtensionBase in order to specify PointerType::NotNull - class ReferencedByPointer : public pointer_utils::PointerObjectExtensionBase< - pointer_details::NonPtrManager, PolymorphicContext, pointer_details::NoRTTI> { - public: - ReferencedByPointer() : pointer_utils::PointerObjectExtensionBase< - pointer_details::NonPtrManager, PolymorphicContext, pointer_details::NoRTTI>( - PointerType::NotNull) {} - }; - - } - - namespace traits { - - template - struct ExtensionTraits, T*> { - using TValue = T; - static constexpr bool SupportValueOverload = true; - static constexpr bool SupportObjectOverload = true; - //if underlying type is not polymorphic, then we can enable lambda syntax - static constexpr bool SupportLambdaOverload = !RTTI::template isPolymorphic(); - }; - - template - struct ExtensionTraits { - //although pointer observer doesn't serialize anything, but we still add value overload support to be consistent with pointer owners - //observer only writes/reads pointer id from pointer linking context - using TValue = T; - static constexpr bool SupportValueOverload = true; - static constexpr bool SupportObjectOverload = true; - static constexpr bool SupportLambdaOverload = false; - }; - - template - struct ExtensionTraits { - //allow everything, because it is serialized as regular type, except it also creates pointerId that is required by NonOwningPointer to work - using TValue = T; - static constexpr bool SupportValueOverload = true; - static constexpr bool SupportObjectOverload = true; - static constexpr bool SupportLambdaOverload = true; - }; - } + template + static constexpr bool isPolymorphic() + { + return false; + } +}; } -#endif //BITSERY_EXT_POINTER_H +template +using PointerOwnerBase = + pointer_utils::PointerObjectExtensionBase; + +using PointerOwner = PointerOwnerBase; + +using PointerObserver = + pointer_utils::PointerObjectExtensionBase; + +// inherit from PointerObjectExtensionBase in order to specify +// PointerType::NotNull +class ReferencedByPointer + : public pointer_utils::PointerObjectExtensionBase< + pointer_details::NonPtrManager, + PolymorphicContext, + pointer_details::NoRTTI> +{ +public: + ReferencedByPointer() + : pointer_utils::PointerObjectExtensionBase( + PointerType::NotNull) + { + } +}; + +} + +namespace traits { + +template +struct ExtensionTraits, T*> +{ + using TValue = T; + static constexpr bool SupportValueOverload = true; + static constexpr bool SupportObjectOverload = true; + // if underlying type is not polymorphic, then we can enable lambda syntax + static constexpr bool SupportLambdaOverload = + !RTTI::template isPolymorphic(); +}; + +template +struct ExtensionTraits +{ + // although pointer observer doesn't serialize anything, but we still add + // value overload support to be consistent with pointer owners observer only + // writes/reads pointer id from pointer linking context + using TValue = T; + static constexpr bool SupportValueOverload = true; + static constexpr bool SupportObjectOverload = true; + static constexpr bool SupportLambdaOverload = false; +}; + +template +struct ExtensionTraits +{ + // allow everything, because it is serialized as regular type, except it also + // creates pointerId that is required by NonOwningPointer to work + using TValue = T; + static constexpr bool SupportValueOverload = true; + static constexpr bool SupportObjectOverload = true; + static constexpr bool SupportLambdaOverload = true; +}; +} + +} + +#endif // BITSERY_EXT_POINTER_H diff --git a/include/bitsery/ext/std_atomic.h b/include/bitsery/ext/std_atomic.h index 1469b66..0b8f35b 100644 --- a/include/bitsery/ext/std_atomic.h +++ b/include/bitsery/ext/std_atomic.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2020 Nick Renieris +// Copyright (c) 2020 Nick Renieris // -//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: +// 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 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. +// 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_EXT_STD_ATOMIC_H #define BITSERY_EXT_STD_ATOMIC_H @@ -27,39 +27,41 @@ #include namespace bitsery { - namespace ext { +namespace ext { - class StdAtomic { - public: +class StdAtomic +{ +public: + template + void serialize(Ser& ser, const std::atomic& obj, Fnc&& fnc) const + { + auto res = obj.load(); + fnc(ser, res); + } - template - void serialize(Ser& ser, const std::atomic& obj, Fnc&& fnc) const { - auto res = obj.load(); - fnc(ser, res); - } - - template - void deserialize(Des& des, std::atomic& obj, Fnc&& fnc) const { - T res{}; - fnc(des, res); - obj.store(res); - } - }; - - } - - namespace traits { - template - struct ExtensionTraits> { - using TValue = T; - static constexpr bool SupportValueOverload = true; - static constexpr bool SupportObjectOverload = false; - static constexpr bool SupportLambdaOverload = false; - }; - - } + template + void deserialize(Des& des, std::atomic& obj, Fnc&& fnc) const + { + T res{}; + fnc(des, res); + obj.store(res); + } +}; } +namespace traits { +template +struct ExtensionTraits> +{ + using TValue = T; + static constexpr bool SupportValueOverload = true; + static constexpr bool SupportObjectOverload = false; + static constexpr bool SupportLambdaOverload = false; +}; -#endif //BITSERY_EXT_STD_ATOMIC_H +} + +} + +#endif // BITSERY_EXT_STD_ATOMIC_H diff --git a/include/bitsery/ext/std_bitset.h b/include/bitsery/ext/std_bitset.h index abd395d..ad795d8 100644 --- a/include/bitsery/ext/std_bitset.h +++ b/include/bitsery/ext/std_bitset.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2020 Mindaugas Vinkelis +// Copyright (c) 2020 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: +// 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 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. +// 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_EXT_STD_BITSET_H #define BITSERY_EXT_STD_BITSET_H @@ -27,113 +27,137 @@ #include namespace bitsery { - namespace ext { +namespace ext { - class StdBitset { - public: +class StdBitset +{ +public: + template + void serialize(Ser& ser, const std::bitset& obj, Fnc&&) const + { + constexpr size_t BYTES = N / 8; + constexpr size_t LEFTOVER = N % 8; + if (BYTES > sizeof(unsigned long long)) { + for (size_t i = 0u; i < BYTES; ++i) { + size_t offset = i * 8; + auto data = obj[offset + 0] + (obj[offset + 1] << 1) + + (obj[offset + 2] << 2) + (obj[offset + 3] << 3) + + (obj[offset + 4] << 4) + (obj[offset + 5] << 5) + + (obj[offset + 6] << 6) + (obj[offset + 7] << 7); + ser.value1b(static_cast(data)); + } - template - void serialize(Ser &ser, const std::bitset &obj, Fnc &&) const { - constexpr size_t BYTES = N / 8; - constexpr size_t LEFTOVER = N % 8; - if (BYTES > sizeof(unsigned long long)) { - for(size_t i = 0u; i < BYTES; ++i) { - size_t offset = i * 8; - auto data = obj[offset + 0] + - (obj[offset + 1] << 1) + - (obj[offset + 2] << 2) + - (obj[offset + 3] << 3) + - (obj[offset + 4] << 4) + - (obj[offset + 5] << 5) + - (obj[offset + 6] << 6) + - (obj[offset + 7] << 7); - ser.value1b(static_cast(data)); - } - - } else { - // more performant way - auto data = obj.to_ullong(); - for(size_t i = 0u; i < BYTES; ++i) { - ser.value1b(static_cast(data & 0xFF)); - data >>= 8; - } - } - if (LEFTOVER > 0) { - serializeLeftoverImpl(ser.adapter(), obj, N - LEFTOVER, N, std::is_same{}); - } - } - - template - void deserialize(Des &des, std::bitset &obj, Fnc &&) const { - constexpr size_t BYTES = N / 8; - constexpr size_t LEFTOVER = N % 8; - for(size_t i = 0u; i < BYTES; ++i) { - size_t offset = i * 8; - uint8_t data = 0; - des.value1b(data); - obj[offset + 0] = data & 0x01u; - obj[offset + 1] = data & 0x02u; - obj[offset + 2] = data & 0x04u; - obj[offset + 3] = data & 0x08u; - obj[offset + 4] = data & 0x10u; - obj[offset + 5] = data & 0x20u; - obj[offset + 6] = data & 0x40u; - obj[offset + 7] = data & 0x80u; - } - if (LEFTOVER > 0) { - deserializeLeftoverImpl(des.adapter(), obj, N - LEFTOVER, N, std::is_same{}); - } - } - - private: - - template - void serializeLeftoverImpl(Writer& w, const std::bitset &obj, size_t from, size_t to, std::integral_constant) const { - auto data = 0; - for (auto i = from; i < to; ++i) { - data += obj[i] << (i - from); - } - w.template writeBytes<1>(static_cast(data)); - } - - template - void serializeLeftoverImpl(Writer& w, const std::bitset &obj, size_t from, size_t to, std::integral_constant) const { - for (auto i = from; i < to; ++i) { - w.writeBits(obj[i] ? 1u : 0u, 1); - } - } - - template - void deserializeLeftoverImpl(Reader& r, std::bitset &obj, size_t from, size_t to, std::integral_constant) const { - uint8_t data = 0u; - r.template readBytes<1>(data); - for (auto i = from; i < to; ++i) { - obj[i] = data & (1u << (i - from)); - } - } - - template - void deserializeLeftoverImpl(Reader& r, std::bitset &obj, size_t from, size_t to, std::integral_constant) const { - for (auto i = from; i < to; ++i) { - uint8_t res = 0u; - r.readBits(res, 1); - obj[i] = res == 1; - } - } - - }; + } else { + // more performant way + auto data = obj.to_ullong(); + for (size_t i = 0u; i < BYTES; ++i) { + ser.value1b(static_cast(data & 0xFF)); + data >>= 8; + } } - - namespace traits { - template - struct ExtensionTraits> { - using TValue = void; - static constexpr bool SupportValueOverload = false; - static constexpr bool SupportObjectOverload = true; - static constexpr bool SupportLambdaOverload = false; - }; + if (LEFTOVER > 0) { + serializeLeftoverImpl(ser.adapter(), + obj, + N - LEFTOVER, + N, + std::is_same{}); } + } + + template + void deserialize(Des& des, std::bitset& obj, Fnc&&) const + { + constexpr size_t BYTES = N / 8; + constexpr size_t LEFTOVER = N % 8; + for (size_t i = 0u; i < BYTES; ++i) { + size_t offset = i * 8; + uint8_t data = 0; + des.value1b(data); + obj[offset + 0] = data & 0x01u; + obj[offset + 1] = data & 0x02u; + obj[offset + 2] = data & 0x04u; + obj[offset + 3] = data & 0x08u; + obj[offset + 4] = data & 0x10u; + obj[offset + 5] = data & 0x20u; + obj[offset + 6] = data & 0x40u; + obj[offset + 7] = data & 0x80u; + } + if (LEFTOVER > 0) { + deserializeLeftoverImpl(des.adapter(), + obj, + N - LEFTOVER, + N, + std::is_same{}); + } + } + +private: + template + void serializeLeftoverImpl(Writer& w, + const std::bitset& obj, + size_t from, + size_t to, + std::integral_constant) const + { + auto data = 0; + for (auto i = from; i < to; ++i) { + data += obj[i] << (i - from); + } + w.template writeBytes<1>(static_cast(data)); + } + + template + void serializeLeftoverImpl(Writer& w, + const std::bitset& obj, + size_t from, + size_t to, + std::integral_constant) const + { + for (auto i = from; i < to; ++i) { + w.writeBits(obj[i] ? 1u : 0u, 1); + } + } + + template + void deserializeLeftoverImpl(Reader& r, + std::bitset& obj, + size_t from, + size_t to, + std::integral_constant) const + { + uint8_t data = 0u; + r.template readBytes<1>(data); + for (auto i = from; i < to; ++i) { + obj[i] = data & (1u << (i - from)); + } + } + + template + void deserializeLeftoverImpl(Reader& r, + std::bitset& obj, + size_t from, + size_t to, + std::integral_constant) const + { + for (auto i = from; i < to; ++i) { + uint8_t res = 0u; + r.readBits(res, 1); + obj[i] = res == 1; + } + } +}; } +namespace traits { +template +struct ExtensionTraits> +{ + using TValue = void; + static constexpr bool SupportValueOverload = false; + static constexpr bool SupportObjectOverload = true; + static constexpr bool SupportLambdaOverload = false; +}; +} +} -#endif //BITSERY_EXT_STD_BITSET_H +#endif // BITSERY_EXT_STD_BITSET_H diff --git a/include/bitsery/ext/std_chrono.h b/include/bitsery/ext/std_chrono.h index 4884b0a..6f09694 100644 --- a/include/bitsery/ext/std_chrono.h +++ b/include/bitsery/ext/std_chrono.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. +// 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_EXT_STD_CHRONO_H #define BITSERY_EXT_STD_CHRONO_H @@ -27,68 +27,91 @@ #include namespace bitsery { - namespace ext { +namespace ext { - class StdDuration { - public: +class StdDuration +{ +public: + template + void serialize(Ser& ser, + const std::chrono::duration& obj, + Fnc&& fnc) const + { + auto res = obj.count(); + fnc(ser, res); + } - template - void serialize(Ser& ser, const std::chrono::duration& obj, Fnc&& fnc) const { - auto res = obj.count(); - fnc(ser, res); - } + template + void deserialize(Des& des, + std::chrono::duration& obj, + Fnc&& fnc) const + { + T res{}; + fnc(des, res); + obj = std::chrono::duration{ res }; + } +}; - template - void deserialize(Des& des, std::chrono::duration& obj, Fnc&& fnc) const { - T res{}; - fnc(des, res); - obj = std::chrono::duration{res}; - } - }; +class StdTimePoint +{ +public: + template + void serialize( + Ser& ser, + const std::chrono::time_point>& obj, + Fnc&& fnc) const + { + auto res = obj.time_since_epoch().count(); + fnc(ser, res); + } - class StdTimePoint { - public: - - template - void serialize(Ser& ser, const std::chrono::time_point>& obj, - Fnc&& fnc) const { - auto res = obj.time_since_epoch().count(); - fnc(ser, res); - } - - template - void deserialize(Des& des, std::chrono::time_point>& obj, - Fnc&& fnc) const { - T res{}; - fnc(des, res); - auto dur = std::chrono::duration{res}; - obj = std::chrono::time_point>{dur}; - } - }; - - } - - namespace traits { - template - struct ExtensionTraits> { - using TValue = Rep; - static constexpr bool SupportValueOverload = true; - static constexpr bool SupportObjectOverload = false; - static constexpr bool SupportLambdaOverload = false; - }; - - template - struct ExtensionTraits>> { - using TValue = Rep; - static constexpr bool SupportValueOverload = true; - static constexpr bool SupportObjectOverload = false; - static constexpr bool SupportLambdaOverload = false; - }; - - } + template + void deserialize( + Des& des, + std::chrono::time_point>& obj, + Fnc&& fnc) const + { + T res{}; + fnc(des, res); + auto dur = std::chrono::duration{ res }; + obj = + std::chrono::time_point>{ dur }; + } +}; } +namespace traits { +template +struct ExtensionTraits> +{ + using TValue = Rep; + static constexpr bool SupportValueOverload = true; + static constexpr bool SupportObjectOverload = false; + static constexpr bool SupportLambdaOverload = false; +}; -#endif //BITSERY_EXT_STD_CHRONO_H +template +struct ExtensionTraits< + ext::StdTimePoint, + std::chrono::time_point>> +{ + using TValue = Rep; + static constexpr bool SupportValueOverload = true; + static constexpr bool SupportObjectOverload = false; + static constexpr bool SupportLambdaOverload = false; +}; + +} + +} + +#endif // BITSERY_EXT_STD_CHRONO_H diff --git a/include/bitsery/ext/std_map.h b/include/bitsery/ext/std_map.h index 702b6a9..2e44a33 100644 --- a/include/bitsery/ext/std_map.h +++ b/include/bitsery/ext/std_map.h @@ -1,100 +1,122 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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_EXT_STD_MAP_H #define BITSERY_EXT_STD_MAP_H -#include "../traits/core/traits.h" #include "../details/serialization_common.h" -//we need this, so we could reserve for non ordered map +#include "../traits/core/traits.h" +// we need this, so we could reserve for non ordered map #include namespace bitsery { - namespace ext { +namespace ext { - class StdMap { - public: +class StdMap +{ +public: + constexpr explicit StdMap(size_t maxSize) + : _maxSize{ maxSize } + { + } - constexpr explicit StdMap(size_t maxSize):_maxSize{maxSize} {} + template + void serialize(Ser& ser, const T& obj, Fnc&& fnc) const + { + using TKey = typename T::key_type; + using TValue = typename T::mapped_type; + auto size = obj.size(); + assert(size <= _maxSize); + details::writeSize(ser.adapter(), size); - template - void serialize(Ser &ser, const T &obj, Fnc &&fnc) const { - using TKey = typename T::key_type; - using TValue = typename T::mapped_type; - auto size = obj.size(); - assert(size <= _maxSize); - details::writeSize(ser.adapter(), size); + for (auto& v : obj) + fnc(ser, const_cast(v.first), const_cast(v.second)); + } - for (auto &v:obj) - fnc(ser, const_cast(v.first), const_cast(v.second)); - } + template + void deserialize(Des& des, T& obj, Fnc&& fnc) const + { + using TKey = typename T::key_type; + using TValue = typename T::mapped_type; - template - void deserialize(Des &des, T &obj, Fnc &&fnc) const { - using TKey = typename T::key_type; - using TValue = typename T::mapped_type; + size_t size{}; + details::readSize( + des.adapter(), + size, + _maxSize, + std::integral_constant{}); + obj.clear(); + reserve(obj, size); - size_t size{}; - details::readSize(des.adapter(), size, _maxSize, - std::integral_constant{}); - obj.clear(); - reserve(obj, size); - - auto hint = obj.begin(); - for (auto i = 0u; i < size; ++i) { - auto key = bitsery::Access::create(); - auto value = bitsery::Access::create(); - fnc(des, key, value); - hint = obj.emplace_hint(hint, std::move(key), std::move(value)); - } - } - private: - template - void reserve(std::unordered_map& obj, size_t size) const { - obj.reserve(size); - } - template - void reserve(std::unordered_multimap& obj, size_t size) const { - obj.reserve(size); - } - template - void reserve(T& , size_t ) const { - //for ordered container do nothing - } - size_t _maxSize; - }; + auto hint = obj.begin(); + for (auto i = 0u; i < size; ++i) { + auto key = bitsery::Access::create(); + auto value = bitsery::Access::create(); + fnc(des, key, value); + hint = obj.emplace_hint(hint, std::move(key), std::move(value)); } + } - namespace traits { - template - struct ExtensionTraits { - using TValue = void; - static constexpr bool SupportValueOverload = false; - static constexpr bool SupportObjectOverload = false; - static constexpr bool SupportLambdaOverload = true; - }; - } +private: + template + void reserve(std::unordered_map& obj, + size_t size) const + { + obj.reserve(size); + } + template + void reserve(std::unordered_multimap& obj, + size_t size) const + { + obj.reserve(size); + } + template + void reserve(T&, size_t) const + { + // for ordered container do nothing + } + size_t _maxSize; +}; +} + +namespace traits { +template +struct ExtensionTraits +{ + using TValue = void; + static constexpr bool SupportValueOverload = false; + static constexpr bool SupportObjectOverload = false; + static constexpr bool SupportLambdaOverload = true; +}; +} } - -#endif //BITSERY_EXT_STD_MAP_H +#endif // BITSERY_EXT_STD_MAP_H diff --git a/include/bitsery/ext/std_optional.h b/include/bitsery/ext/std_optional.h index 57ec9d1..b58f086 100644 --- a/include/bitsery/ext/std_optional.h +++ b/include/bitsery/ext/std_optional.h @@ -1,96 +1,109 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_EXT_STD_OPTIONAL_H #define BITSERY_EXT_STD_OPTIONAL_H -#include "../traits/core/traits.h" #include "../details/serialization_common.h" +#include "../traits/core/traits.h" #include namespace bitsery { - namespace ext { +namespace ext { - class StdOptional { - public: +class StdOptional +{ +public: + /** + * Works with std::optional types + * @param alignBeforeData only makes sense when bit-packing enabled, by + * default aligns after writing/reading bool state of optional + */ + explicit StdOptional(bool alignBeforeData = true) + : _alignBeforeData{ alignBeforeData } + { + } - /** - * Works with std::optional types - * @param alignBeforeData only makes sense when bit-packing enabled, by default aligns after writing/reading bool state of optional - */ - explicit StdOptional(bool alignBeforeData=true):_alignBeforeData{alignBeforeData} {} + template + void serialize(Ser& ser, const std::optional& obj, Fnc&& fnc) const + { + ser.boolValue(static_cast(obj)); + if (_alignBeforeData) + ser.adapter().align(); + if (obj) + fnc(ser, const_cast(*obj)); + } - template - void serialize(Ser &ser, const std::optional &obj, Fnc &&fnc) const { - ser.boolValue(static_cast(obj)); - if (_alignBeforeData) - ser.adapter().align(); - if (obj) - fnc(ser, const_cast(*obj)); - } - - template - void deserialize(Des &des, std::optional &obj, Fnc &&fnc) const { - bool exists{}; - des.boolValue(exists); - if (_alignBeforeData) - des.adapter().align(); - if (exists) { - deserialize_impl(des, obj, fnc, std::is_trivial{}); - } else { - obj = std::nullopt; - } - } - private: - - template - void deserialize_impl(Des &des, std::optional &obj, Fnc &&fnc, std::true_type) const { - obj = ::bitsery::Access::create(); - fnc(des, *obj); - } - - template - void deserialize_impl(Des &des, std::optional &obj, Fnc &&fnc, std::false_type) const { - if (!obj) { - obj = ::bitsery::Access::create(); - } - fnc(des, *obj); - } - bool _alignBeforeData; - }; + template + void deserialize(Des& des, std::optional& obj, Fnc&& fnc) const + { + bool exists{}; + des.boolValue(exists); + if (_alignBeforeData) + des.adapter().align(); + if (exists) { + deserialize_impl(des, obj, fnc, std::is_trivial{}); + } else { + obj = std::nullopt; } + } - namespace traits { - template - struct ExtensionTraits> { - using TValue = T; - static constexpr bool SupportValueOverload = true; - static constexpr bool SupportObjectOverload = true; - static constexpr bool SupportLambdaOverload = true; - }; +private: + template + void deserialize_impl(Des& des, + std::optional& obj, + Fnc&& fnc, + std::true_type) const + { + obj = ::bitsery::Access::create(); + fnc(des, *obj); + } + + template + void deserialize_impl(Des& des, + std::optional& obj, + Fnc&& fnc, + std::false_type) const + { + if (!obj) { + obj = ::bitsery::Access::create(); } + fnc(des, *obj); + } + bool _alignBeforeData; +}; +} + +namespace traits { +template +struct ExtensionTraits> +{ + using TValue = T; + static constexpr bool SupportValueOverload = true; + static constexpr bool SupportObjectOverload = true; + static constexpr bool SupportLambdaOverload = true; +}; +} } - -#endif //BITSERY_EXT_STD_OPTIONAL_H +#endif // BITSERY_EXT_STD_OPTIONAL_H diff --git a/include/bitsery/ext/std_queue.h b/include/bitsery/ext/std_queue.h index 08d39f4..c084a5b 100644 --- a/include/bitsery/ext/std_queue.h +++ b/include/bitsery/ext/std_queue.h @@ -1,111 +1,127 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_EXT_STD_QUEUE_H #define BITSERY_EXT_STD_QUEUE_H -//include type traits for deque and vector, because they are defaults for queue and priority_queue +// include type traits for deque and vector, because they are defaults for queue +// and priority_queue #include "../traits/deque.h" #include "../traits/vector.h" -#include #include +#include namespace bitsery { - namespace ext { +namespace ext { - class StdQueue { - private: - //inherit from queue so we could take underlying container - template - struct QueueCnt : public std::queue - { - static const C& getContainer(const std::queue& s ) - { - //get address of underlying container - return s.*(&QueueCnt::c); - } - static C& getContainer(std::queue& s ) - { - //get address of underlying container - return s.*(&QueueCnt::c); - } - }; - //inherit from queue so we could take underlying container - template - struct PriorityQueueCnt : public std::priority_queue - { - static const Seq& getContainer(const std::priority_queue& s ) - { - //get address of underlying container - return s.*(&PriorityQueueCnt::c); - } - static Seq& getContainer(std::priority_queue& s ) - { - //get address of underlying container - return s.*(&PriorityQueueCnt::c); - } - }; - - size_t _maxSize; - public: - explicit StdQueue(size_t maxSize):_maxSize{maxSize} {}; - - //for queue - template - void serialize(Ser &ser, const std::queue &obj, Fnc &&fnc) const { - ser.container(QueueCnt::getContainer(obj), _maxSize, std::forward(fnc)); - } - - template - void deserialize(Des &des, std::queue &obj, Fnc &&fnc) const { - des.container(QueueCnt::getContainer(obj), _maxSize, std::forward(fnc)); - } - - //for priority_queue - template - void serialize(Ser &ser, const std::priority_queue &obj, Fnc &&fnc) const { - ser.container(PriorityQueueCnt::getContainer(obj), _maxSize, std::forward(fnc)); - } - - template - void deserialize(Des &des, std::priority_queue &obj, Fnc &&fnc) const { - des.container(PriorityQueueCnt::getContainer(obj), _maxSize, std::forward(fnc)); - } - - }; +class StdQueue +{ +private: + // inherit from queue so we could take underlying container + template + struct QueueCnt : public std::queue + { + static const C& getContainer(const std::queue& s) + { + // get address of underlying container + return s.*(&QueueCnt::c); } - - namespace traits { - template - struct ExtensionTraits { - using TValue = typename T::value_type; - static constexpr bool SupportValueOverload = true; - static constexpr bool SupportObjectOverload = true; - static constexpr bool SupportLambdaOverload = true; - }; + static C& getContainer(std::queue& s) + { + // get address of underlying container + return s.*(&QueueCnt::c); } + }; + // inherit from queue so we could take underlying container + template + struct PriorityQueueCnt : public std::priority_queue + { + static const Seq& getContainer(const std::priority_queue& s) + { + // get address of underlying container + return s.*(&PriorityQueueCnt::c); + } + static Seq& getContainer(std::priority_queue& s) + { + // get address of underlying container + return s.*(&PriorityQueueCnt::c); + } + }; + + size_t _maxSize; + +public: + explicit StdQueue(size_t maxSize) + : _maxSize{ maxSize } {}; + + // for queue + template + void serialize(Ser& ser, const std::queue& obj, Fnc&& fnc) const + { + ser.container( + QueueCnt::getContainer(obj), _maxSize, std::forward(fnc)); + } + + template + void deserialize(Des& des, std::queue& obj, Fnc&& fnc) const + { + des.container( + QueueCnt::getContainer(obj), _maxSize, std::forward(fnc)); + } + + // for priority_queue + template + void serialize(Ser& ser, + const std::priority_queue& obj, + Fnc&& fnc) const + { + ser.container(PriorityQueueCnt::getContainer(obj), + _maxSize, + std::forward(fnc)); + } + + template + void deserialize(Des& des, + std::priority_queue& obj, + Fnc&& fnc) const + { + des.container(PriorityQueueCnt::getContainer(obj), + _maxSize, + std::forward(fnc)); + } +}; +} + +namespace traits { +template +struct ExtensionTraits +{ + using TValue = typename T::value_type; + static constexpr bool SupportValueOverload = true; + static constexpr bool SupportObjectOverload = true; + static constexpr bool SupportLambdaOverload = true; +}; +} } - -#endif //BITSERY_EXT_STD_QUEUE_H +#endif // BITSERY_EXT_STD_QUEUE_H diff --git a/include/bitsery/ext/std_set.h b/include/bitsery/ext/std_set.h index 607ecce..2926d4d 100644 --- a/include/bitsery/ext/std_set.h +++ b/include/bitsery/ext/std_set.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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_EXT_STD_SET_H #define BITSERY_EXT_STD_SET_H @@ -27,71 +27,83 @@ #include namespace bitsery { - namespace ext { +namespace ext { - class StdSet { - public: +class StdSet +{ +public: + constexpr explicit StdSet(size_t maxSize) + : _maxSize{ maxSize } + { + } - constexpr explicit StdSet(size_t maxSize):_maxSize{maxSize} {} + template + void serialize(Ser& ser, const T& obj, Fnc&& fnc) const + { + using TKey = typename T::key_type; + auto size = obj.size(); + assert(size <= _maxSize); + details::writeSize(ser.adapter(), size); - template - void serialize(Ser &ser, const T &obj, Fnc &&fnc) const { - using TKey = typename T::key_type; - auto size = obj.size(); - assert(size <= _maxSize); - details::writeSize(ser.adapter(), size); + for (auto& v : obj) + fnc(ser, const_cast(v)); + } - for (auto &v:obj) - fnc(ser, const_cast(v)); - } + template + void deserialize(Des& des, T& obj, Fnc&& fnc) const + { + using TKey = typename T::key_type; - template - void deserialize(Des &des, T &obj, Fnc &&fnc) const { - using TKey = typename T::key_type; - - size_t size{}; - details::readSize(des.adapter(), size, _maxSize, std::integral_constant{}); - obj.clear(); - reserve(obj, size); - auto hint = obj.begin(); - for (auto i = 0u; i < size; ++i) { - auto key = bitsery::Access::create(); - fnc(des, key); - hint = obj.emplace_hint(hint, std::move(key)); - } - } - private: - - template - void reserve(std::unordered_set& obj, size_t size) const { - obj.reserve(size); - } - template - void reserve(std::unordered_multiset& obj, size_t size) const { - obj.reserve(size); - } - - - - template - void reserve(T& , size_t ) const { - //for ordered container do nothing - } - size_t _maxSize; - }; + size_t size{}; + details::readSize( + des.adapter(), + size, + _maxSize, + std::integral_constant{}); + obj.clear(); + reserve(obj, size); + auto hint = obj.begin(); + for (auto i = 0u; i < size; ++i) { + auto key = bitsery::Access::create(); + fnc(des, key); + hint = obj.emplace_hint(hint, std::move(key)); } + } - namespace traits { - template - struct ExtensionTraits { - using TValue = typename T::key_type; - static constexpr bool SupportValueOverload = true; - static constexpr bool SupportObjectOverload = true; - static constexpr bool SupportLambdaOverload = true; - }; - } +private: + template + void reserve(std::unordered_set& obj, + size_t size) const + { + obj.reserve(size); + } + template + void reserve(std::unordered_multiset& obj, + size_t size) const + { + obj.reserve(size); + } + + template + void reserve(T&, size_t) const + { + // for ordered container do nothing + } + size_t _maxSize; +}; +} + +namespace traits { +template +struct ExtensionTraits +{ + using TValue = typename T::key_type; + static constexpr bool SupportValueOverload = true; + static constexpr bool SupportObjectOverload = true; + static constexpr bool SupportLambdaOverload = true; +}; +} } - -#endif //BITSERY_EXT_STD_SET_H +#endif // BITSERY_EXT_STD_SET_H diff --git a/include/bitsery/ext/std_smart_ptr.h b/include/bitsery/ext/std_smart_ptr.h index 85872d8..c555fba 100644 --- a/include/bitsery/ext/std_smart_ptr.h +++ b/include/bitsery/ext/std_smart_ptr.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2018 Mindaugas Vinkelis +// Copyright (c) 2018 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: +// 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 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. +// 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_EXT_STD_SMART_PTR_H #define BITSERY_EXT_STD_SMART_PTR_H @@ -30,168 +30,209 @@ #include namespace bitsery { - namespace ext { +namespace ext { - namespace smart_ptr_details { +namespace smart_ptr_details { - //further code is for managing shared ownership - //do not nest this type in pointer manager class itself, because it will be different type for different T - struct SharedPtrSharedState : pointer_utils::PointerSharedStateBase { - std::shared_ptr obj{}; - }; +// further code is for managing shared ownership +// do not nest this type in pointer manager class itself, because it will be +// different type for different T +struct SharedPtrSharedState : pointer_utils::PointerSharedStateBase +{ + std::shared_ptr obj{}; +}; - template - struct SmartPtrOwnerManager { +template +struct SmartPtrOwnerManager +{ - using TElement = typename T::element_type; + using TElement = typename T::element_type; - template - static TElement* getPtr(std::unique_ptr& obj) { - return obj.get(); - } + template + static TElement* getPtr(std::unique_ptr& obj) + { + return obj.get(); + } - static TElement* getPtr(std::shared_ptr& obj) { - return obj.get(); - } + static TElement* getPtr(std::shared_ptr& obj) { return obj.get(); } - static TElement* getPtr(std::weak_ptr& obj) { - if (auto ptr = obj.lock()) - return ptr.get(); - return nullptr; - } + static TElement* getPtr(std::weak_ptr& obj) + { + if (auto ptr = obj.lock()) + return ptr.get(); + return nullptr; + } - static constexpr PointerOwnershipType getOwnership() { - return ::bitsery::details::IsSpecializationOf::value - ? PointerOwnershipType::Owner - : std::is_same, T>::value - ? PointerOwnershipType::SharedOwner - : PointerOwnershipType::SharedObserver; - } + static constexpr PointerOwnershipType getOwnership() + { + return ::bitsery::details::IsSpecializationOf::value + ? PointerOwnershipType::Owner + : std::is_same, T>::value + ? PointerOwnershipType::SharedOwner + : PointerOwnershipType::SharedObserver; + } - template - static void create(std::unique_ptr& obj, pointer_utils::PolyAllocWithTypeId alloc, - size_t typeId) { - obj.reset(alloc.newObject(typeId)); - } + template + static void create(std::unique_ptr& obj, + pointer_utils::PolyAllocWithTypeId alloc, + size_t typeId) + { + obj.reset(alloc.newObject(typeId)); + } - template - static void createPolymorphic(std::unique_ptr& obj, pointer_utils::PolyAllocWithTypeId alloc, - const std::shared_ptr& handler) { - obj.reset(static_cast(handler->create(alloc))); - } + template + static void createPolymorphic( + std::unique_ptr& obj, + pointer_utils::PolyAllocWithTypeId alloc, + const std::shared_ptr& handler) + { + obj.reset(static_cast(handler->create(alloc))); + } - template - static void destroy(std::unique_ptr& obj, pointer_utils::PolyAllocWithTypeId alloc, size_t typeId) { - auto ptr = obj.release(); - alloc.deleteObject(ptr, typeId); - } + template + static void destroy(std::unique_ptr& obj, + pointer_utils::PolyAllocWithTypeId alloc, + size_t typeId) + { + auto ptr = obj.release(); + alloc.deleteObject(ptr, typeId); + } - template - static void destroyPolymorphic(std::unique_ptr& obj, pointer_utils::PolyAllocWithTypeId alloc, - const std::shared_ptr& handler) { - auto ptr = obj.release(); - handler->destroy(alloc, ptr); - } + template + static void destroyPolymorphic( + std::unique_ptr& obj, + pointer_utils::PolyAllocWithTypeId alloc, + const std::shared_ptr& handler) + { + auto ptr = obj.release(); + handler->destroy(alloc, ptr); + } - static void destroy(std::shared_ptr& obj, MemResourceBase*, size_t) { - obj.reset(); - } + static void destroy(std::shared_ptr& obj, MemResourceBase*, size_t) + { + obj.reset(); + } - static void destroyPolymorphic(std::shared_ptr& obj, MemResourceBase*, - const std::shared_ptr&) { - obj.reset(); - } + static void destroyPolymorphic(std::shared_ptr& obj, + MemResourceBase*, + const std::shared_ptr&) + { + obj.reset(); + } - static void destroy(std::weak_ptr& obj, MemResourceBase*, size_t) { - obj.reset(); - } + static void destroy(std::weak_ptr& obj, MemResourceBase*, size_t) + { + obj.reset(); + } - static void destroyPolymorphic(std::weak_ptr& obj, MemResourceBase*, - const std::shared_ptr&) { - obj.reset(); - } + static void destroyPolymorphic(std::weak_ptr& obj, + MemResourceBase*, + const std::shared_ptr&) + { + obj.reset(); + } - // define a type that will store shared state for shared and weak ptrs - using TSharedState = SharedPtrSharedState; + // define a type that will store shared state for shared and weak ptrs + using TSharedState = SharedPtrSharedState; - static void createShared(TSharedState& state, - std::shared_ptr& obj, MemResourceBase* memResource, size_t typeId) { - // capture deleter parameters by value - pointer_utils::PolyAllocWithTypeId alloc{memResource}; - obj.reset(alloc.newObject(typeId), [alloc, typeId](TElement* data) { - alloc.deleteObject(data, typeId); - }, pointer_utils::StdPolyAlloc(memResource)); - state.obj = obj; - } + static void createShared(TSharedState& state, + std::shared_ptr& obj, + MemResourceBase* memResource, + size_t typeId) + { + // capture deleter parameters by value + pointer_utils::PolyAllocWithTypeId alloc{ memResource }; + obj.reset( + alloc.newObject(typeId), + [alloc, typeId](TElement* data) { alloc.deleteObject(data, typeId); }, + pointer_utils::StdPolyAlloc(memResource)); + state.obj = obj; + } - static void createSharedPolymorphic(TSharedState& state, - std::shared_ptr& obj, MemResourceBase* memResource, - const std::shared_ptr& handler) { - // capture deleter parameters by value - pointer_utils::PolyAllocWithTypeId alloc{memResource}; - obj.reset(static_cast(handler->create(alloc)), [alloc, handler](TElement* data) { - handler->destroy(alloc, data); - }, pointer_utils::StdPolyAlloc(memResource)); - state.obj = obj; - } + static void createSharedPolymorphic( + TSharedState& state, + std::shared_ptr& obj, + MemResourceBase* memResource, + const std::shared_ptr& handler) + { + // capture deleter parameters by value + pointer_utils::PolyAllocWithTypeId alloc{ memResource }; + obj.reset( + static_cast(handler->create(alloc)), + [alloc, handler](TElement* data) { handler->destroy(alloc, data); }, + pointer_utils::StdPolyAlloc(memResource)); + state.obj = obj; + } - static void createShared(TSharedState& state, - std::weak_ptr& obj, MemResourceBase* memResource, size_t typeId) { - pointer_utils::PolyAllocWithTypeId alloc{memResource}; - std::shared_ptr res(alloc.newObject(typeId),[alloc, typeId](TElement* data) { - alloc.deleteObject(data, typeId); - }, pointer_utils::StdPolyAlloc(memResource)); - obj = res; - state.obj = res; - } + static void createShared(TSharedState& state, + std::weak_ptr& obj, + MemResourceBase* memResource, + size_t typeId) + { + pointer_utils::PolyAllocWithTypeId alloc{ memResource }; + std::shared_ptr res( + alloc.newObject(typeId), + [alloc, typeId](TElement* data) { alloc.deleteObject(data, typeId); }, + pointer_utils::StdPolyAlloc(memResource)); + obj = res; + state.obj = res; + } - static void createSharedPolymorphic(TSharedState& state, - std::weak_ptr& obj, MemResourceBase* memResource, - const std::shared_ptr& handler) { - pointer_utils::PolyAllocWithTypeId alloc{memResource}; - std::shared_ptr res(static_cast(handler->create(alloc)), - [alloc, handler](TElement* data) { - handler->destroy(alloc, data); - }, pointer_utils::StdPolyAlloc(memResource)); - obj = res; - state.obj = res; - } + static void createSharedPolymorphic( + TSharedState& state, + std::weak_ptr& obj, + MemResourceBase* memResource, + const std::shared_ptr& handler) + { + pointer_utils::PolyAllocWithTypeId alloc{ memResource }; + std::shared_ptr res( + static_cast(handler->create(alloc)), + [alloc, handler](TElement* data) { handler->destroy(alloc, data); }, + pointer_utils::StdPolyAlloc(memResource)); + obj = res; + state.obj = res; + } - static void saveToSharedState(TSharedState& state, T& obj) { - state.obj = std::shared_ptr(obj); - } + static void saveToSharedState(TSharedState& state, T& obj) + { + state.obj = std::shared_ptr(obj); + } - static void loadFromSharedState(TSharedState& state, T& obj) { - //reinterpret_pointer_cast is only since c++17 - auto p = reinterpret_cast(state.obj.get()); - obj = std::shared_ptr(state.obj, p); - } + static void loadFromSharedState(TSharedState& state, T& obj) + { + // reinterpret_pointer_cast is only since c++17 + auto p = reinterpret_cast(state.obj.get()); + obj = std::shared_ptr(state.obj, p); + } +}; +} - }; - } +template +using StdSmartPtrBase = pointer_utils::PointerObjectExtensionBase< + smart_ptr_details::SmartPtrOwnerManager, + PolymorphicContext, + RTTI>; - template - using StdSmartPtrBase = pointer_utils::PointerObjectExtensionBase< - smart_ptr_details::SmartPtrOwnerManager, PolymorphicContext, RTTI>; - - //helper type for convienience - using StdSmartPtr = StdSmartPtrBase; - - } - - namespace traits { - - template - struct ExtensionTraits, T> { - using TValue = typename T::element_type; - static constexpr bool SupportValueOverload = true; - static constexpr bool SupportObjectOverload = true; - //if underlying type is not polymorphic, then we can enable lambda syntax - static constexpr bool SupportLambdaOverload = !RTTI::template isPolymorphic(); - }; - - } +// helper type for convienience +using StdSmartPtr = StdSmartPtrBase; } -#endif //BITSERY_EXT_STD_SMART_PTR_H +namespace traits { + +template +struct ExtensionTraits, T> +{ + using TValue = typename T::element_type; + static constexpr bool SupportValueOverload = true; + static constexpr bool SupportObjectOverload = true; + // if underlying type is not polymorphic, then we can enable lambda syntax + static constexpr bool SupportLambdaOverload = + !RTTI::template isPolymorphic(); +}; + +} + +} + +#endif // BITSERY_EXT_STD_SMART_PTR_H diff --git a/include/bitsery/ext/std_stack.h b/include/bitsery/ext/std_stack.h index 4998a7f..2487e5b 100644 --- a/include/bitsery/ext/std_stack.h +++ b/include/bitsery/ext/std_stack.h @@ -1,25 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_EXT_STD_STACK_H #define BITSERY_EXT_STD_STACK_H @@ -28,53 +27,59 @@ #include namespace bitsery { - namespace ext { +namespace ext { - class StdStack { - private: - //inherit from stack so we could take underlying container - template - struct StackCnt : public std::stack - { - static const C& getContainer(const std::stack& s ) - { - //get address of underlying container - return s.*(&StackCnt::c); - } - static C& getContainer(std::stack& s ) - { - //get address of underlying container - return s.*(&StackCnt::c); - } - }; - size_t _maxSize; - public: - explicit StdStack(size_t maxSize):_maxSize{maxSize} {}; - - template - void serialize(Ser &ser, const std::stack &obj, Fnc &&fnc) const { - ser.container(StackCnt::getContainer(obj), _maxSize, std::forward(fnc)); - } - - template - void deserialize(Des &des, std::stack &obj, Fnc &&fnc) const { - des.container(StackCnt::getContainer(obj), _maxSize, std::forward(fnc)); - } - - }; +class StdStack +{ +private: + // inherit from stack so we could take underlying container + template + struct StackCnt : public std::stack + { + static const C& getContainer(const std::stack& s) + { + // get address of underlying container + return s.*(&StackCnt::c); } - - namespace traits { - template - struct ExtensionTraits> { - using TValue = T; - static constexpr bool SupportValueOverload = true; - static constexpr bool SupportObjectOverload = true; - static constexpr bool SupportLambdaOverload = true; - }; + static C& getContainer(std::stack& s) + { + // get address of underlying container + return s.*(&StackCnt::c); } + }; + size_t _maxSize; + +public: + explicit StdStack(size_t maxSize) + : _maxSize{ maxSize } {}; + + template + void serialize(Ser& ser, const std::stack& obj, Fnc&& fnc) const + { + ser.container( + StackCnt::getContainer(obj), _maxSize, std::forward(fnc)); + } + + template + void deserialize(Des& des, std::stack& obj, Fnc&& fnc) const + { + des.container( + StackCnt::getContainer(obj), _maxSize, std::forward(fnc)); + } +}; +} + +namespace traits { +template +struct ExtensionTraits> +{ + using TValue = T; + static constexpr bool SupportValueOverload = true; + static constexpr bool SupportObjectOverload = true; + static constexpr bool SupportLambdaOverload = true; +}; +} } - -#endif //BITSERY_EXT_STD_STACK_H +#endif // BITSERY_EXT_STD_STACK_H diff --git a/include/bitsery/ext/std_tuple.h b/include/bitsery/ext/std_tuple.h index d698243..099fddd 100644 --- a/include/bitsery/ext/std_tuple.h +++ b/include/bitsery/ext/std_tuple.h @@ -1,81 +1,83 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. - +// 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_EXT_STD_TUPLE_H #define BITSERY_EXT_STD_TUPLE_H - -#include "utils/composite_type_overloads.h" #include "../traits/core/traits.h" +#include "utils/composite_type_overloads.h" #include namespace bitsery { - namespace ext { +namespace ext { - template - class StdTuple : public details::CompositeTypeOverloadsUtils { - public: +template +class StdTuple + : public details::CompositeTypeOverloadsUtils +{ +public: + template + void serialize(Ser& ser, const std::tuple& obj, Fnc&&) const + { + serializeAll(ser, const_cast&>(obj)); + } - template - void serialize(Ser& ser, const std::tuple& obj, Fnc&&) const { - serializeAll(ser, const_cast&>(obj)); - } + template + void deserialize(Des& des, std::tuple& obj, Fnc&&) const + { + serializeAll(des, obj); + } - template - void deserialize(Des& des, std::tuple& obj, Fnc&&) const { - serializeAll(des, obj); - } +private: + template + void serializeAll(S& s, std::tuple& obj) const + { + this->execAll(obj, [this, &s](auto& data, auto index) { + constexpr size_t Index = decltype(index)::value; + this->serializeType(s, std::get(data)); + }); + } +}; - private: - template - void serializeAll(S& s, std::tuple& obj) const { - this->execAll(obj, [this, &s](auto& data, auto index) { - constexpr size_t Index = decltype(index)::value; - this->serializeType(s, std::get(data)); - }); - } - }; +// deduction guide +template +StdTuple(Overloads...) -> StdTuple; +} - // deduction guide - template - StdTuple(Overloads...) -> StdTuple; - } +namespace traits { - namespace traits { - - template - struct ExtensionTraits, Tuple> { - static_assert(bitsery::details::IsSpecializationOf::value, - "StdTuple only works with std::tuple"); - using TValue = void; - static constexpr bool SupportValueOverload = false; - static constexpr bool SupportObjectOverload = true; - static constexpr bool SupportLambdaOverload = false; - }; - - } +template +struct ExtensionTraits, Tuple> +{ + static_assert(bitsery::details::IsSpecializationOf::value, + "StdTuple only works with std::tuple"); + using TValue = void; + static constexpr bool SupportValueOverload = false; + static constexpr bool SupportObjectOverload = true; + static constexpr bool SupportLambdaOverload = false; +}; } +} -#endif //BITSERY_EXT_STD_TUPLE_H +#endif // BITSERY_EXT_STD_TUPLE_H diff --git a/include/bitsery/ext/std_variant.h b/include/bitsery/ext/std_variant.h index 56c0865..14c1e4e 100644 --- a/include/bitsery/ext/std_variant.h +++ b/include/bitsery/ext/std_variant.h @@ -1,102 +1,114 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. - +// 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_EXT_STD_VARIANT_H #define BITSERY_EXT_STD_VARIANT_H - -#include "utils/composite_type_overloads.h" #include "../traits/core/traits.h" +#include "utils/composite_type_overloads.h" #include namespace bitsery { - namespace ext { +namespace ext { - template - class StdVariant : public details::CompositeTypeOverloadsUtils { - public: +template +class StdVariant + : public details::CompositeTypeOverloadsUtils +{ +public: + template + void serialize(Ser& ser, const std::variant& obj, Fnc&&) const + { + auto index = obj.index(); + assert(index != std::variant_npos); + details::writeSize(ser.adapter(), index); + this->execIndex(index, + const_cast&>(obj), + [this, &ser](auto& data, auto index) { + constexpr size_t Index = decltype(index)::value; + this->serializeType(ser, std::get(data)); + }); + } - template - void serialize(Ser& ser, const std::variant& obj, Fnc&&) const { - auto index = obj.index(); - assert(index != std::variant_npos); - details::writeSize(ser.adapter(), index); - this->execIndex(index, const_cast&>(obj), [this, &ser](auto& data, auto index) { - constexpr size_t Index = decltype(index)::value; - this->serializeType(ser, std::get(data)); - }); - } + template + void deserialize(Des& des, std::variant& obj, Fnc&&) const + { + size_t index{}; + details::readSize( + des.adapter(), + index, + sizeof...(Ts), + std::integral_constant{}); + this->execIndex(index, obj, [this, &des](auto& data, auto index) { + constexpr size_t Index = decltype(index)::value; + using TElem = + typename std::variant_alternative>::type; - template - void deserialize(Des& des, std::variant& obj, Fnc&&) const { - size_t index{}; - details::readSize(des.adapter(), index, sizeof...(Ts), std::integral_constant{}); - this->execIndex(index, obj, [this, &des](auto& data, auto index) { - constexpr size_t Index = decltype(index)::value; - using TElem = typename std::variant_alternative>::type; + // Reinitializing nontrivial types may be expensive especially when they + // reference heap data, so if `data` is already holding the requested + // variant then we'll deserialize into the existing object + if constexpr (!std::is_trivial_v) { + if (auto item = std::get_if(&data)) { + this->serializeType(des, *item); + return; + } + } - // Reinitializing nontrivial types may be expensive especially when they - // reference heap data, so if `data` is already holding the requested - // variant then we'll deserialize into the existing object - if constexpr (!std::is_trivial_v) { - if (auto item = std::get_if(&data)) { - this->serializeType(des, *item); - return; - } - } + TElem item = ::bitsery::Access::create(); + this->serializeType(des, item); + data = + std::variant(std::in_place_index_t{}, std::move(item)); + }); + } +}; - TElem item = ::bitsery::Access::create(); - this->serializeType(des, item); - data = std::variant(std::in_place_index_t{}, std::move(item)); - }); - } +// deduction guide +template +StdVariant(Overloads...) -> StdVariant; +} - }; +// defines empty fuction, that handles monostate +template +void +serialize(S&, std::monostate&) +{ +} - // deduction guide - template - StdVariant(Overloads...) -> StdVariant; - } +namespace traits { - //defines empty fuction, that handles monostate - template - void serialize(S& , std::monostate&) {} - - namespace traits { - - template - struct ExtensionTraits, Variant> { - static_assert(bitsery::details::IsSpecializationOf::value, - "StdVariant only works with std::variant"); - using TValue = void; - static constexpr bool SupportValueOverload = false; - static constexpr bool SupportObjectOverload = true; - static constexpr bool SupportLambdaOverload = false; - }; - - } +template +struct ExtensionTraits, Variant> +{ + static_assert( + bitsery::details::IsSpecializationOf::value, + "StdVariant only works with std::variant"); + using TValue = void; + static constexpr bool SupportValueOverload = false; + static constexpr bool SupportObjectOverload = true; + static constexpr bool SupportLambdaOverload = false; +}; } +} -#endif //BITSERY_EXT_STD_VARIANT_H +#endif // BITSERY_EXT_STD_VARIANT_H diff --git a/include/bitsery/ext/utils/composite_type_overloads.h b/include/bitsery/ext/utils/composite_type_overloads.h index 7721e97..d61500a 100644 --- a/include/bitsery/ext/utils/composite_type_overloads.h +++ b/include/bitsery/ext/utils/composite_type_overloads.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. +// 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_EXT_COMPOSITE_TYPE_OVERLOADS_H #define BITSERY_EXT_COMPOSITE_TYPE_OVERLOADS_H @@ -29,108 +29,131 @@ #if __cplusplus < 201703L #error these utils requires c++17 // in theory, it could be implemented using C++11 -// but without class template argument deduction guides that would be very inconvenient to use -// these are very helpul for sum types (e.g. std::variant), -// but for product types (e.g. std::tuple) you can you can easily do it your self with lambda, without extension +// but without class template argument deduction guides that would be very +// inconvenient to use these are very helpul for sum types (e.g. std::variant), +// but for product types (e.g. std::tuple) you can you can easily do it your +// self with lambda, without extension #endif namespace bitsery { - namespace ext { - // might be usable, when you want to have one overload set for different composite types, - // e.g. variant, tuple and pair - template - struct CompositeTypeOverloads : Ts ... { - using Ts::operator()...; - }; +namespace ext { +// might be usable, when you want to have one overload set for different +// composite types, e.g. variant, tuple and pair +template +struct CompositeTypeOverloads : Ts... +{ + using Ts::operator()...; +}; - template - CompositeTypeOverloads(Overloads...) -> CompositeTypeOverloads; +template +CompositeTypeOverloads(Overloads...) -> CompositeTypeOverloads; - // convenient way to invoke s.value, shorter than specifying a lambda - template - struct OverloadValue { - template - void operator()(S& s, T& v) const { - s.template value(v); - } - }; +// convenient way to invoke s.value, shorter than specifying a lambda +template +struct OverloadValue +{ + template + void operator()(S& s, T& v) const + { + s.template value(v); + } +}; - // convenient way to invoke other extension using value or object overloads - // there is no reason to write OverloadExtLambda, - // because you'll need to specify lambda type, which is very inconvenient and it will be much - // easier to simple write a lambda with extension inside it, - // in order to implement it in a convenient way, i need a way to deduce only last template parameter (lambda type) - // but this is not possible with deduction guides at the moment +// convenient way to invoke other extension using value or object overloads +// there is no reason to write OverloadExtLambda, +// because you'll need to specify lambda type, which is very inconvenient and it +// will be much easier to simple write a lambda with extension inside it, in +// order to implement it in a convenient way, i need a way to deduce only last +// template parameter (lambda type) but this is not possible with deduction +// guides at the moment - template - struct OverloadExtValue : public Ext { - template - void operator()(S& s, T& v) const { - s.template ext(v, static_cast(*this)); - } - }; +template +struct OverloadExtValue : public Ext +{ + template + void operator()(S& s, T& v) const + { + s.template ext(v, static_cast(*this)); + } +}; - template - struct OverloadExtObject : public Ext { - template - void operator()(S& s, T& v) const { - s.ext(v, static_cast(*this)); - } - }; - } - - namespace details { - - template typename CompositeType, typename ...Overloads> - class CompositeTypeOverloadsUtils : public ext::CompositeTypeOverloads { - protected: - // converts run-time index to compile-time index, - // by calling lambda with std::integral_constant - template - void execIndex(size_t index, CompositeType& obj, Fnc&& fnc) const { - execIndexImpl(index, obj, std::forward(fnc), std::index_sequence_for{}); - } - - // call lambda for all indexes in composite type - template - void execAll(CompositeType& obj, Fnc&& fnc) const { - execAllImpl(obj, std::forward(fnc), std::index_sequence_for{}); - } - - // serialize a type, by using overload first - template - void serializeType(S& s, T& v) const { - // first check if overload exists, otherwise try to call serialize method - if constexpr (hasOverload()) { - std::invoke(*this, s, v); - } else { - static_assert(details::SerializeFunction::isDefined(), - "Please define overload or 'serialize' function for your type."); - s.object(v); - } - } - - private: - - template - static constexpr bool hasOverload() { - return std::is_invocable, - std::add_lvalue_reference_t, std::add_lvalue_reference_t>::value; - } - - template - void execIndexImpl(size_t index, Variant& obj, Fnc&& fnc, std::index_sequence) const { - ((index == Is ? fnc(obj, std::integral_constant{}), 0 : 0), ...); - } - - template - void execAllImpl(Variant& obj, Fnc&& fnc, std::index_sequence) const { - (fnc(obj, std::integral_constant{}), ...); - } - }; - - } +template +struct OverloadExtObject : public Ext +{ + template + void operator()(S& s, T& v) const + { + s.ext(v, static_cast(*this)); + } +}; } -#endif //BITSERY_EXT_COMPOSITE_TYPE_OVERLOADS_H +namespace details { + +template typename CompositeType, typename... Overloads> +class CompositeTypeOverloadsUtils + : public ext::CompositeTypeOverloads +{ +protected: + // converts run-time index to compile-time index, + // by calling lambda with std::integral_constant + template + void execIndex(size_t index, CompositeType& obj, Fnc&& fnc) const + { + execIndexImpl( + index, obj, std::forward(fnc), std::index_sequence_for{}); + } + + // call lambda for all indexes in composite type + template + void execAll(CompositeType& obj, Fnc&& fnc) const + { + execAllImpl(obj, std::forward(fnc), std::index_sequence_for{}); + } + + // serialize a type, by using overload first + template + void serializeType(S& s, T& v) const + { + // first check if overload exists, otherwise try to call serialize method + if constexpr (hasOverload()) { + std::invoke(*this, s, v); + } else { + static_assert( + details::SerializeFunction::isDefined(), + "Please define overload or 'serialize' function for your type."); + s.object(v); + } + } + +private: + template + static constexpr bool hasOverload() + { + return std::is_invocable, + std::add_lvalue_reference_t, + std::add_lvalue_reference_t>::value; + } + + template + void execIndexImpl(size_t index, + Variant& obj, + Fnc&& fnc, + std::index_sequence) const + { + ((index == Is ? fnc(obj, std::integral_constant{}), 0 : 0), + ...); + } + + template + void execAllImpl(Variant& obj, Fnc&& fnc, std::index_sequence) const + { + (fnc(obj, std::integral_constant{}), ...); + } +}; + +} +} + +#endif // BITSERY_EXT_COMPOSITE_TYPE_OVERLOADS_H diff --git a/include/bitsery/ext/utils/memory_resource.h b/include/bitsery/ext/utils/memory_resource.h index a49c788..c829273 100644 --- a/include/bitsery/ext/utils/memory_resource.h +++ b/include/bitsery/ext/utils/memory_resource.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2018 Mindaugas Vinkelis +// Copyright (c) 2018 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: +// 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 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. +// 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_EXT_MEMORY_RESOURCE_H #define BITSERY_EXT_MEMORY_RESOURCE_H @@ -27,145 +27,170 @@ #include namespace bitsery { - namespace ext { - // these are very similar to c++17 polymorphic allocator and memory resource classes - // but i don't want to enforce users to use c++17 if they want to use pointers - // plus this has additional information from RTTI about runtime type information, - // might be useful working with polymorphic types. - // The same memory resource is used to allocate internal data in various contexts, - // (typeId is always 0 for internal data allocation in contexts). +namespace ext { +// these are very similar to c++17 polymorphic allocator and memory resource +// classes but i don't want to enforce users to use c++17 if they want to use +// pointers plus this has additional information from RTTI about runtime type +// information, might be useful working with polymorphic types. The same memory +// resource is used to allocate internal data in various contexts, (typeId is +// always 0 for internal data allocation in contexts). - class MemResourceBase { - public: - virtual void* allocate(size_t bytes, size_t alignment, size_t typeId) = 0; +class MemResourceBase +{ +public: + virtual void* allocate(size_t bytes, size_t alignment, size_t typeId) = 0; - virtual void deallocate(void* ptr, size_t bytes, size_t alignment, size_t typeId) noexcept = 0; + virtual void deallocate(void* ptr, + size_t bytes, + size_t alignment, + size_t typeId) noexcept = 0; - virtual ~MemResourceBase() noexcept = default; - }; + virtual ~MemResourceBase() noexcept = default; +}; - // default implementation for MemResourceBase using new and delete - class MemResourceNewDelete final: public MemResourceBase { - public: - inline void* allocate(size_t bytes, size_t /*alignment*/, size_t /*typeId*/) final { - return (::operator new(bytes)); - } +// default implementation for MemResourceBase using new and delete +class MemResourceNewDelete final : public MemResourceBase +{ +public: + inline void* allocate(size_t bytes, + size_t /*alignment*/, + size_t /*typeId*/) final + { + return (::operator new(bytes)); + } - inline void - deallocate(void* ptr, size_t /*bytes*/, size_t /*alignment*/, size_t /*typeId*/) noexcept final { - (::operator delete(ptr)); - } + inline void deallocate(void* ptr, + size_t /*bytes*/, + size_t /*alignment*/, + size_t /*typeId*/) noexcept final + { + (::operator delete(ptr)); + } - ~MemResourceNewDelete() noexcept final = default; - }; + ~MemResourceNewDelete() noexcept final = default; +}; - // these classes are used internally by bitsery extensions and and pointer utils - namespace pointer_utils { - // this is helper class that stores memory resource and knows how to construct/destroy objects - // capture this by value for custom deleters, because during deserialization mem resource can be changed - class PolyAllocWithTypeId final { - public: +// these classes are used internally by bitsery extensions and and pointer utils +namespace pointer_utils { +// this is helper class that stores memory resource and knows how to +// construct/destroy objects capture this by value for custom deleters, because +// during deserialization mem resource can be changed +class PolyAllocWithTypeId final +{ +public: + constexpr PolyAllocWithTypeId(MemResourceBase* memResource = nullptr) + : _resource{ memResource } + { + } - constexpr PolyAllocWithTypeId(MemResourceBase* memResource = nullptr) - :_resource{memResource} {} + template + T* allocate(size_t n, size_t typeId) const + { + const auto bytes = sizeof(T) * n; + constexpr auto alignment = std::alignment_of::value; + void* ptr = + _resource + ? _resource->allocate(bytes, alignment, typeId) + : ext::MemResourceNewDelete{}.allocate(bytes, alignment, typeId); + return static_cast(ptr); + } - template - T* allocate(size_t n, size_t typeId) const { - const auto bytes = sizeof(T) * n; - constexpr auto alignment = std::alignment_of::value; - void* ptr = _resource - ? _resource->allocate(bytes, alignment, typeId) - : ext::MemResourceNewDelete{}.allocate(bytes, alignment, typeId); - return static_cast(ptr); - } + template + void deallocate(T* ptr, size_t n, size_t typeId) const noexcept + { + const auto bytes = sizeof(T) * n; + constexpr auto alignment = std::alignment_of::value; + _resource + ? _resource->deallocate(ptr, bytes, alignment, typeId) + : ext::MemResourceNewDelete{}.deallocate(ptr, bytes, alignment, typeId); + } - template - void deallocate(T* ptr, size_t n, size_t typeId) const noexcept { - const auto bytes = sizeof(T) * n; - constexpr auto alignment = std::alignment_of::value; - _resource - ? _resource->deallocate(ptr, bytes, alignment, typeId) - : ext::MemResourceNewDelete{}.deallocate(ptr, bytes, alignment, typeId); - } + template + T* newObject(size_t typeId) const + { + auto ptr = allocate(1, typeId); + return ::bitsery::Access::create(ptr); + } - template - T* newObject(size_t typeId) const { - auto ptr = allocate(1, typeId); - return ::bitsery::Access::create(ptr); - } + template + void deleteObject(T* obj, size_t typeId) const + { + obj->~T(); + deallocate(obj, 1, typeId); + } - template - void deleteObject(T* obj, size_t typeId) const { - obj->~T(); - deallocate(obj, 1, typeId); - } + void setMemResource(ext::MemResourceBase* resource) { _resource = resource; } - void setMemResource(ext::MemResourceBase* resource) { - _resource = resource; - } + ext::MemResourceBase* getMemResource() const { return _resource; } - ext::MemResourceBase* getMemResource() const { - return _resource; - } + bool operator==(const PolyAllocWithTypeId& rhs) const noexcept + { + return _resource == rhs._resource; + } - bool operator==(const PolyAllocWithTypeId& rhs) const noexcept { - return _resource == rhs._resource; - } + bool operator!=(const PolyAllocWithTypeId& rhs) const noexcept + { + return !(*this == rhs); + } - bool operator!=(const PolyAllocWithTypeId& rhs) const noexcept { - return !(*this == rhs); - } +private: + ext::MemResourceBase* _resource; +}; - private: - ext::MemResourceBase* _resource; - }; +// this is very similar to c++17 PolymorphicAllocator +// it just wraps our PolyAllocWithTypeId and pass 0 as typeId +// and defines core functions for c++ Allocator concept, +template +class StdPolyAlloc +{ +public: + using value_type = T; - // this is very similar to c++17 PolymorphicAllocator - // it just wraps our PolyAllocWithTypeId and pass 0 as typeId - // and defines core functions for c++ Allocator concept, - template - class StdPolyAlloc { - public: - using value_type = T; + explicit constexpr StdPolyAlloc(MemResourceBase* memResource) + : _alloc{ memResource } + { + } + explicit constexpr StdPolyAlloc(PolyAllocWithTypeId alloc) + : _alloc{ alloc } + { + } - explicit constexpr StdPolyAlloc(MemResourceBase* memResource) - :_alloc{memResource} {} - explicit constexpr StdPolyAlloc(PolyAllocWithTypeId alloc) : _alloc{alloc} {} + template + friend class StdPolyAlloc; - template - friend class StdPolyAlloc; + template + constexpr explicit StdPolyAlloc(const StdPolyAlloc& other) noexcept + : _alloc{ other._alloc } + { + } - template - constexpr explicit StdPolyAlloc(const StdPolyAlloc& other) noexcept - :_alloc{other._alloc} { - } + T* allocate(std::size_t n) { return _alloc.allocate(n, 0); } - T* allocate(std::size_t n) { - return _alloc.allocate(n, 0); - } + void deallocate(T* p, std::size_t n) noexcept + { + return _alloc.deallocate(p, n, 0); + } - void deallocate(T* p, std::size_t n) noexcept { - return _alloc.deallocate(p, n, 0); - } + template + friend bool operator==(const StdPolyAlloc& lhs, + const StdPolyAlloc& rhs) noexcept + { + return lhs._alloc == rhs._alloc; + } - template - friend bool operator==(const StdPolyAlloc& lhs, - const StdPolyAlloc& rhs) noexcept { - return lhs._alloc == rhs._alloc; - } + template + friend bool operator!=(const StdPolyAlloc& lhs, + const StdPolyAlloc& rhs) noexcept + { + return !(lhs == rhs); + } - template - friend bool operator!=(const StdPolyAlloc& lhs, - const StdPolyAlloc& rhs) noexcept { - return !(lhs == rhs); - } - - private: - PolyAllocWithTypeId _alloc; - }; - - } - } +private: + PolyAllocWithTypeId _alloc; +}; } -#endif //BITSERY_EXT_MEMORY_RESOURCE_H +} + +} +#endif // BITSERY_EXT_MEMORY_RESOURCE_H diff --git a/include/bitsery/ext/utils/pointer_utils.h b/include/bitsery/ext/utils/pointer_utils.h index 3d4048e..753223e 100644 --- a/include/bitsery/ext/utils/pointer_utils.h +++ b/include/bitsery/ext/utils/pointer_utils.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2018 Mindaugas Vinkelis +// Copyright (c) 2018 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: +// 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 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. +// 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_POINTER_UTILS_H #define BITSERY_POINTER_UTILS_H @@ -26,455 +26,600 @@ #include "polymorphism_utils.h" namespace bitsery { - namespace ext { - - //change name - enum class PointerType : uint8_t { - Nullable, - NotNull - }; - - // Observer - not responsible for pointer lifetime management. - // Owner - only ONE owner is responsible for this pointers creation/destruction - // SharedOwner, SharedObserver - MANY shared owners is responsible for pointer creation/destruction - // requires additional context to manage shared owners themselves. - // SharedOwner actually manages life time e.g. std::shared_ptr - // SharedObserver do not manage life time of the pointer, but can observe shared state .e.. std::weak_ptr - // and differently from Observer, creates new object if necessary and saves to shared state - enum class PointerOwnershipType : uint8_t { - Observer, - Owner, - SharedOwner, - SharedObserver - }; - - namespace pointer_utils { - - //this class is used to store context for shared ptr owners - struct PointerSharedStateBase { - virtual ~PointerSharedStateBase() = default; - }; - - struct PointerSharedStateDeleter { - PointerSharedStateDeleter() = default; - explicit PointerSharedStateDeleter(MemResourceBase* memResource) - :_memResource{memResource} {} - void operator()(PointerSharedStateBase* data) const { - data->~PointerSharedStateBase(); - StdPolyAlloc alloc{_memResource}; - alloc.deallocate(data, 1); - } - MemResourceBase* _memResource = nullptr; - }; - - //PLC info is internal classes for serializer, and deserializer - struct PLCInfo { - explicit PLCInfo(PointerOwnershipType ownershipType_) - : ownershipType{ownershipType_}, - isSharedProcessed{false} {}; - PointerOwnershipType ownershipType; - bool isSharedProcessed; - - void update(PointerOwnershipType ptrType) { - //do nothing for observer - if (ptrType == PointerOwnershipType::Observer) - return; - if (ownershipType == PointerOwnershipType::Observer) { - //set ownership type - ownershipType = ptrType; - return; - } - //only shared ownership can get here multiple times - assert(ptrType == PointerOwnershipType::SharedOwner || - ptrType == PointerOwnershipType::SharedObserver); - //check if need to update to SharedOwner - if (ptrType == PointerOwnershipType::SharedOwner) - ownershipType = ptrType; - //mark that object already processed, so we do not serialize/deserialize duplicate objects - isSharedProcessed = true; - } - }; - - struct PLCInfoSerializer : PLCInfo { - PLCInfoSerializer(size_t id_, PointerOwnershipType ownershipType_) - : PLCInfo(ownershipType_), id{id_} {} - - size_t id; - }; - - struct PLCInfoDeserializer : PLCInfo { - PLCInfoDeserializer(void* ptr, PointerOwnershipType ownershipType_, MemResourceBase* memResource_) - : PLCInfo(ownershipType_), - ownerPtr{ptr}, - memResource{memResource_}, - observersList{StdPolyAlloc>{memResource_}} {}; - - //need to override these explicitly because we have pointer member - PLCInfoDeserializer(const PLCInfoDeserializer&) = delete; - - PLCInfoDeserializer(PLCInfoDeserializer&&) = default; - - PLCInfoDeserializer& operator=(const PLCInfoDeserializer&) = delete; - - PLCInfoDeserializer& operator=(PLCInfoDeserializer&&) = default; - - void processOwner(void* ptr) { - ownerPtr = ptr; - assert(ownershipType != PointerOwnershipType::Observer); - for (auto& o:observersList) - o.get() = ptr; - observersList.clear(); - observersList.shrink_to_fit(); - } - - void processObserver(void* (& ptr)) { - if (ownerPtr) { - ptr = ownerPtr; - } else { - observersList.emplace_back(ptr); - } - } - - void* ownerPtr; - MemResourceBase* memResource; - std::vector, - StdPolyAlloc>> observersList; - std::unique_ptr sharedState{}; - }; - - class PointerLinkingContextSerialization { - public: - explicit PointerLinkingContextSerialization(MemResourceBase* memResource = nullptr) - : _currId{0}, - _ptrMap{StdPolyAlloc>{memResource}} {} - - PointerLinkingContextSerialization(const PointerLinkingContextSerialization&) = delete; - - PointerLinkingContextSerialization& operator=(const PointerLinkingContextSerialization&) = delete; - - PointerLinkingContextSerialization(PointerLinkingContextSerialization&&) = default; - - PointerLinkingContextSerialization& operator=(PointerLinkingContextSerialization&&) = default; - - ~PointerLinkingContextSerialization() = default; - - const PLCInfoSerializer& getInfoByPtr(const void* ptr, PointerOwnershipType ptrType) { - auto res = _ptrMap.emplace(ptr, PLCInfoSerializer{_currId + 1u, ptrType}); - auto& ptrInfo = res.first->second; - if (res.second) { - ++_currId; - return ptrInfo; - } - ptrInfo.update(ptrType); - return ptrInfo; - } - - //valid, when all pointers have owners. - //we cannot serialize pointers, if we haven't serialized objects themselves - bool isPointerSerializationValid() const { - return std::all_of(_ptrMap.begin(), _ptrMap.end(), - [](const std::pair& p) { - return p.second.ownershipType == PointerOwnershipType::SharedOwner || - p.second.ownershipType == PointerOwnershipType::Owner; - }); - } - - private: - size_t _currId; - std::unordered_map, std::equal_to, - StdPolyAlloc> - > _ptrMap; - }; - - class PointerLinkingContextDeserialization { - public: - explicit PointerLinkingContextDeserialization(MemResourceBase* memResource = nullptr) - : _memResource{memResource}, - _idMap{StdPolyAlloc>{memResource}} {} - - PointerLinkingContextDeserialization(const PointerLinkingContextDeserialization&) = delete; - - PointerLinkingContextDeserialization& operator=(const PointerLinkingContextDeserialization&) = delete; - - PointerLinkingContextDeserialization(PointerLinkingContextDeserialization&&) = default; - - PointerLinkingContextDeserialization& operator=(PointerLinkingContextDeserialization&&) = default; - - ~PointerLinkingContextDeserialization() = default; - - PLCInfoDeserializer& getInfoById(size_t id, PointerOwnershipType ptrType) { - auto res = _idMap.emplace(id, PLCInfoDeserializer{nullptr, ptrType, _memResource}); - auto& ptrInfo = res.first->second; - if (!res.second) - ptrInfo.update(ptrType); - return ptrInfo; - } - - void clearSharedState() { - for (auto& item: _idMap) - item.second.sharedState.reset(); - } - - //valid, when all pointers has owners - bool isPointerDeserializationValid() const { - return std::all_of(_idMap.begin(), _idMap.end(), - [](const std::pair& p) { - return p.second.ownershipType == PointerOwnershipType::SharedOwner || - p.second.ownershipType == PointerOwnershipType::Owner; - }); - } - - MemResourceBase* getMemResource() noexcept { - return _memResource; - } - - void setMemResource(MemResourceBase* resource) noexcept { - _memResource = resource; - } - - private: - MemResourceBase* _memResource; - std::unordered_map, std::equal_to, - StdPolyAlloc>> _idMap; - }; - } - - //this class is for convenience - class PointerLinkingContext : - public pointer_utils::PointerLinkingContextSerialization, - public pointer_utils::PointerLinkingContextDeserialization { - public: - explicit PointerLinkingContext(MemResourceBase* memResource = nullptr) - :pointer_utils::PointerLinkingContextSerialization(memResource), - pointer_utils::PointerLinkingContextDeserialization(memResource) {}; - - bool isValid() const { - return isPointerSerializationValid() && isPointerDeserializationValid(); - } - }; - - namespace pointer_utils { - - template class TPtrManager, - template class TPolymorphicContext, typename RTTI> - class PointerObjectExtensionBase { - public: - - // helper types - template - struct IsPolymorphic : std::integral_constant::TElement>()> { - }; - - template - using OwnershipType = std::integral_constant; - - - explicit PointerObjectExtensionBase(PointerType ptrType = PointerType::Nullable, - MemResourceBase* resource = nullptr, - bool resourcePropagate = false) : - _ptrType{ptrType}, - _resourcePropagate{resourcePropagate}, - _resource{resource} { - } - - template - void serialize(Ser& ser, const T& obj, Fnc&& fnc) const { - - auto ptr = TPtrManager::getPtr(const_cast(obj)); - if (ptr) { - auto& ctx = ser.template context(); - auto& ptrInfo = ctx.getInfoByPtr(getBasePtr(ptr), TPtrManager::getOwnership()); - details::writeSize(ser.adapter(), ptrInfo.id); - if (TPtrManager::getOwnership() != PointerOwnershipType::Observer) { - if (!ptrInfo.isSharedProcessed) - serializeImpl(ser, ptr, std::forward(fnc), IsPolymorphic{}); - } - } else { - assert(_ptrType == PointerType::Nullable); - details::writeSize(ser.adapter(), 0); - } - - } - - template - void deserialize(Des& des, T& obj, Fnc&& fnc) const { - size_t id{}; - details::readSize(des.adapter(), id, 0, std::false_type{}); - auto& ctx = des.template context(); - auto prevResource = ctx.getMemResource(); - auto memResource = _resource ? _resource : prevResource; - // if we have resource and propagate is true, then change current resource - // so that deserializing nested pointers it will be used - if (_resource && _resourcePropagate) { - ctx.setMemResource(memResource); - } - if (id) { - auto& ptrInfo = ctx.getInfoById(id, TPtrManager::getOwnership()); - deserializeImpl(memResource, ptrInfo, des, obj, std::forward(fnc), IsPolymorphic{}, - OwnershipType::getOwnership()>{}); - } else { - if (_ptrType == PointerType::Nullable) { - if (auto ptr = TPtrManager::getPtr(obj)) { - destroyPtr(memResource, des, obj, IsPolymorphic{}); - }; - } else - des.adapter().error(ReaderError::InvalidPointer); - } - if (_resource && _resourcePropagate) { - ctx.setMemResource(prevResource); - } - } - - private: - - template - void destroyPtr(MemResourceBase* memResource, Des& des, TObj& obj, - std::true_type /*polymorphic*/) const { - const auto& ctx = des.template context>(); - auto ptr = TPtrManager::getPtr(obj); - TPtrManager::destroyPolymorphic(obj, memResource, ctx.getPolymorphicHandler(*ptr)); - } - - template - void destroyPtr(MemResourceBase* memResource, Des&, TObj& obj, - std::false_type /*polymorphic*/) const { - TPtrManager::destroy(obj, memResource, RTTI::template get::TElement>()); - } - - - template - const void* getBasePtr(const T* ptr) const { - // todo implement handling of types with virtual inheritance - // this is required to correctly track same object, when one object is derived and other is base class - // e.g. shared_ptr and weak_ptr or pointer observer Base* - return ptr; - } - - template - void serializeImpl(Ser& ser, TPtr& ptr, Fnc&&, std::true_type) const { - const auto& ctx = ser.template context>(); - ctx.serialize(ser, *ptr); - } - - template - void serializeImpl(Ser& ser, TPtr& ptr, Fnc&& fnc, std::false_type) const { - fnc(ser, *ptr); - } - - template - void deserializeImpl(MemResourceBase* memResource, PLCInfoDeserializer& ptrInfo, Des& des, T& obj, Fnc&&, - std::true_type, OwnershipType) const { - const auto& ctx = des.template context>(); - ctx.deserialize(des, TPtrManager::getPtr(obj), - [&obj, memResource]( - const std::shared_ptr& handler) { - TPtrManager::createPolymorphic(obj, memResource, handler); - return TPtrManager::getPtr(obj); - }, - [&obj, memResource](const std::shared_ptr& handler) { - TPtrManager::destroyPolymorphic(obj, memResource, handler); - }); - ptrInfo.processOwner(TPtrManager::getPtr(obj)); - } - - template - void deserializeImpl(MemResourceBase* memResource, PLCInfoDeserializer& ptrInfo, Des& des, T& obj, Fnc&& fnc, - std::false_type, OwnershipType) const { - auto ptr = TPtrManager::getPtr(obj); - if (ptr) { - fnc(des, *ptr); - } else { - TPtrManager::create(obj, memResource, RTTI::template get::TElement>()); - ptr = TPtrManager::getPtr(obj); - fnc(des, *ptr); - } - ptrInfo.processOwner(ptr); - } - - template - void deserializeImpl(MemResourceBase* memResource, PLCInfoDeserializer& ptrInfo, Des& des, T& obj, Fnc&&, - std::true_type, OwnershipType) const { - if (!ptrInfo.sharedState) { - const auto& ctx = des.template context>(); - ctx.deserialize(des, TPtrManager::getPtr(obj), - [&obj, &ptrInfo, memResource, this]( - const std::shared_ptr& handler) { - TPtrManager::createSharedPolymorphic( - createAndGetSharedStateObj(ptrInfo), - obj, memResource, handler); - return TPtrManager::getPtr(obj); - }, - [&obj, memResource](const std::shared_ptr& handler) { - TPtrManager::destroyPolymorphic(obj, memResource, handler); - }); - if (!ptrInfo.sharedState) - TPtrManager::saveToSharedState(createAndGetSharedStateObj(ptrInfo), obj); - } - TPtrManager::loadFromSharedState(getSharedStateObj(ptrInfo), obj); - ptrInfo.processOwner(TPtrManager::getPtr(obj)); - } - - template - void deserializeImpl(MemResourceBase* memResource, PLCInfoDeserializer& ptrInfo, Des& des, T& obj, Fnc&& fnc, - std::false_type, OwnershipType) const { - if (!ptrInfo.sharedState) { - auto ptr = TPtrManager::getPtr(obj); - if (ptr) { - TPtrManager::saveToSharedState(createAndGetSharedStateObj(ptrInfo), obj); - } else { - TPtrManager::createShared( - createAndGetSharedStateObj(ptrInfo), - obj, memResource, RTTI::template get::TElement>()); - ptr = TPtrManager::getPtr(obj); - } - fnc(des, *ptr); - } - TPtrManager::loadFromSharedState(getSharedStateObj(ptrInfo), obj); - ptrInfo.processOwner(TPtrManager::getPtr(obj)); - } - - template - void deserializeImpl(MemResourceBase* memResource, PLCInfoDeserializer& ptrInfo, Des& des, T& obj, - Fnc&& fnc, isPolymorph polymorph, - OwnershipType) const { - deserializeImpl(memResource, ptrInfo, des, obj, fnc, polymorph, - OwnershipType{}); - } - - template - void deserializeImpl(MemResourceBase* , PLCInfoDeserializer& ptrInfo, Des&, T& obj, Fnc&&, - isPolymorphic, OwnershipType) const { - ptrInfo.processObserver(reinterpret_cast(TPtrManager::getPtrRef(obj))); - } - - template - typename TPtrManager::TSharedState& createAndGetSharedStateObj(PLCInfoDeserializer& info) const { - using TSharedState = typename TPtrManager::TSharedState; - StdPolyAlloc alloc {info.memResource}; - auto* ptr = alloc.allocate(1); - auto* obj = new (ptr)TSharedState{}; - info.sharedState = std::unique_ptr( - obj, PointerSharedStateDeleter{info.memResource}); - return *obj; - } - - template - typename TPtrManager::TSharedState& getSharedStateObj(PLCInfoDeserializer& info) const { - return static_cast::TSharedState&>(*info.sharedState); - } - - - PointerType _ptrType; - bool _resourcePropagate; - MemResourceBase* _resource; - }; - - } - +namespace ext { + +// change name +enum class PointerType : uint8_t +{ + Nullable, + NotNull +}; + +// Observer - not responsible for pointer lifetime management. +// Owner - only ONE owner is responsible for this pointers creation/destruction +// SharedOwner, SharedObserver - MANY shared owners is responsible for pointer +// creation/destruction requires additional context to manage shared owners +// themselves. SharedOwner actually manages life time e.g. std::shared_ptr +// SharedObserver do not manage life time of the pointer, but can observe shared +// state .e.. std::weak_ptr and differently from Observer, creates new object if +// necessary and saves to shared state +enum class PointerOwnershipType : uint8_t +{ + Observer, + Owner, + SharedOwner, + SharedObserver +}; + +namespace pointer_utils { + +// this class is used to store context for shared ptr owners +struct PointerSharedStateBase +{ + virtual ~PointerSharedStateBase() = default; +}; + +struct PointerSharedStateDeleter +{ + PointerSharedStateDeleter() = default; + explicit PointerSharedStateDeleter(MemResourceBase* memResource) + : _memResource{ memResource } + { + } + void operator()(PointerSharedStateBase* data) const + { + data->~PointerSharedStateBase(); + StdPolyAlloc alloc{ _memResource }; + alloc.deallocate(data, 1); + } + MemResourceBase* _memResource = nullptr; +}; + +// PLC info is internal classes for serializer, and deserializer +struct PLCInfo +{ + explicit PLCInfo(PointerOwnershipType ownershipType_) + : ownershipType{ ownershipType_ } + , isSharedProcessed{ false } {}; + PointerOwnershipType ownershipType; + bool isSharedProcessed; + + void update(PointerOwnershipType ptrType) + { + // do nothing for observer + if (ptrType == PointerOwnershipType::Observer) + return; + if (ownershipType == PointerOwnershipType::Observer) { + // set ownership type + ownershipType = ptrType; + return; } + // only shared ownership can get here multiple times + assert(ptrType == PointerOwnershipType::SharedOwner || + ptrType == PointerOwnershipType::SharedObserver); + // check if need to update to SharedOwner + if (ptrType == PointerOwnershipType::SharedOwner) + ownershipType = ptrType; + // mark that object already processed, so we do not serialize/deserialize + // duplicate objects + isSharedProcessed = true; + } +}; + +struct PLCInfoSerializer : PLCInfo +{ + PLCInfoSerializer(size_t id_, PointerOwnershipType ownershipType_) + : PLCInfo(ownershipType_) + , id{ id_ } + { + } + + size_t id; +}; + +struct PLCInfoDeserializer : PLCInfo +{ + PLCInfoDeserializer(void* ptr, + PointerOwnershipType ownershipType_, + MemResourceBase* memResource_) + : PLCInfo(ownershipType_) + , ownerPtr{ ptr } + , memResource{ memResource_ } + , observersList{ StdPolyAlloc>{ + memResource_ } } {}; + + // need to override these explicitly because we have pointer member + PLCInfoDeserializer(const PLCInfoDeserializer&) = delete; + + PLCInfoDeserializer(PLCInfoDeserializer&&) = default; + + PLCInfoDeserializer& operator=(const PLCInfoDeserializer&) = delete; + + PLCInfoDeserializer& operator=(PLCInfoDeserializer&&) = default; + + void processOwner(void* ptr) + { + ownerPtr = ptr; + assert(ownershipType != PointerOwnershipType::Observer); + for (auto& o : observersList) + o.get() = ptr; + observersList.clear(); + observersList.shrink_to_fit(); + } + + void processObserver(void*(&ptr)) + { + if (ownerPtr) { + ptr = ownerPtr; + } else { + observersList.emplace_back(ptr); + } + } + + void* ownerPtr; + MemResourceBase* memResource; + std::vector, + StdPolyAlloc>> + observersList; + std::unique_ptr + sharedState{}; +}; + +class PointerLinkingContextSerialization +{ +public: + explicit PointerLinkingContextSerialization( + MemResourceBase* memResource = nullptr) + : _currId{ 0 } + , _ptrMap{ StdPolyAlloc>{ + memResource } } + { + } + + PointerLinkingContextSerialization( + const PointerLinkingContextSerialization&) = delete; + + PointerLinkingContextSerialization& operator=( + const PointerLinkingContextSerialization&) = delete; + + PointerLinkingContextSerialization(PointerLinkingContextSerialization&&) = + default; + + PointerLinkingContextSerialization& operator=( + PointerLinkingContextSerialization&&) = default; + + ~PointerLinkingContextSerialization() = default; + + const PLCInfoSerializer& getInfoByPtr(const void* ptr, + PointerOwnershipType ptrType) + { + auto res = _ptrMap.emplace(ptr, PLCInfoSerializer{ _currId + 1u, ptrType }); + auto& ptrInfo = res.first->second; + if (res.second) { + ++_currId; + return ptrInfo; + } + ptrInfo.update(ptrType); + return ptrInfo; + } + + // valid, when all pointers have owners. + // we cannot serialize pointers, if we haven't serialized objects themselves + bool isPointerSerializationValid() const + { + return std::all_of( + _ptrMap.begin(), + _ptrMap.end(), + [](const std::pair& p) { + return p.second.ownershipType == PointerOwnershipType::SharedOwner || + p.second.ownershipType == PointerOwnershipType::Owner; + }); + } + +private: + size_t _currId; + std::unordered_map< + const void*, + PLCInfoSerializer, + std::hash, + std::equal_to, + StdPolyAlloc>> + _ptrMap; +}; + +class PointerLinkingContextDeserialization +{ +public: + explicit PointerLinkingContextDeserialization( + MemResourceBase* memResource = nullptr) + : _memResource{ memResource } + , _idMap{ StdPolyAlloc>{ + memResource } } + { + } + + PointerLinkingContextDeserialization( + const PointerLinkingContextDeserialization&) = delete; + + PointerLinkingContextDeserialization& operator=( + const PointerLinkingContextDeserialization&) = delete; + + PointerLinkingContextDeserialization(PointerLinkingContextDeserialization&&) = + default; + + PointerLinkingContextDeserialization& operator=( + PointerLinkingContextDeserialization&&) = default; + + ~PointerLinkingContextDeserialization() = default; + + PLCInfoDeserializer& getInfoById(size_t id, PointerOwnershipType ptrType) + { + auto res = + _idMap.emplace(id, PLCInfoDeserializer{ nullptr, ptrType, _memResource }); + auto& ptrInfo = res.first->second; + if (!res.second) + ptrInfo.update(ptrType); + return ptrInfo; + } + + void clearSharedState() + { + for (auto& item : _idMap) + item.second.sharedState.reset(); + } + + // valid, when all pointers has owners + bool isPointerDeserializationValid() const + { + return std::all_of( + _idMap.begin(), + _idMap.end(), + [](const std::pair& p) { + return p.second.ownershipType == PointerOwnershipType::SharedOwner || + p.second.ownershipType == PointerOwnershipType::Owner; + }); + } + + MemResourceBase* getMemResource() noexcept { return _memResource; } + + void setMemResource(MemResourceBase* resource) noexcept + { + _memResource = resource; + } + +private: + MemResourceBase* _memResource; + std::unordered_map, + std::equal_to, + StdPolyAlloc>> + _idMap; +}; } -#endif //BITSERY_POINTER_UTILS_H +// this class is for convenience +class PointerLinkingContext + : public pointer_utils::PointerLinkingContextSerialization + , public pointer_utils::PointerLinkingContextDeserialization +{ +public: + explicit PointerLinkingContext(MemResourceBase* memResource = nullptr) + : pointer_utils::PointerLinkingContextSerialization(memResource) + , pointer_utils::PointerLinkingContextDeserialization(memResource){}; + + bool isValid() const + { + return isPointerSerializationValid() && isPointerDeserializationValid(); + } +}; + +namespace pointer_utils { + +template class TPtrManager, + template + class TPolymorphicContext, + typename RTTI> +class PointerObjectExtensionBase +{ +public: + // helper types + template + struct IsPolymorphic + : std::integral_constant< + bool, + RTTI::template isPolymorphic::TElement>()> + { + }; + + template + using OwnershipType = std::integral_constant; + + explicit PointerObjectExtensionBase( + PointerType ptrType = PointerType::Nullable, + MemResourceBase* resource = nullptr, + bool resourcePropagate = false) + : _ptrType{ ptrType } + , _resourcePropagate{ resourcePropagate } + , _resource{ resource } + { + } + + template + void serialize(Ser& ser, const T& obj, Fnc&& fnc) const + { + + auto ptr = TPtrManager::getPtr(const_cast(obj)); + if (ptr) { + auto& ctx = ser.template context< + pointer_utils::PointerLinkingContextSerialization>(); + auto& ptrInfo = + ctx.getInfoByPtr(getBasePtr(ptr), TPtrManager::getOwnership()); + details::writeSize(ser.adapter(), ptrInfo.id); + if (TPtrManager::getOwnership() != PointerOwnershipType::Observer) { + if (!ptrInfo.isSharedProcessed) + serializeImpl(ser, ptr, std::forward(fnc), IsPolymorphic{}); + } + } else { + assert(_ptrType == PointerType::Nullable); + details::writeSize(ser.adapter(), 0); + } + } + + template + void deserialize(Des& des, T& obj, Fnc&& fnc) const + { + size_t id{}; + details::readSize(des.adapter(), id, 0, std::false_type{}); + auto& ctx = des.template context< + pointer_utils::PointerLinkingContextDeserialization>(); + auto prevResource = ctx.getMemResource(); + auto memResource = _resource ? _resource : prevResource; + // if we have resource and propagate is true, then change current resource + // so that deserializing nested pointers it will be used + if (_resource && _resourcePropagate) { + ctx.setMemResource(memResource); + } + if (id) { + auto& ptrInfo = ctx.getInfoById(id, TPtrManager::getOwnership()); + deserializeImpl(memResource, + ptrInfo, + des, + obj, + std::forward(fnc), + IsPolymorphic{}, + OwnershipType::getOwnership()>{}); + } else { + if (_ptrType == PointerType::Nullable) { + if (auto ptr = TPtrManager::getPtr(obj)) { + destroyPtr(memResource, des, obj, IsPolymorphic{}); + }; + } else + des.adapter().error(ReaderError::InvalidPointer); + } + if (_resource && _resourcePropagate) { + ctx.setMemResource(prevResource); + } + } + +private: + template + void destroyPtr(MemResourceBase* memResource, + Des& des, + TObj& obj, + std::true_type /*polymorphic*/) const + { + const auto& ctx = des.template context>(); + auto ptr = TPtrManager::getPtr(obj); + TPtrManager::destroyPolymorphic( + obj, memResource, ctx.getPolymorphicHandler(*ptr)); + } + + template + void destroyPtr(MemResourceBase* memResource, + Des&, + TObj& obj, + std::false_type /*polymorphic*/) const + { + TPtrManager::destroy( + obj, + memResource, + RTTI::template get::TElement>()); + } + + template + const void* getBasePtr(const T* ptr) const + { + // todo implement handling of types with virtual inheritance + // this is required to correctly track same object, when one object is + // derived and other is base class e.g. shared_ptr and + // weak_ptr or pointer observer Base* + return ptr; + } + + template + void serializeImpl(Ser& ser, TPtr& ptr, Fnc&&, std::true_type) const + { + const auto& ctx = ser.template context>(); + ctx.serialize(ser, *ptr); + } + + template + void serializeImpl(Ser& ser, TPtr& ptr, Fnc&& fnc, std::false_type) const + { + fnc(ser, *ptr); + } + + template + void deserializeImpl(MemResourceBase* memResource, + PLCInfoDeserializer& ptrInfo, + Des& des, + T& obj, + Fnc&&, + std::true_type, + OwnershipType) const + { + const auto& ctx = des.template context>(); + ctx.deserialize( + des, + TPtrManager::getPtr(obj), + [&obj, + memResource](const std::shared_ptr& handler) { + TPtrManager::createPolymorphic(obj, memResource, handler); + return TPtrManager::getPtr(obj); + }, + [&obj, + memResource](const std::shared_ptr& handler) { + TPtrManager::destroyPolymorphic(obj, memResource, handler); + }); + ptrInfo.processOwner(TPtrManager::getPtr(obj)); + } + + template + void deserializeImpl(MemResourceBase* memResource, + PLCInfoDeserializer& ptrInfo, + Des& des, + T& obj, + Fnc&& fnc, + std::false_type, + OwnershipType) const + { + auto ptr = TPtrManager::getPtr(obj); + if (ptr) { + fnc(des, *ptr); + } else { + TPtrManager::create( + obj, + memResource, + RTTI::template get::TElement>()); + ptr = TPtrManager::getPtr(obj); + fnc(des, *ptr); + } + ptrInfo.processOwner(ptr); + } + + template + void deserializeImpl(MemResourceBase* memResource, + PLCInfoDeserializer& ptrInfo, + Des& des, + T& obj, + Fnc&&, + std::true_type, + OwnershipType) const + { + if (!ptrInfo.sharedState) { + const auto& ctx = des.template context>(); + ctx.deserialize( + des, + TPtrManager::getPtr(obj), + [&obj, &ptrInfo, memResource, this]( + const std::shared_ptr& handler) { + TPtrManager::createSharedPolymorphic( + createAndGetSharedStateObj(ptrInfo), obj, memResource, handler); + return TPtrManager::getPtr(obj); + }, + [&obj, + memResource](const std::shared_ptr& handler) { + TPtrManager::destroyPolymorphic(obj, memResource, handler); + }); + if (!ptrInfo.sharedState) + TPtrManager::saveToSharedState( + createAndGetSharedStateObj(ptrInfo), obj); + } + TPtrManager::loadFromSharedState(getSharedStateObj(ptrInfo), obj); + ptrInfo.processOwner(TPtrManager::getPtr(obj)); + } + + template + void deserializeImpl(MemResourceBase* memResource, + PLCInfoDeserializer& ptrInfo, + Des& des, + T& obj, + Fnc&& fnc, + std::false_type, + OwnershipType) const + { + if (!ptrInfo.sharedState) { + auto ptr = TPtrManager::getPtr(obj); + if (ptr) { + TPtrManager::saveToSharedState( + createAndGetSharedStateObj(ptrInfo), obj); + } else { + TPtrManager::createShared( + createAndGetSharedStateObj(ptrInfo), + obj, + memResource, + RTTI::template get::TElement>()); + ptr = TPtrManager::getPtr(obj); + } + fnc(des, *ptr); + } + TPtrManager::loadFromSharedState(getSharedStateObj(ptrInfo), obj); + ptrInfo.processOwner(TPtrManager::getPtr(obj)); + } + + template + void deserializeImpl( + MemResourceBase* memResource, + PLCInfoDeserializer& ptrInfo, + Des& des, + T& obj, + Fnc&& fnc, + isPolymorph polymorph, + OwnershipType) const + { + deserializeImpl(memResource, + ptrInfo, + des, + obj, + fnc, + polymorph, + OwnershipType{}); + } + + template + void deserializeImpl(MemResourceBase*, + PLCInfoDeserializer& ptrInfo, + Des&, + T& obj, + Fnc&&, + isPolymorphic, + OwnershipType) const + { + ptrInfo.processObserver( + reinterpret_cast(TPtrManager::getPtrRef(obj))); + } + + template + typename TPtrManager::TSharedState& createAndGetSharedStateObj( + PLCInfoDeserializer& info) const + { + using TSharedState = typename TPtrManager::TSharedState; + StdPolyAlloc alloc{ info.memResource }; + auto* ptr = alloc.allocate(1); + auto* obj = new (ptr) TSharedState{}; + info.sharedState = + std::unique_ptr( + obj, PointerSharedStateDeleter{ info.memResource }); + return *obj; + } + + template + typename TPtrManager::TSharedState& getSharedStateObj( + PLCInfoDeserializer& info) const + { + return static_cast::TSharedState&>( + *info.sharedState); + } + + PointerType _ptrType; + bool _resourcePropagate; + MemResourceBase* _resource; +}; + +} + +} +} + +#endif // BITSERY_POINTER_UTILS_H diff --git a/include/bitsery/ext/utils/polymorphism_utils.h b/include/bitsery/ext/utils/polymorphism_utils.h index fba4534..27cc917 100644 --- a/include/bitsery/ext/utils/polymorphism_utils.h +++ b/include/bitsery/ext/utils/polymorphism_utils.h @@ -1,286 +1,366 @@ -//MIT License +// MIT License // -//Copyright (c) 2018 Mindaugas Vinkelis +// Copyright (c) 2018 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: +// 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 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. +// 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_EXT_POLYMORPHISM_UTILS_H #define BITSERY_EXT_POLYMORPHISM_UTILS_H #include "memory_resource.h" #include -#include #include +#include namespace bitsery { - namespace ext { +namespace ext { - //helper type, that contains list of types - template - struct PolymorphicClassesList { - }; +// helper type, that contains list of types +template +struct PolymorphicClassesList +{ +}; - //specialize for your base class by deriving from PolymorphicDerivedClasses with list of derivatives that DIRECTLY inherits from your base class. -//e.g. -// template <> PolymorphicBaseClass: PolymorphicDerivedClasses{}; -// template <> PolymorphicBaseClass: PolymorphicDerivedClasses {}; -// IMPORTANT !!! -// although you can add all derivates to same base like this: -// template <> PolymorphicBaseClass:PolymorphicDerivedClasses{}; -// it will not work when you try to serialize Dog*, because it will not find Bulldog and GoldenRetriever - template - struct PolymorphicBaseClass { - using Childs = PolymorphicClassesList<>; - }; +// specialize for your base class by deriving from PolymorphicDerivedClasses +// with list of derivatives that DIRECTLY inherits from your base class. +// e.g. +// template <> PolymorphicBaseClass: PolymorphicDerivedClasses{}; template <> PolymorphicBaseClass: +// PolymorphicDerivedClasses {}; IMPORTANT !!! +// although you can add all derivates to same base like this: +// template <> PolymorphicBaseClass:PolymorphicDerivedClasses{}; it will not work when you try to serialize +// Dog*, because it will not find Bulldog and GoldenRetriever +template +struct PolymorphicBaseClass +{ + using Childs = PolymorphicClassesList<>; +}; -//derive from this class when specifying childs for your base class, atleast one child must exists, hence T1 -//e.g. -// template <> PolymorphicBaseClass: PolymorphicDerivedClasses{}; - template - struct PolymorphicDerivedClasses { - using Childs = PolymorphicClassesList; - }; +// derive from this class when specifying childs for your base class, atleast +// one child must exists, hence T1 e.g. +// template <> PolymorphicBaseClass: PolymorphicDerivedClasses{}; +template +struct PolymorphicDerivedClasses +{ + using Childs = PolymorphicClassesList; +}; - class PolymorphicHandlerBase { - public: - virtual void* create(const pointer_utils::PolyAllocWithTypeId& alloc) const = 0; +class PolymorphicHandlerBase +{ +public: + virtual void* create( + const pointer_utils::PolyAllocWithTypeId& alloc) const = 0; - virtual void destroy(const pointer_utils::PolyAllocWithTypeId& alloc, void* ptr) const = 0; + virtual void destroy(const pointer_utils::PolyAllocWithTypeId& alloc, + void* ptr) const = 0; - virtual void process(void* ser, void* obj) const = 0; + virtual void process(void* ser, void* obj) const = 0; - virtual ~PolymorphicHandlerBase() = default; - }; + virtual ~PolymorphicHandlerBase() = default; +}; - template - class PolymorphicHandler : public PolymorphicHandlerBase { - public: +template +class PolymorphicHandler : public PolymorphicHandlerBase +{ +public: + void* create(const pointer_utils::PolyAllocWithTypeId& alloc) const final + { + return toBase(alloc.newObject(RTTI::template get())); + } - void* create(const pointer_utils::PolyAllocWithTypeId& alloc) const final { - return toBase(alloc.newObject(RTTI::template get())); - } + void destroy(const pointer_utils::PolyAllocWithTypeId& alloc, + void* ptr) const final + { + alloc.deleteObject(fromBase(ptr), RTTI::template get()); + } - void destroy(const pointer_utils::PolyAllocWithTypeId& alloc, void* ptr) const final { - alloc.deleteObject(fromBase(ptr), RTTI::template get()); - } + void process(void* ser, void* obj) const final + { + static_cast(ser)->object(*fromBase(obj)); + } - void process(void* ser, void* obj) const final { - static_cast(ser)->object(*fromBase(obj)); - } +private: + TDerived* fromBase(void* obj) const + { + return RTTI::template cast(static_cast(obj)); + } - private: + TBase* toBase(void* obj) const + { + return RTTI::template cast(static_cast(obj)); + } +}; - TDerived* fromBase(void* obj) const { - return RTTI::template cast(static_cast(obj)); - } +template +class PolymorphicContext +{ +private: + struct BaseToDerivedKey + { - TBase* toBase(void* obj) const { - return RTTI::template cast(static_cast(obj)); - } - - }; - - template - class PolymorphicContext { - private: - - struct BaseToDerivedKey { - - std::size_t baseHash; - std::size_t derivedHash; - - bool operator==(const BaseToDerivedKey& other) const { - return baseHash == other.baseHash && derivedHash == other.derivedHash; - } - }; - - struct BaseToDerivedKeyHashier { - size_t operator()(const BaseToDerivedKey& key) const { - return (key.baseHash + (key.baseHash << 6) + (key.derivedHash >> 2)) ^ key.derivedHash; - } - }; - - template class THierarchy, typename TBase, typename TDerived> - void add() { - addToMap(std::is_abstract{}); - addChilds(typename THierarchy::Childs{}); - } - - template class THierarchy, typename TBase, typename TDerived, typename T1, typename ... Tn> - void addChilds(PolymorphicClassesList) { - static_assert(std::is_base_of::value, - "PolymorphicBaseClass must derive a list of derived classes from TBase."); - add(); - addChilds(PolymorphicClassesList{}); - //iterate through derived class hierarchy as well - add(); - } - - template class THierarchy, typename TBase, typename TDerived> - void addChilds(PolymorphicClassesList<>) { - } - - template - void addToMap(std::false_type) { - using THandler = PolymorphicHandler; - BaseToDerivedKey key{RTTI::template get(), RTTI::template get()}; - pointer_utils::StdPolyAlloc alloc{_memResource}; - auto ptr = alloc.allocate(1); - std::shared_ptr handler(new (ptr)THandler{}, [alloc](THandler* data) mutable { - data->~THandler(); - alloc.deallocate(data, 1); - }, alloc); - if (_baseToDerivedMap - .emplace(key, std::move(handler)) - .second) { - auto it = _baseToDerivedArray.find(key.baseHash); - if (it == _baseToDerivedArray.end()) { - it = _baseToDerivedArray.emplace( - std::piecewise_construct, - std::forward_as_tuple(key.baseHash), - std::forward_as_tuple(pointer_utils::StdPolyAlloc{_memResource})).first; - } - it->second.push_back(key.derivedHash); - } - } - - template - void addToMap(std::true_type) { - //cannot add abstract class - } - - MemResourceBase* _memResource; - // store shared ptr to polymorphic handler, because it might be copied to "smart pointer" deleter - std::unordered_map, - BaseToDerivedKeyHashier, std::equal_to, - pointer_utils::StdPolyAlloc>> - > _baseToDerivedMap; - // this will allow convert from platform specific type information, to platform independent base->derived index - // this only works if all polymorphic relationships (PolymorphicBaseClass -> PolymorphicDerivedClasses) - // is equal between platforms. - std::unordered_map>, - std::hash, std::equal_to, - pointer_utils::StdPolyAlloc>>> - > _baseToDerivedArray; - - public: - - explicit PolymorphicContext(MemResourceBase* memResource = nullptr) - :_memResource{memResource}, - _baseToDerivedMap{pointer_utils::StdPolyAlloc>>{memResource}}, - _baseToDerivedArray{pointer_utils::StdPolyAlloc>>>{memResource}} - {} - - PolymorphicContext(const PolymorphicContext& ) = delete; - PolymorphicContext& operator = (const PolymorphicContext&) = delete; - PolymorphicContext(PolymorphicContext&& ) = default; - PolymorphicContext& operator = (PolymorphicContext&&) = default; - - - void clear() { - _baseToDerivedMap.clear(); - _baseToDerivedArray.clear(); - } - - // THierarchy is the name of class, that defines hierarchy - // PolymorphicBaseClass is defined as default parameter, so that at instantiation time - // it will get unique symbol in translation unit for PolymorphicBaseClass (which is defined in anonymous namespace) - // https://github.com/fraillt/bitsery/issues/9 - template class THierarchy = PolymorphicBaseClass, typename T1, typename ...Tn> - void registerBasesList(PolymorphicClassesList) { - add(); - registerBasesList(PolymorphicClassesList{}); - } - - template class THierarchy> - void registerBasesList(PolymorphicClassesList<>) { - } - - // optional method, in case you want to construct base class hierarchy your self - template - void registerSingleBaseBranch() { - static_assert(std::is_base_of::value, "TDerived must be derived from TBase"); - static_assert(!std::is_abstract::value, "TDerived cannot be abstract"); - addToMap(std::false_type{}); - } - - - template - void serialize(Serializer& ser, TBase& obj) const { - //get derived key - BaseToDerivedKey key{RTTI::template get(), RTTI::template get(obj)}; - auto it = _baseToDerivedMap.find(key); - assert(it != _baseToDerivedMap.end()); - - //convert derived hash to derived index, to make it work in cross-platform environment - auto& vec = _baseToDerivedArray.find(key.baseHash)->second; - auto derivedIndex = static_cast(std::distance(vec.begin(), std::find(vec.begin(), vec.end(), - key.derivedHash))); - details::writeSize(ser.adapter(), derivedIndex); - - //serialize - it->second->process(&ser, &obj); - } - - template - void deserialize(Deserializer& des, TBase* obj, - TCreateFnc createFnc, TDestroyFnc destroyFnc) const { - size_t derivedIndex{}; - details::readSize(des.adapter(), derivedIndex, 0, std::false_type{}); - - auto baseToDerivedVecIt = _baseToDerivedArray.find(RTTI::template get()); - //base class is known at compile time, so we can assert on this one - assert(baseToDerivedVecIt != _baseToDerivedArray.end()); - - if (baseToDerivedVecIt->second.size() > derivedIndex) { - //convert derived index to derived hash, to make it work in cross-platform environment - auto derivedHash = baseToDerivedVecIt->second[derivedIndex]; - auto& handler = _baseToDerivedMap.find( - BaseToDerivedKey{RTTI::template get(), derivedHash})->second; - //if object is null or different type, create new and assign it - if (obj == nullptr || RTTI::template get(*obj) != derivedHash) { - if (obj) { - destroyFnc(getPolymorphicHandler(*obj)); - } - obj = createFnc(handler); - } - handler->process(&des, obj); - } else - des.adapter().error(ReaderError::InvalidPointer); - } - - template - const std::shared_ptr& getPolymorphicHandler(TBase& obj) const { - auto deleteHandlerIt = _baseToDerivedMap.find( - BaseToDerivedKey{RTTI::template get(), RTTI::template get(obj)}); - assert(deleteHandlerIt != _baseToDerivedMap.end()); - return deleteHandlerIt->second; - } - - - }; + std::size_t baseHash; + std::size_t derivedHash; + bool operator==(const BaseToDerivedKey& other) const + { + return baseHash == other.baseHash && derivedHash == other.derivedHash; } + }; + + struct BaseToDerivedKeyHashier + { + size_t operator()(const BaseToDerivedKey& key) const + { + return (key.baseHash + (key.baseHash << 6) + (key.derivedHash >> 2)) ^ + key.derivedHash; + } + }; + + template + class THierarchy, + typename TBase, + typename TDerived> + void add() + { + addToMap(std::is_abstract{}); + addChilds( + typename THierarchy::Childs{}); + } + + template + class THierarchy, + typename TBase, + typename TDerived, + typename T1, + typename... Tn> + void addChilds(PolymorphicClassesList) + { + static_assert(std::is_base_of::value, + "PolymorphicBaseClass must derive a list of derived " + "classes from TBase."); + add(); + addChilds( + PolymorphicClassesList{}); + // iterate through derived class hierarchy as well + add(); + } + + template + class THierarchy, + typename TBase, + typename TDerived> + void addChilds(PolymorphicClassesList<>) + { + } + + template + void addToMap(std::false_type) + { + using THandler = PolymorphicHandler; + BaseToDerivedKey key{ RTTI::template get(), + RTTI::template get() }; + pointer_utils::StdPolyAlloc alloc{ _memResource }; + auto ptr = alloc.allocate(1); + std::shared_ptr handler( + new (ptr) THandler{}, + [alloc](THandler* data) mutable { + data->~THandler(); + alloc.deallocate(data, 1); + }, + alloc); + if (_baseToDerivedMap.emplace(key, std::move(handler)).second) { + auto it = _baseToDerivedArray.find(key.baseHash); + if (it == _baseToDerivedArray.end()) { + it = _baseToDerivedArray + .emplace(std::piecewise_construct, + std::forward_as_tuple(key.baseHash), + std::forward_as_tuple( + pointer_utils::StdPolyAlloc{ _memResource })) + .first; + } + it->second.push_back(key.derivedHash); + } + } + + template + void addToMap(std::true_type) + { + // cannot add abstract class + } + + MemResourceBase* _memResource; + // store shared ptr to polymorphic handler, because it might be copied to + // "smart pointer" deleter + std::unordered_map, + BaseToDerivedKeyHashier, + std::equal_to, + pointer_utils::StdPolyAlloc< + std::pair>>> + _baseToDerivedMap; + // this will allow convert from platform specific type information, to + // platform independent base->derived index this only works if all polymorphic + // relationships (PolymorphicBaseClass -> + // PolymorphicDerivedClasses) is equal between platforms. + std::unordered_map< + size_t, + std::vector>, + std::hash, + std::equal_to, + pointer_utils::StdPolyAlloc< + std::pair>>>> + _baseToDerivedArray; + +public: + explicit PolymorphicContext(MemResourceBase* memResource = nullptr) + : _memResource{ memResource } + , _baseToDerivedMap{ pointer_utils::StdPolyAlloc< + std::pair>>{ memResource } } + , _baseToDerivedArray{ pointer_utils::StdPolyAlloc< + std::pair>>>{ + memResource } } + { + } + + PolymorphicContext(const PolymorphicContext&) = delete; + PolymorphicContext& operator=(const PolymorphicContext&) = delete; + PolymorphicContext(PolymorphicContext&&) = default; + PolymorphicContext& operator=(PolymorphicContext&&) = default; + + void clear() + { + _baseToDerivedMap.clear(); + _baseToDerivedArray.clear(); + } + + // THierarchy is the name of class, that defines hierarchy + // PolymorphicBaseClass is defined as default parameter, so that at + // instantiation time it will get unique symbol in translation unit for + // PolymorphicBaseClass (which is defined in anonymous namespace) + // https://github.com/fraillt/bitsery/issues/9 + template class THierarchy = PolymorphicBaseClass, + typename T1, + typename... Tn> + void registerBasesList(PolymorphicClassesList) + { + add(); + registerBasesList(PolymorphicClassesList{}); + } + + template class THierarchy> + void registerBasesList(PolymorphicClassesList<>) + { + } + + // optional method, in case you want to construct base class hierarchy your + // self + template + void registerSingleBaseBranch() + { + static_assert(std::is_base_of::value, + "TDerived must be derived from TBase"); + static_assert(!std::is_abstract::value, + "TDerived cannot be abstract"); + addToMap(std::false_type{}); + } + + template + void serialize(Serializer& ser, TBase& obj) const + { + // get derived key + BaseToDerivedKey key{ RTTI::template get(), + RTTI::template get(obj) }; + auto it = _baseToDerivedMap.find(key); + assert(it != _baseToDerivedMap.end()); + + // convert derived hash to derived index, to make it work in cross-platform + // environment + auto& vec = _baseToDerivedArray.find(key.baseHash)->second; + auto derivedIndex = static_cast(std::distance( + vec.begin(), std::find(vec.begin(), vec.end(), key.derivedHash))); + details::writeSize(ser.adapter(), derivedIndex); + + // serialize + it->second->process(&ser, &obj); + } + + template + void deserialize(Deserializer& des, + TBase* obj, + TCreateFnc createFnc, + TDestroyFnc destroyFnc) const + { + size_t derivedIndex{}; + details::readSize(des.adapter(), derivedIndex, 0, std::false_type{}); + + auto baseToDerivedVecIt = + _baseToDerivedArray.find(RTTI::template get()); + // base class is known at compile time, so we can assert on this one + assert(baseToDerivedVecIt != _baseToDerivedArray.end()); + + if (baseToDerivedVecIt->second.size() > derivedIndex) { + // convert derived index to derived hash, to make it work in + // cross-platform environment + auto derivedHash = baseToDerivedVecIt->second[derivedIndex]; + auto& handler = + _baseToDerivedMap + .find(BaseToDerivedKey{ RTTI::template get(), derivedHash }) + ->second; + // if object is null or different type, create new and assign it + if (obj == nullptr || RTTI::template get(*obj) != derivedHash) { + if (obj) { + destroyFnc(getPolymorphicHandler(*obj)); + } + obj = createFnc(handler); + } + handler->process(&des, obj); + } else + des.adapter().error(ReaderError::InvalidPointer); + } + + template + const std::shared_ptr& getPolymorphicHandler( + TBase& obj) const + { + auto deleteHandlerIt = _baseToDerivedMap.find(BaseToDerivedKey{ + RTTI::template get(), RTTI::template get(obj) }); + assert(deleteHandlerIt != _baseToDerivedMap.end()); + return deleteHandlerIt->second; + } +}; } -#endif //BITSERY_EXT_POLYMORPHISM_UTILS_H +} + +#endif // BITSERY_EXT_POLYMORPHISM_UTILS_H diff --git a/include/bitsery/ext/utils/rtti_utils.h b/include/bitsery/ext/utils/rtti_utils.h index be9ea5e..b017bb0 100644 --- a/include/bitsery/ext/utils/rtti_utils.h +++ b/include/bitsery/ext/utils/rtti_utils.h @@ -1,61 +1,65 @@ -//MIT License +// MIT License // -//Copyright (c) 2018 Mindaugas Vinkelis +// Copyright (c) 2018 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: +// 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 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. +// 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_RTTI_UTILS_H #define BITSERY_RTTI_UTILS_H -#include -#include #include +#include +#include namespace bitsery { - namespace ext { +namespace ext { - struct StandardRTTI { +struct StandardRTTI +{ - template - static size_t get(TBase& obj) { - return typeid(obj).hash_code(); - } + template + static size_t get(TBase& obj) + { + return typeid(obj).hash_code(); + } - template - static constexpr size_t get() { - return typeid(TBase).hash_code(); - } + template + static constexpr size_t get() + { + return typeid(TBase).hash_code(); + } - template - static constexpr TDerived* cast(TBase* obj) { - static_assert(!std::is_pointer::value, ""); - return dynamic_cast(obj); - } + template + static constexpr TDerived* cast(TBase* obj) + { + static_assert(!std::is_pointer::value, ""); + return dynamic_cast(obj); + } - template - static constexpr bool isPolymorphic() { - return std::is_polymorphic::value; - } + template + static constexpr bool isPolymorphic() + { + return std::is_polymorphic::value; + } +}; - }; - - } +} } -#endif //BITSERY_RTTI_UTILS_H +#endif // BITSERY_RTTI_UTILS_H diff --git a/include/bitsery/ext/value_range.h b/include/bitsery/ext/value_range.h index 88ec2fc..0352dd5 100644 --- a/include/bitsery/ext/value_range.h +++ b/include/bitsery/ext/value_range.h @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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_EXT_VALUE_RANGE_H #define BITSERY_EXT_VALUE_RANGE_H @@ -27,191 +27,242 @@ namespace bitsery { - namespace ext { - //this class is used to make default RangeSpec float specialization always prefer constructor with precision - struct BitsConstraint { - explicit constexpr BitsConstraint(size_t bits) : value{bits} {} +namespace ext { +// this class is used to make default RangeSpec float specialization always +// prefer constructor with precision +struct BitsConstraint +{ + explicit constexpr BitsConstraint(size_t bits) + : value{ bits } + { + } - const size_t value; - }; + const size_t value; +}; +} + +// implementation details for range functionality +namespace details { + +template +constexpr size_t +getSize(T v, size_t s) +{ + return v > 0 ? getSize(v / 2, s + 1) : s; +} + +template +constexpr size_t +calcRequiredBits(T min, T max) +{ + // call recursive function, because some compilers only support constexpr + // functions with return-only body + return getSize(max - min, 0); +} + +template +struct RangeSpec +{ + + constexpr RangeSpec(T minValue, T maxValue) + : min{ minValue } + , max{ maxValue } + , bitsRequired{ calcRequiredBits(min, max) } + { + } + + const T min; + const T max; + const size_t bitsRequired; +}; + +template +struct RangeSpec::value>::type> +{ + + constexpr RangeSpec(T minValue, T maxValue) + : min{ minValue } + , max{ maxValue } + , bitsRequired{ calcRequiredBits( + static_cast::type>(min), + static_cast::type>(max)) } + { + } + + const T min; + const T max; + const size_t bitsRequired; +}; + +template +struct RangeSpec< + T, + typename std::enable_if::value>::type> +{ + + constexpr RangeSpec(T minValue, T maxValue, ext::BitsConstraint bits) + : min{ minValue } + , max{ maxValue } + , bitsRequired{ bits.value } + { + } + + constexpr RangeSpec(T minValue, T maxValue, T precision) + : min{ minValue } + , max{ maxValue } + , bitsRequired{ calcRequiredBits>( + {}, + static_cast>((max - min) / precision)) } + { + } + + const T min; + const T max; + const size_t bitsRequired; +}; + +template::value>::type* = nullptr> +details::SameSizeUnsigned +getRangeValue(const T& v, const RangeSpec& r) +{ + return static_cast>(v - r.min); +} + +template::value>::type* = nullptr> +details::SameSizeUnsigned +getRangeValue(const T& v, const RangeSpec& r) +{ + using VT = details::SameSizeUnsigned; + return static_cast(static_cast(v) - static_cast(r.min)); +} + +template< + typename T, + typename std::enable_if::value>::type* = nullptr> +details::SameSizeUnsigned +getRangeValue(const T& v, const RangeSpec& r) +{ + using VT = details::SameSizeUnsigned; + const VT maxUint = (static_cast(1) << r.bitsRequired) - 1; + const T ratio = (v - r.min) / (r.max - r.min); + return static_cast(ratio * static_cast(maxUint)); +} + +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 = typename std::underlying_type::type; + reinterpret_cast(v) += static_cast(r.min); +} + +template< + typename T, + typename std::enable_if::value>::type* = nullptr> +void +setRangeValue(T& v, const RangeSpec& r) +{ + using UIT = details::SameSizeUnsigned; + const auto intRep = reinterpret_cast(v); + const UIT maxUint = (static_cast(1) << r.bitsRequired) - 1; + v = r.min + + (static_cast(intRep) / static_cast(maxUint)) * (r.max - r.min); +} + +template::value>::type* = nullptr> +bool +isRangeValid(const T& v, const RangeSpec& r) +{ + return !(r.min > v || v > r.max); +} + +template::value>::type* = nullptr> +bool +isRangeValid(const T& v, const RangeSpec& r) +{ + using VT = typename std::underlying_type::type; + return !(static_cast(r.min) > static_cast(v) || + static_cast(v) > static_cast(r.max)); +} +} + +namespace ext { + +template +class ValueRange +{ +public: + template + constexpr ValueRange(const TValue& min, const TValue& max, Args&&... args) + : _range{ min, max, std::forward(args)... } + { + } + + template + void serialize(Ser& ser, const T& v, Fnc&&) const + { + assert(details::isRangeValid(v, _range)); + using BT = decltype(details::getRangeValue(v, _range)); + ser.adapter().template writeBits(details::getRangeValue(v, _range), + _range.bitsRequired); + } + + template + void deserialize(Des& des, T& v, Fnc&&) const + { + auto& reader = des.adapter(); + reader.readBits(reinterpret_cast&>(v), + _range.bitsRequired); + details::setRangeValue(v, _range); + handleInvalidRange( + reader, v, std::integral_constant{}); + } + + constexpr size_t getRequiredBits() const { return _range.bitsRequired; }; + +private: + template + void handleInvalidRange(Reader& reader, T& v, std::true_type) const + { + if (!details::isRangeValid(v, _range)) { + reader.error(ReaderError::InvalidData); + v = _range.min; } + } - //implementation details for range functionality - namespace details { + template + void handleInvalidRange(Reader&, T&, std::false_type) const + { + } - template - constexpr size_t getSize(T v, size_t s) { - return v > 0 ? getSize(v / 2, s + 1) : s; - } + details::RangeSpec _range; +}; +} - template - constexpr size_t calcRequiredBits(T min, T max) { - //call recursive function, because some compilers only support constexpr functions with return-only body - return getSize(max - min, 0); - } - - template - struct RangeSpec { - - constexpr RangeSpec(T minValue, T maxValue) - : min{minValue}, - max{maxValue}, - bitsRequired{calcRequiredBits(min, max)} { - } - - const T min; - const T max; - const size_t bitsRequired; - }; - - - template - struct RangeSpec::value>::type> { - - constexpr RangeSpec(T minValue, T maxValue) : - min{minValue}, - max{maxValue}, - bitsRequired{calcRequiredBits( - static_cast::type>(min), - static_cast::type>(max))} { - } - - const T min; - const T max; - const size_t bitsRequired; - }; - - - template - struct RangeSpec::value>::type> { - - constexpr RangeSpec(T minValue, T maxValue, ext::BitsConstraint bits) : - min{minValue}, - max{maxValue}, - bitsRequired{bits.value} { - } - - constexpr RangeSpec(T minValue, T maxValue, T precision) : - min{minValue}, - max{maxValue}, - bitsRequired{calcRequiredBits>( - {}, static_cast>((max - min) / precision))} { - - } - - const T min; - const T max; - const size_t bitsRequired; - }; - - template::value>::type * = nullptr> - details::SameSizeUnsigned getRangeValue(const T &v, const RangeSpec &r) { - return static_cast>(v - r.min); - } - - template::value>::type * = nullptr> - details::SameSizeUnsigned getRangeValue(const T &v, const RangeSpec &r) { - using VT = details::SameSizeUnsigned; - return static_cast(static_cast(v) - static_cast(r.min)); - } - - template::value>::type * = nullptr> - details::SameSizeUnsigned getRangeValue(const T &v, const RangeSpec &r) { - using VT = details::SameSizeUnsigned; - const VT maxUint = (static_cast(1) << r.bitsRequired) - 1; - const T ratio = (v - r.min) / (r.max - r.min); - return static_cast(ratio * static_cast(maxUint)); - } - - 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 = typename std::underlying_type::type; - reinterpret_cast(v) += static_cast(r.min); - } - - template::value>::type * = nullptr> - void setRangeValue(T &v, const RangeSpec &r) { - using UIT = details::SameSizeUnsigned; - const auto intRep = reinterpret_cast(v); - const UIT maxUint = (static_cast(1) << r.bitsRequired) - 1; - v = r.min + (static_cast(intRep) / static_cast(maxUint)) * (r.max - r.min); - } - - template::value>::type * = nullptr> - bool isRangeValid(const T &v, const RangeSpec &r) { - return !(r.min > v || v > r.max); - } - - template::value>::type * = nullptr> - bool isRangeValid(const T &v, const RangeSpec &r) { - using VT = typename std::underlying_type::type; - return !(static_cast(r.min) > static_cast(v) - || static_cast(v) > static_cast(r.max)); - } - } - - namespace ext { - - template - class ValueRange { - public: - - template - constexpr ValueRange(const TValue& min, const TValue& max, Args &&... args) - :_range{min, max, std::forward(args)...} {} - - template - void serialize(Ser &ser, const T &v, Fnc &&) const { - assert(details::isRangeValid(v, _range)); - using BT = decltype(details::getRangeValue(v, _range)); - ser.adapter().template writeBits(details::getRangeValue(v, _range), _range.bitsRequired); - } - - template - void deserialize(Des &des, T &v, Fnc &&) const { - auto& reader = des.adapter(); - reader.readBits(reinterpret_cast &>(v), _range.bitsRequired); - details::setRangeValue(v, _range); - handleInvalidRange(reader, v, std::integral_constant{}); - } - - constexpr size_t getRequiredBits() const { - return _range.bitsRequired; - }; - private: - - template - void handleInvalidRange(Reader& reader, T& v, std::true_type) const { - if (!details::isRangeValid(v, _range)) { - reader.error(ReaderError::InvalidData); - v = _range.min; - } - } - - template - void handleInvalidRange(Reader&, T&, std::false_type) const { - } - - details::RangeSpec _range; - }; - } - - namespace traits { - template - struct ExtensionTraits, T> { - using TValue = void; - static constexpr bool SupportValueOverload = false; - static constexpr bool SupportObjectOverload = true; - static constexpr bool SupportLambdaOverload = false; - }; - } +namespace traits { +template +struct ExtensionTraits, T> +{ + using TValue = void; + static constexpr bool SupportValueOverload = false; + static constexpr bool SupportObjectOverload = true; + static constexpr bool SupportLambdaOverload = false; +}; +} } - -#endif //BITSERY_EXT_VALUE_RANGE_H +#endif // BITSERY_EXT_VALUE_RANGE_H diff --git a/include/bitsery/serializer.h b/include/bitsery/serializer.h index 8e71f9b..d93f1de 100644 --- a/include/bitsery/serializer.h +++ b/include/bitsery/serializer.h @@ -1,25 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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 @@ -29,394 +28,553 @@ namespace bitsery { - template - class Serializer: public details::AdapterAndContextRef { - public: - //helper type, that always returns bit-packing enabled type, useful inside serialize function when enabling bitpacking - using BPEnabledType = Serializer; - using TConfig = typename TOutputAdapter::TConfig; - - using details::AdapterAndContextRef::AdapterAndContextRef; - - /* - * object function - */ - template - void object(const T &obj) { - details::SerializeFunction::invoke(*this, const_cast(obj)); - } - - template - void object(const T &obj, Fnc &&fnc) { - fnc(*this, const_cast(obj)); - } - - /* - * functionality, that enables simpler serialization syntax, by including additional header - */ - - template - Serializer &operator()(TArgs &&... args) { - archive(std::forward(args)...); - return *this; - } - - /* - * value overloads - */ - - template - void value(const T &v) { - static_assert(details::IsFundamentalType::value, "Value must be integral, float or enum type."); - using TValue = typename details::IntegralFromFundamental::TValue; - this->_adapter.template writeBytes(reinterpret_cast(v)); - } - - /* - * enable bit-packing - */ - template - void enableBitPacking(Fnc&& fnc) { - procEnableBitPacking(std::forward(fnc), - std::is_same{}, - std::integral_constant{}); - } - - /* - * extension functions - */ - - template - void ext(const T &obj, const Ext &extension, Fnc &&fnc) { - static_assert(details::IsExtensionTraitsDefined::value, "Please define ExtensionTraits"); - static_assert(traits::ExtensionTraits::SupportLambdaOverload, - "extension doesn't support overload with lambda"); - extension.serialize(*this, obj, std::forward(fnc)); - } - - template - void ext(const T &obj, const Ext &extension) { - static_assert(details::IsExtensionTraitsDefined::value, "Please define ExtensionTraits"); - static_assert(traits::ExtensionTraits::SupportValueOverload, - "extension doesn't support overload with `value`"); - using ExtVType = typename traits::ExtensionTraits::TValue; - using VType = typename std::conditional::value, details::DummyType, ExtVType>::type; - extension.serialize(*this, obj, [](Serializer& s, VType &v) { s.value(v); }); - } - - template - void ext(const T &obj, const Ext &extension) { - static_assert(details::IsExtensionTraitsDefined::value, "Please define ExtensionTraits"); - static_assert(traits::ExtensionTraits::SupportObjectOverload, - "extension doesn't support overload with `object`"); - using ExtVType = typename traits::ExtensionTraits::TValue; - using VType = typename std::conditional::value, details::DummyType, ExtVType>::type; - extension.serialize(*this, obj, [](Serializer& s, VType &v) { s.object(v); }); - } - - /* - * boolValue - */ - - void boolValue(bool v) { - procBoolValue(v, std::is_same{}); - } - - /* - * text overloads - */ - - template - void text(const T &str, size_t maxSize) { - static_assert(details::IsTextTraitsDefined::value, - "Please define TextTraits or include from "); - static_assert(traits::ContainerTraits::isResizable, - "use text(const T&) overload without `maxSize` for static container"); - procText(str, maxSize); - } - - template - void text(const T &str) { - static_assert(details::IsTextTraitsDefined::value, - "Please define TextTraits or include from "); - static_assert(!traits::ContainerTraits::isResizable, - "use text(const T&, size_t) overload with `maxSize` for dynamic containers"); - procText(str, traits::ContainerTraits::size(str)); - } - - /* - * container overloads - */ - - //dynamic size containers - - template - void container(const T &obj, size_t maxSize, Fnc &&fnc) { - static_assert(details::IsContainerTraitsDefined::value, - "Please define ContainerTraits or include from "); - static_assert(traits::ContainerTraits::isResizable, - "use container(const T&, Fnc) overload without `maxSize` for static containers"); - auto size = traits::ContainerTraits::size(obj); - (void)maxSize; // unused in release - assert(size <= maxSize); - details::writeSize(this->_adapter, size); - procContainer(std::begin(obj), std::end(obj), std::forward(fnc)); - } - - template - void container(const T &obj, size_t maxSize) { - static_assert(details::IsContainerTraitsDefined::value, - "Please define ContainerTraits or include from "); - static_assert(traits::ContainerTraits::isResizable, - "use container(const T&) overload without `maxSize` for static containers"); - static_assert(VSIZE > 0, ""); - auto size = traits::ContainerTraits::size(obj); - (void)maxSize; // unused in release - assert(size <= maxSize); - details::writeSize(this->_adapter, size); - - procContainer(std::begin(obj), std::end(obj), std::integral_constant::isContiguous>{}); - } - - template - void container(const T &obj, size_t maxSize) { - static_assert(details::IsContainerTraitsDefined::value, - "Please define ContainerTraits or include from "); - static_assert(traits::ContainerTraits::isResizable, - "use container(const T&) overload without `maxSize` for static containers"); - auto size = traits::ContainerTraits::size(obj); - (void)maxSize; // unused in release - assert(size <= maxSize); - details::writeSize(this->_adapter, size); - procContainer(std::begin(obj), std::end(obj)); - } - - //fixed size containers - - template::value>::type * = nullptr> - void container(const T &obj, Fnc &&fnc) { - static_assert(details::IsContainerTraitsDefined::value, - "Please define ContainerTraits or include from "); - static_assert(!traits::ContainerTraits::isResizable, - "use container(const T&, size_t, Fnc) overload with `maxSize` for dynamic containers"); - procContainer(std::begin(obj), std::end(obj), std::forward(fnc)); - } - - template - void container(const T &obj) { - static_assert(details::IsContainerTraitsDefined::value, - "Please define ContainerTraits or include from "); - static_assert(!traits::ContainerTraits::isResizable, - "use container(const T&, size_t) overload with `maxSize` for dynamic containers"); - static_assert(VSIZE > 0, ""); - procContainer(std::begin(obj), std::end(obj), std::integral_constant::isContiguous>{}); - } - - template - void container(const T &obj) { - static_assert(details::IsContainerTraitsDefined::value, - "Please define ContainerTraits or include from "); - static_assert(!traits::ContainerTraits::isResizable, - "use container(const T&, size_t) overload with `maxSize` for dynamic containers"); - procContainer(std::begin(obj), std::end(obj)); - } - - //overloads for functions with explicit type size - - template - void value1b(T &&v) { value<1>(std::forward(v)); } - - template - void value2b(T &&v) { value<2>(std::forward(v)); } - - template - void value4b(T &&v) { value<4>(std::forward(v)); } - - template - void value8b(T &&v) { value<8>(std::forward(v)); } - - template - void value16b(T &&v) { value<16>(std::forward(v)); } - - template - void ext1b(const T &v, Ext &&extension) { ext<1, T, Ext>(v, std::forward(extension)); } - - template - void ext2b(const T &v, Ext &&extension) { ext<2, T, Ext>(v, std::forward(extension)); } - - template - void ext4b(const T &v, Ext &&extension) { ext<4, T, Ext>(v, std::forward(extension)); } - - template - void ext8b(const T &v, Ext &&extension) { ext<8, T, Ext>(v, std::forward(extension)); } - - template - void ext16b(const T &v, Ext &&extension) { ext<16, T, Ext>(v, std::forward(extension)); } - - template - void text1b(const T &str, size_t maxSize) { text<1>(str, maxSize); } - - template - void text2b(const T &str, size_t maxSize) { text<2>(str, maxSize); } - - template - void text4b(const T &str, size_t maxSize) { text<4>(str, maxSize); } - - template - void text1b(const T &str) { text<1>(str); } - - template - void text2b(const T &str) { text<2>(str); } - - template - void text4b(const T &str) { text<4>(str); } - - template - void container1b(T &&obj, size_t maxSize) { container<1>(std::forward(obj), maxSize); } - - template - void container2b(T &&obj, size_t maxSize) { container<2>(std::forward(obj), maxSize); } - - template - void container4b(T &&obj, size_t maxSize) { container<4>(std::forward(obj), maxSize); } - - template - void container8b(T &&obj, size_t maxSize) { container<8>(std::forward(obj), maxSize); } - - template - void container16b(T &&obj, size_t maxSize) { container<16>(std::forward(obj), maxSize); } - - template - void container1b(T &&obj) { container<1>(std::forward(obj)); } - - template - void container2b(T &&obj) { container<2>(std::forward(obj)); } - - template - void container4b(T &&obj) { container<4>(std::forward(obj)); } - - template - void container8b(T &&obj) { container<8>(std::forward(obj)); } - - template - void container16b(T &&obj) { container<16>(std::forward(obj)); } - - - private: - - //process value types - //false_type means that we must process all elements individually - template - void procContainer(It first, It last, std::false_type) { - for (; first != last; ++first) - value(*first); - } - - //process value types - //true_type means, that we can copy whole buffer - template - void procContainer(It first, It last, std::true_type) { - using TValue = typename std::decay::type; - using TIntegral = typename details::IntegralFromFundamental::TValue; - if (first != last) - this->_adapter.template writeBuffer(reinterpret_cast(&(*first)), - static_cast(std::distance(first, last))); - } - - //process by calling functions - template - void procContainer(It first, It last, Fnc fnc) { - using TValue = typename std::decay::type; - for (; first != last; ++first) { - fnc(*this, const_cast(*first)); - } - } - - //process text, - template - void procText(const T& str, size_t maxSize) { - const size_t length = traits::TextTraits::length(str); - (void)maxSize; // unused in release - assert((length + (traits::TextTraits::addNUL ? 1u : 0u)) <= maxSize); - details::writeSize(this->_adapter, length); - auto begin = std::begin(str); - using diff_t = typename std::iterator_traits::difference_type; - procContainer(begin, std::next(begin, static_cast(length)), std::integral_constant::isContiguous>{}); - } - - //process object types - template - void procContainer(It first, It last) { - for (; first != last; ++first) - object(*first); - } - - //proc bool writing bit or byte, depending on if BitPackingEnabled or not - void procBoolValue(bool v, std::true_type) { - this->_adapter.writeBits(static_cast(v ? 1 : 0), 1); - } - - void procBoolValue(bool v, std::false_type) { - this->_adapter.template writeBytes<1>(static_cast(v ? 1 : 0)); - } - - //enable bit-packing or do nothing if it is already enabled - template - void procEnableBitPacking(const Fnc& fnc, std::true_type, HasContext) { - fnc(*this); - } - - template - void procEnableBitPacking(const Fnc& fnc, std::false_type, std::true_type) { - BPEnabledType ser{this->_context, this->_adapter}; - fnc(ser); - } - - template - void procEnableBitPacking(const Fnc& fnc, std::false_type, std::false_type) { - BPEnabledType ser{this->_adapter}; - fnc(ser); - } - - //these are dummy functions for extensions that have TValue = void - void object(const details::DummyType&) { - - } - - template - void value(const details::DummyType&) { - - } - - template - void archive(T &&head, TArgs &&... tail) { - //serialize object - details::BriefSyntaxFunction::invoke(*this, std::forward(head)); - //expand other elements - archive(std::forward(tail)...); - } - //dummy function, that stops archive variadic arguments expansion - void archive() { - } - - }; - - //helper function that set ups all the basic steps and after serialziation returns serialized bytes count - template - size_t quickSerialization(OutputAdapter adapter, const T& value) { - Serializer ser{std::move(adapter)}; - ser.object(value); - ser.adapter().flush(); - return ser.adapter().writtenBytesCount(); +template +class Serializer + : public details::AdapterAndContextRef +{ +public: + // helper type, that always returns bit-packing enabled type, useful inside + // serialize function when enabling bitpacking + using BPEnabledType = + Serializer; + using TConfig = typename TOutputAdapter::TConfig; + + using details::AdapterAndContextRef::AdapterAndContextRef; + + /* + * object function + */ + template + void object(const T& obj) + { + details::SerializeFunction::invoke(*this, + const_cast(obj)); + } + + template + void object(const T& obj, Fnc&& fnc) + { + fnc(*this, const_cast(obj)); + } + + /* + * functionality, that enables simpler serialization syntax, by including + * additional header + */ + + template + Serializer& operator()(TArgs&&... args) + { + archive(std::forward(args)...); + return *this; + } + + /* + * value overloads + */ + + template + void value(const T& v) + { + static_assert(details::IsFundamentalType::value, + "Value must be integral, float or enum type."); + using TValue = typename details::IntegralFromFundamental::TValue; + this->_adapter.template writeBytes( + reinterpret_cast(v)); + } + + /* + * enable bit-packing + */ + template + void enableBitPacking(Fnc&& fnc) + { + procEnableBitPacking( + std::forward(fnc), + std::is_same{}, + std::integral_constant{}); + } + + /* + * extension functions + */ + + template + void ext(const T& obj, const Ext& extension, Fnc&& fnc) + { + static_assert(details::IsExtensionTraitsDefined::value, + "Please define ExtensionTraits"); + static_assert(traits::ExtensionTraits::SupportLambdaOverload, + "extension doesn't support overload with lambda"); + extension.serialize(*this, obj, std::forward(fnc)); + } + + template + void ext(const T& obj, const Ext& extension) + { + static_assert(details::IsExtensionTraitsDefined::value, + "Please define ExtensionTraits"); + static_assert(traits::ExtensionTraits::SupportValueOverload, + "extension doesn't support overload with `value`"); + using ExtVType = typename traits::ExtensionTraits::TValue; + using VType = typename std::conditional::value, + details::DummyType, + ExtVType>::type; + extension.serialize( + *this, obj, [](Serializer& s, VType& v) { s.value(v); }); + } + + template + void ext(const T& obj, const Ext& extension) + { + static_assert(details::IsExtensionTraitsDefined::value, + "Please define ExtensionTraits"); + static_assert(traits::ExtensionTraits::SupportObjectOverload, + "extension doesn't support overload with `object`"); + using ExtVType = typename traits::ExtensionTraits::TValue; + using VType = typename std::conditional::value, + details::DummyType, + ExtVType>::type; + extension.serialize( + *this, obj, [](Serializer& s, VType& v) { s.object(v); }); + } + + /* + * boolValue + */ + + void boolValue(bool v) + { + procBoolValue(v, + std::is_same{}); + } + + /* + * text overloads + */ + + template + void text(const T& str, size_t maxSize) + { + static_assert( + details::IsTextTraitsDefined::value, + "Please define TextTraits or include from "); + static_assert( + traits::ContainerTraits::isResizable, + "use text(const T&) overload without `maxSize` for static container"); + procText(str, maxSize); + } + + template + void text(const T& str) + { + static_assert( + details::IsTextTraitsDefined::value, + "Please define TextTraits or include from "); + static_assert(!traits::ContainerTraits::isResizable, + "use text(const T&, size_t) overload with `maxSize` for " + "dynamic containers"); + procText(str, traits::ContainerTraits::size(str)); + } + + /* + * container overloads + */ + + // dynamic size containers + + template + void container(const T& obj, size_t maxSize, Fnc&& fnc) + { + static_assert( + details::IsContainerTraitsDefined::value, + "Please define ContainerTraits or include from "); + static_assert(traits::ContainerTraits::isResizable, + "use container(const T&, Fnc) overload without `maxSize` for " + "static containers"); + auto size = traits::ContainerTraits::size(obj); + (void)maxSize; // unused in release + assert(size <= maxSize); + details::writeSize(this->_adapter, size); + procContainer(std::begin(obj), std::end(obj), std::forward(fnc)); + } + + template + void container(const T& obj, size_t maxSize) + { + static_assert( + details::IsContainerTraitsDefined::value, + "Please define ContainerTraits or include from "); + static_assert(traits::ContainerTraits::isResizable, + "use container(const T&) overload without `maxSize` for " + "static containers"); + static_assert(VSIZE > 0, ""); + auto size = traits::ContainerTraits::size(obj); + (void)maxSize; // unused in release + assert(size <= maxSize); + details::writeSize(this->_adapter, size); + + procContainer( + std::begin(obj), + std::end(obj), + std::integral_constant::isContiguous>{}); + } + + template + void container(const T& obj, size_t maxSize) + { + static_assert( + details::IsContainerTraitsDefined::value, + "Please define ContainerTraits or include from "); + static_assert(traits::ContainerTraits::isResizable, + "use container(const T&) overload without `maxSize` for " + "static containers"); + auto size = traits::ContainerTraits::size(obj); + (void)maxSize; // unused in release + assert(size <= maxSize); + details::writeSize(this->_adapter, size); + procContainer(std::begin(obj), std::end(obj)); + } + + // fixed size containers + + template< + typename T, + typename Fnc, + typename std::enable_if::value>::type* = nullptr> + void container(const T& obj, Fnc&& fnc) + { + static_assert( + details::IsContainerTraitsDefined::value, + "Please define ContainerTraits or include from "); + static_assert(!traits::ContainerTraits::isResizable, + "use container(const T&, size_t, Fnc) overload with " + "`maxSize` for dynamic containers"); + procContainer(std::begin(obj), std::end(obj), std::forward(fnc)); + } + + template + void container(const T& obj) + { + static_assert( + details::IsContainerTraitsDefined::value, + "Please define ContainerTraits or include from "); + static_assert(!traits::ContainerTraits::isResizable, + "use container(const T&, size_t) overload with `maxSize` for " + "dynamic containers"); + static_assert(VSIZE > 0, ""); + procContainer( + std::begin(obj), + std::end(obj), + std::integral_constant::isContiguous>{}); + } + + template + void container(const T& obj) + { + static_assert( + details::IsContainerTraitsDefined::value, + "Please define ContainerTraits or include from "); + static_assert(!traits::ContainerTraits::isResizable, + "use container(const T&, size_t) overload with `maxSize` for " + "dynamic containers"); + procContainer(std::begin(obj), std::end(obj)); + } + + // overloads for functions with explicit type size + + template + void value1b(T&& v) + { + value<1>(std::forward(v)); + } + + template + void value2b(T&& v) + { + value<2>(std::forward(v)); + } + + template + void value4b(T&& v) + { + value<4>(std::forward(v)); + } + + template + void value8b(T&& v) + { + value<8>(std::forward(v)); + } + + template + void value16b(T&& v) + { + value<16>(std::forward(v)); + } + + template + void ext1b(const T& v, Ext&& extension) + { + ext<1, T, Ext>(v, std::forward(extension)); + } + + template + void ext2b(const T& v, Ext&& extension) + { + ext<2, T, Ext>(v, std::forward(extension)); + } + + template + void ext4b(const T& v, Ext&& extension) + { + ext<4, T, Ext>(v, std::forward(extension)); + } + + template + void ext8b(const T& v, Ext&& extension) + { + ext<8, T, Ext>(v, std::forward(extension)); + } + + template + void ext16b(const T& v, Ext&& extension) + { + ext<16, T, Ext>(v, std::forward(extension)); + } + + template + void text1b(const T& str, size_t maxSize) + { + text<1>(str, maxSize); + } + + template + void text2b(const T& str, size_t maxSize) + { + text<2>(str, maxSize); + } + + template + void text4b(const T& str, size_t maxSize) + { + text<4>(str, maxSize); + } + + template + void text1b(const T& str) + { + text<1>(str); + } + + template + void text2b(const T& str) + { + text<2>(str); + } + + template + void text4b(const T& str) + { + text<4>(str); + } + + template + void container1b(T&& obj, size_t maxSize) + { + container<1>(std::forward(obj), maxSize); + } + + template + void container2b(T&& obj, size_t maxSize) + { + container<2>(std::forward(obj), maxSize); + } + + template + void container4b(T&& obj, size_t maxSize) + { + container<4>(std::forward(obj), maxSize); + } + + template + void container8b(T&& obj, size_t maxSize) + { + container<8>(std::forward(obj), maxSize); + } + + template + void container16b(T&& obj, size_t maxSize) + { + container<16>(std::forward(obj), maxSize); + } + + template + void container1b(T&& obj) + { + container<1>(std::forward(obj)); + } + + template + void container2b(T&& obj) + { + container<2>(std::forward(obj)); + } + + template + void container4b(T&& obj) + { + container<4>(std::forward(obj)); + } + + template + void container8b(T&& obj) + { + container<8>(std::forward(obj)); + } + + template + void container16b(T&& obj) + { + container<16>(std::forward(obj)); + } + +private: + // process value types + // false_type means that we must process all elements individually + template + void procContainer(It first, It last, std::false_type) + { + for (; first != last; ++first) + value(*first); + } + + // process value types + // true_type means, that we can copy whole buffer + template + void procContainer(It first, It last, std::true_type) + { + using TValue = typename std::decay::type; + using TIntegral = typename details::IntegralFromFundamental::TValue; + if (first != last) + this->_adapter.template writeBuffer( + reinterpret_cast(&(*first)), + static_cast(std::distance(first, last))); + } + + // process by calling functions + template + void procContainer(It first, It last, Fnc fnc) + { + using TValue = typename std::decay::type; + for (; first != last; ++first) { + fnc(*this, const_cast(*first)); } + } - template - size_t quickSerialization(Context& ctx, OutputAdapter adapter, const T& value) { - Serializer ser{ctx, std::move(adapter)}; - ser.object(value); - ser.adapter().flush(); - return ser.adapter().writtenBytesCount(); - } + // process text, + template + void procText(const T& str, size_t maxSize) + { + const size_t length = traits::TextTraits::length(str); + (void)maxSize; // unused in release + assert((length + (traits::TextTraits::addNUL ? 1u : 0u)) <= maxSize); + details::writeSize(this->_adapter, length); + auto begin = std::begin(str); + using diff_t = + typename std::iterator_traits::difference_type; + procContainer( + begin, + std::next(begin, static_cast(length)), + std::integral_constant::isContiguous>{}); + } + + // process object types + template + void procContainer(It first, It last) + { + for (; first != last; ++first) + object(*first); + } + + // proc bool writing bit or byte, depending on if BitPackingEnabled or not + void procBoolValue(bool v, std::true_type) + { + this->_adapter.writeBits(static_cast(v ? 1 : 0), 1); + } + + void procBoolValue(bool v, std::false_type) + { + this->_adapter.template writeBytes<1>( + static_cast(v ? 1 : 0)); + } + + // enable bit-packing or do nothing if it is already enabled + template + void procEnableBitPacking(const Fnc& fnc, std::true_type, HasContext) + { + fnc(*this); + } + + template + void procEnableBitPacking(const Fnc& fnc, std::false_type, std::true_type) + { + BPEnabledType ser{ this->_context, this->_adapter }; + fnc(ser); + } + + template + void procEnableBitPacking(const Fnc& fnc, std::false_type, std::false_type) + { + BPEnabledType ser{ this->_adapter }; + fnc(ser); + } + + // these are dummy functions for extensions that have TValue = void + void object(const details::DummyType&) {} + + template + void value(const details::DummyType&) + { + } + + template + void archive(T&& head, TArgs&&... tail) + { + // serialize object + details::BriefSyntaxFunction::invoke(*this, + std::forward(head)); + // expand other elements + archive(std::forward(tail)...); + } + // dummy function, that stops archive variadic arguments expansion + void archive() {} +}; + +// helper function that set ups all the basic steps and after serialziation +// returns serialized bytes count +template +size_t +quickSerialization(OutputAdapter adapter, const T& value) +{ + Serializer ser{ std::move(adapter) }; + ser.object(value); + ser.adapter().flush(); + return ser.adapter().writtenBytesCount(); +} + +template +size_t +quickSerialization(Context& ctx, OutputAdapter adapter, const T& value) +{ + Serializer ser{ ctx, std::move(adapter) }; + ser.object(value); + ser.adapter().flush(); + return ser.adapter().writtenBytesCount(); +} } -#endif //BITSERY_SERIALIZER_H +#endif // BITSERY_SERIALIZER_H diff --git a/include/bitsery/traits/array.h b/include/bitsery/traits/array.h index f43b2b7..acc28f2 100644 --- a/include/bitsery/traits/array.h +++ b/include/bitsery/traits/array.h @@ -1,25 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_TRAITS_STD_ARRAY_H #define BITSERY_TRAITS_STD_ARRAY_H @@ -29,16 +28,20 @@ namespace bitsery { - namespace traits { - template - struct ContainerTraits> - :public StdContainer, false, true> {}; +namespace traits { +template +struct ContainerTraits> + : public StdContainer, false, true> +{ +}; - template - struct BufferAdapterTraits> - :public StdContainerForBufferAdapter> {}; - } +template +struct BufferAdapterTraits> + : public StdContainerForBufferAdapter> +{ +}; +} } -#endif //BITSERY_TYPE_TRAITS_STD_ARRAY_H +#endif // BITSERY_TYPE_TRAITS_STD_ARRAY_H diff --git a/include/bitsery/traits/core/std_defaults.h b/include/bitsery/traits/core/std_defaults.h index 564061b..20cd5ef 100644 --- a/include/bitsery/traits/core/std_defaults.h +++ b/include/bitsery/traits/core/std_defaults.h @@ -1,104 +1,114 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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_TRAITS_CORE_STD_DEFAULTS_H #define BITSERY_TRAITS_CORE_STD_DEFAULTS_H -#include "traits.h" #include "../../details/serialization_common.h" +#include "traits.h" namespace bitsery { - namespace traits { +namespace traits { - /* - * these are helper types, to easier write specializations for std types - */ +/* + * these are helper types, to easier write specializations for std types + */ - template - struct StdContainer { - using TValue = typename T::value_type; - static constexpr bool isResizable = Resizable; - static constexpr bool isContiguous = Contiguous; - static size_t size(const T& container) { - return container.size(); - } - }; +template +struct StdContainer +{ + using TValue = typename T::value_type; + static constexpr bool isResizable = Resizable; + static constexpr bool isContiguous = Contiguous; + static size_t size(const T& container) { return container.size(); } +}; - //specialization for resizable - template - struct StdContainer { - using TValue = typename T::value_type; - static constexpr bool isResizable = true; - static constexpr bool isContiguous = Contiguous; - static size_t size(const T& container) { - return container.size(); - } - static void resize(T& container, size_t size) { - resizeImpl(container, size, std::is_default_constructible{}); - } - private: - using diff_t = typename T::difference_type; +// specialization for resizable +template +struct StdContainer +{ + using TValue = typename T::value_type; + static constexpr bool isResizable = true; + static constexpr bool isContiguous = Contiguous; + static size_t size(const T& container) { return container.size(); } + static void resize(T& container, size_t size) + { + resizeImpl(container, size, std::is_default_constructible{}); + } - static void resizeImpl(T& container, size_t size, std::true_type) { - container.resize(size); - } - static void resizeImpl(T& container, size_t newSize, std::false_type) { - const auto oldSize = size(container); - for (auto it = oldSize; it < newSize; ++it) { - container.push_back(::bitsery::Access::create()); - } - if (oldSize > newSize) { - container.erase(std::next(std::begin(container), static_cast(newSize)), std::end(container)); - } - } - - }; - - template ::isResizable> - struct StdContainerForBufferAdapter { - using TIterator = typename T::iterator; - using TConstIterator = typename T::const_iterator; - using TValue = typename ContainerTraits::TValue; - }; - - //specialization for resizable buffers - template - struct StdContainerForBufferAdapter { - using TIterator = typename T::iterator; - using TConstIterator = typename T::const_iterator; - using TValue = typename ContainerTraits::TValue; - - - static void increaseBufferSize(T& container, size_t /*currSize*/, size_t minSize) { - //since we're writing to buffer use different resize strategy than default implementation - //when small size grow faster, to avoid thouse 2/4/8/16... byte allocations - auto newSize = static_cast(static_cast(container.size()) * 1.5) + 128; - //make data cache friendly - newSize -= newSize % 64;//64 is cache line size - container.resize((std::max)(newSize > minSize ? newSize : minSize, container.capacity())); - } - }; +private: + using diff_t = typename T::difference_type; + static void resizeImpl(T& container, size_t size, std::true_type) + { + container.resize(size); + } + static void resizeImpl(T& container, size_t newSize, std::false_type) + { + const auto oldSize = size(container); + for (auto it = oldSize; it < newSize; ++it) { + container.push_back(::bitsery::Access::create()); } + if (oldSize > newSize) { + container.erase( + std::next(std::begin(container), static_cast(newSize)), + std::end(container)); + } + } +}; + +template::isResizable> +struct StdContainerForBufferAdapter +{ + using TIterator = typename T::iterator; + using TConstIterator = typename T::const_iterator; + using TValue = typename ContainerTraits::TValue; +}; + +// specialization for resizable buffers +template +struct StdContainerForBufferAdapter +{ + using TIterator = typename T::iterator; + using TConstIterator = typename T::const_iterator; + using TValue = typename ContainerTraits::TValue; + + static void increaseBufferSize(T& container, + size_t /*currSize*/, + size_t minSize) + { + // since we're writing to buffer use different resize strategy than default + // implementation when small size grow faster, to avoid thouse 2/4/8/16... + // byte allocations + auto newSize = + static_cast(static_cast(container.size()) * 1.5) + 128; + // make data cache friendly + newSize -= newSize % 64; // 64 is cache line size + container.resize( + (std::max)(newSize > minSize ? newSize : minSize, container.capacity())); + } +}; + +} } -#endif //BITSERY_TRAITS_CORE_STD_DEFAULTS_H +#endif // BITSERY_TRAITS_CORE_STD_DEFAULTS_H diff --git a/include/bitsery/traits/core/traits.h b/include/bitsery/traits/core/traits.h index f6fbcbe..38d1a26 100644 --- a/include/bitsery/traits/core/traits.h +++ b/include/bitsery/traits/core/traits.h @@ -1,188 +1,208 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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_TRAITS_CORE_TRAITS_H #define BITSERY_TRAITS_CORE_TRAITS_H -#include #include "../../details/not_defined_type.h" +#include namespace bitsery { - namespace traits { +namespace traits { - /* - * core library traits, used to extend library for custom types - */ +/* + * core library traits, used to extend library for custom types + */ - //traits for extension - template - struct ExtensionTraits { - //this type is used, when using extesion without custom lambda - // eg.: extension4b>(obj, myextension{}) will call s.value4b(obj) for TValue - // or extesion(obj, myextension{}) will call s.object(obj) for TValue - //when this is void, it will compile, but value and object overloads will do nothing. - using TValue = details::NotDefinedType; +// traits for extension +template +struct ExtensionTraits +{ + // this type is used, when using extesion without custom lambda + // eg.: extension4b>(obj, myextension{}) will call s.value4b(obj) for TValue + // or extesion(obj, myextension{}) will call s.object(obj) for TValue + // when this is void, it will compile, but value and object overloads will do + // nothing. + using TValue = details::NotDefinedType; - //does extension support ext(...) syntax, by calling value with TValue - static constexpr bool SupportValueOverload = false; - //does extension support ext(...) syntax, by calling object with TValue - static constexpr bool SupportObjectOverload = false; - //does extension support ext(..., lambda) - static constexpr bool SupportLambdaOverload = false; - }; + // does extension support ext(...) syntax, by calling value with TValue + static constexpr bool SupportValueOverload = false; + // does extension support ext(...) syntax, by calling object with TValue + static constexpr bool SupportObjectOverload = false; + // does extension support ext(..., lambda) + static constexpr bool SupportLambdaOverload = false; +}; - //primary traits for containers - template - struct ContainerTraits { +// primary traits for containers +template +struct ContainerTraits +{ - using TValue = details::NotDefinedType; + using TValue = details::NotDefinedType; - static constexpr bool isResizable = false; - //contiguous arrays has oppurtunity to memcpy whole buffer directly when using funtamental types - //contiguous doesn't nesessary equal to random access iterator. - //contiguous hopefully will be available in c++20 - static constexpr bool isContiguous = false; - //resize function, called only if container is resizable - static void resize(T& , size_t ) { - static_assert(std::is_void::value, - "Define ContainerTraits or include from to use as container"); - } - //get container size - static size_t size(const T& ) { - static_assert(std::is_void::value, - "Define ContainerTraits or include from to use as container"); - return 0u; - } - }; + static constexpr bool isResizable = false; + // contiguous arrays has oppurtunity to memcpy whole buffer directly when + // using funtamental types contiguous doesn't nesessary equal to random access + // iterator. contiguous hopefully will be available in c++20 + static constexpr bool isContiguous = false; + // resize function, called only if container is resizable + static void resize(T&, size_t) + { + static_assert(std::is_void::value, + "Define ContainerTraits or include from " + "to use as container"); + } + // get container size + static size_t size(const T&) + { + static_assert(std::is_void::value, + "Define ContainerTraits or include from " + "to use as container"); + return 0u; + } +}; - //specialization for C style array - template - struct ContainerTraits { - using TValue = T; - static constexpr bool isResizable = false; - static constexpr bool isContiguous = true; - static size_t size(const T (&)[N]) { - return N; - } - }; +// specialization for C style array +template +struct ContainerTraits +{ + using TValue = T; + static constexpr bool isResizable = false; + static constexpr bool isContiguous = true; + static size_t size(const T (&)[N]) { return N; } +}; - //specialization for initializer list. - //only serializer can use it - template - struct ContainerTraits> { - using TValue = T; - static constexpr bool isResizable = false; - static constexpr bool isContiguous = true; - static size_t size(const std::initializer_list& container) { - return container.size(); - } - }; +// specialization for initializer list. +// only serializer can use it +template +struct ContainerTraits> +{ + using TValue = T; + static constexpr bool isResizable = false; + static constexpr bool isContiguous = true; + static size_t size(const std::initializer_list& container) + { + return container.size(); + } +}; - //specialization for pointer type buffer - //only deserializer can use it - template - struct ContainerTraits { - using TValue = T; - static constexpr bool isResizable = false; - static constexpr bool isContiguous = true; - static size_t size(const T* ) { - static_assert(std::is_void::value, "cannot get size for container of type T*"); - return 0u; - } - }; +// specialization for pointer type buffer +// only deserializer can use it +template +struct ContainerTraits +{ + using TValue = T; + static constexpr bool isResizable = false; + static constexpr bool isContiguous = true; + static size_t size(const T*) + { + static_assert(std::is_void::value, + "cannot get size for container of type T*"); + return 0u; + } +}; - template - struct ContainerTraits { - using TValue = T; - static constexpr bool isResizable = false; - static constexpr bool isContiguous = true; - static size_t size(const T* ) { - static_assert(std::is_void::value, "cannot get size for container of type T*"); - return 0u; - } - }; +template +struct ContainerTraits +{ + using TValue = T; + static constexpr bool isResizable = false; + static constexpr bool isContiguous = true; + static size_t size(const T*) + { + static_assert(std::is_void::value, + "cannot get size for container of type T*"); + return 0u; + } +}; +// traits for text, default adds null-terminated character at the end +template +struct TextTraits +{ + using TValue = details::NotDefinedType; + // if container is not null-terminated by default, add NUL at the end + static constexpr bool addNUL = true; + // get length of null terminated container + static size_t length(const T&) + { + static_assert( + std::is_void::value, + "Define TextTraits or include from to use as text"); + return 0u; + } +}; - //traits for text, default adds null-terminated character at the end - template - struct TextTraits { - using TValue = details::NotDefinedType; - //if container is not null-terminated by default, add NUL at the end - static constexpr bool addNUL = true; +// traits only for buffer adapters +template +struct BufferAdapterTraits +{ + using TIterator = details::NotDefinedType; + using TConstIterator = details::NotDefinedType; + using TValue = typename ContainerTraits::TValue; - //get length of null terminated container - static size_t length(const T& ) { - static_assert(std::is_void::value, - "Define TextTraits or include from to use as text"); - return 0u; - } - }; + // this function is only applies to resizable containers - //traits only for buffer adapters - template - struct BufferAdapterTraits { - using TIterator = details::NotDefinedType; - using TConstIterator = details::NotDefinedType; - using TValue = typename ContainerTraits::TValue; + // this function is only used by Writer, when writing data to buffer, + // it is called only current buffer size is not enough to write. + // it is used to dramaticaly improve performance by updating buffer directly + // instead of using back_insert_iterator to append each byte to buffer. - //this function is only applies to resizable containers + static void increaseBufferSize(T&, size_t, size_t) + { + static_assert(std::is_void::value, + "Define BufferAdapterTraits or include from " + " to use as buffer adapter container"); + } +}; - //this function is only used by Writer, when writing data to buffer, - //it is called only current buffer size is not enough to write. - //it is used to dramaticaly improve performance by updating buffer directly - //instead of using back_insert_iterator to append each byte to buffer. +// specialization for c-style buffer +template +struct BufferAdapterTraits +{ + using TIterator = T*; + using TConstIterator = const T*; + using TValue = T; +}; - static void increaseBufferSize(T& ,size_t , size_t ) { - static_assert(std::is_void::value, - "Define BufferAdapterTraits or include from to use as buffer adapter container"); - } +// specialization for pointer type buffer +template +struct BufferAdapterTraits +{ + using TIterator = const T*; + using TConstIterator = const T*; + using TValue = T; +}; - }; +template +struct BufferAdapterTraits +{ + using TIterator = T*; + using TConstIterator = const T*; + using TValue = T; +}; - //specialization for c-style buffer - template - struct BufferAdapterTraits { - using TIterator = T*; - using TConstIterator = const T*; - using TValue = T; - }; - - //specialization for pointer type buffer - template - struct BufferAdapterTraits { - using TIterator = const T*; - using TConstIterator = const T*; - using TValue = T; - }; - - template - struct BufferAdapterTraits { - using TIterator = T*; - using TConstIterator = const T*; - using TValue = T; - }; - - } +} } -#endif //BITSERY_TRAITS_CORE_TRAITS_H +#endif // BITSERY_TRAITS_CORE_TRAITS_H diff --git a/include/bitsery/traits/deque.h b/include/bitsery/traits/deque.h index 23f6626..600e87c 100644 --- a/include/bitsery/traits/deque.h +++ b/include/bitsery/traits/deque.h @@ -1,25 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_TRAITS_STD_DEQUE_H #define BITSERY_TRAITS_STD_DEQUE_H @@ -29,14 +28,16 @@ namespace bitsery { - namespace traits { +namespace traits { - template - struct ContainerTraits> - : public StdContainer, true, false> {}; - - } +template +struct ContainerTraits> + : public StdContainer, true, false> +{ +}; } -#endif //BITSERY_TRAITS_STD_DEQUE_H +} + +#endif // BITSERY_TRAITS_STD_DEQUE_H diff --git a/include/bitsery/traits/forward_list.h b/include/bitsery/traits/forward_list.h index e42458b..10b756b 100644 --- a/include/bitsery/traits/forward_list.h +++ b/include/bitsery/traits/forward_list.h @@ -1,69 +1,79 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_TRAITS_STD_FORWARD_LIST_H #define BITSERY_TRAITS_STD_FORWARD_LIST_H -#include "core/traits.h" #include "../details/serialization_common.h" +#include "core/traits.h" #include namespace bitsery { - namespace traits { +namespace traits { - template - struct ContainerTraits> { - using TValue = T; - static constexpr bool isResizable = true; - static constexpr bool isContiguous = false; - static size_t size(const std::forward_list& container) { - return static_cast(std::distance(container.begin(), container.end())); - } - static void resize(std::forward_list& container, size_t size) { - resizeImpl(container, size, std::is_default_constructible{}); - } - private: - using diff_t = typename std::forward_list::difference_type; - static void resizeImpl(std::forward_list& container, size_t size, std::true_type) { - container.resize(size); - } - static void resizeImpl(std::forward_list& container, size_t newSize, std::false_type) { - const auto oldSize = size(container); - for (auto it = oldSize; it < newSize; ++it) { - container.push_front(::bitsery::Access::create()); - } - if (oldSize > newSize) { - //erase_after must have atleast one element to work - if (newSize > 0) - container.erase_after(std::next(std::begin(container), static_cast(newSize-1))); - else - container.clear(); - } - } - }; +template +struct ContainerTraits> +{ + using TValue = T; + static constexpr bool isResizable = true; + static constexpr bool isContiguous = false; + static size_t size(const std::forward_list& container) + { + return static_cast( + std::distance(container.begin(), container.end())); + } + static void resize(std::forward_list& container, size_t size) + { + resizeImpl(container, size, std::is_default_constructible{}); + } + +private: + using diff_t = typename std::forward_list::difference_type; + static void resizeImpl(std::forward_list& container, + size_t size, + std::true_type) + { + container.resize(size); + } + static void resizeImpl(std::forward_list& container, + size_t newSize, + std::false_type) + { + const auto oldSize = size(container); + for (auto it = oldSize; it < newSize; ++it) { + container.push_front(::bitsery::Access::create()); } + if (oldSize > newSize) { + // erase_after must have atleast one element to work + if (newSize > 0) + container.erase_after( + std::next(std::begin(container), static_cast(newSize - 1))); + else + container.clear(); + } + } +}; +} } - -#endif //BITSERY_TRAITS_STD_FORWARD_LIST_H +#endif // BITSERY_TRAITS_STD_FORWARD_LIST_H diff --git a/include/bitsery/traits/list.h b/include/bitsery/traits/list.h index fc15fdd..0ccb514 100644 --- a/include/bitsery/traits/list.h +++ b/include/bitsery/traits/list.h @@ -1,25 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_TRAITS_STD_LIST_H #define BITSERY_TRAITS_STD_LIST_H @@ -29,14 +28,16 @@ namespace bitsery { - namespace traits { +namespace traits { - template - struct ContainerTraits> - : public StdContainer, true, false> {}; - - } +template +struct ContainerTraits> + : public StdContainer, true, false> +{ +}; } -#endif //BITSERY_TRAITS_STD_LIST_H +} + +#endif // BITSERY_TRAITS_STD_LIST_H diff --git a/include/bitsery/traits/string.h b/include/bitsery/traits/string.h index fe9ce38..22a322d 100644 --- a/include/bitsery/traits/string.h +++ b/include/bitsery/traits/string.h @@ -1,25 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_TRAITS_STD_STRING_H #define BITSERY_TRAITS_STD_STRING_H @@ -29,43 +28,55 @@ namespace bitsery { - namespace traits { +namespace traits { - // specialization for string, because string is already included for std::char_traits +// specialization for string, because string is already included for +// std::char_traits - template - struct ContainerTraits> - :public StdContainer, true, true> {}; +template +struct ContainerTraits> + : public StdContainer, true, true> +{ +}; - template - struct TextTraits> { - using TValue = typename ContainerTraits>::TValue; - //string is automatically null-terminated - static constexpr bool addNUL = false; +template +struct TextTraits> +{ + using TValue = typename ContainerTraits< + std::basic_string>::TValue; + // string is automatically null-terminated + static constexpr bool addNUL = false; - //is is not 100% accurate, but for performance reasons assume that string stores text, not binary data - static size_t length(const std::basic_string& str) { - return str.size(); - } - }; + // is is not 100% accurate, but for performance reasons assume that string + // stores text, not binary data + static size_t length(const std::basic_string& str) + { + return str.size(); + } +}; - //specialization for c-array - template - struct TextTraits { - using TValue = T; - static constexpr bool addNUL = true; +// specialization for c-array +template +struct TextTraits +{ + using TValue = T; + static constexpr bool addNUL = true; - static size_t length(const T (&container)[N]) { - return std::char_traits::length(container); - } - }; + static size_t length(const T (&container)[N]) + { + return std::char_traits::length(container); + } +}; - template - struct BufferAdapterTraits> - :public StdContainerForBufferAdapter> {}; - - } +template +struct BufferAdapterTraits> + : public StdContainerForBufferAdapter< + std::basic_string> +{ +}; } -#endif //BITSERY_TRAITS_VECTOR_H +} + +#endif // BITSERY_TRAITS_VECTOR_H diff --git a/include/bitsery/traits/vector.h b/include/bitsery/traits/vector.h index fdff9e0..9568f7c 100644 --- a/include/bitsery/traits/vector.h +++ b/include/bitsery/traits/vector.h @@ -1,25 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_TRAITS_STD_VECTOR_H #define BITSERY_TRAITS_STD_VECTOR_H @@ -29,22 +28,28 @@ namespace bitsery { - namespace traits { - template - struct ContainerTraits> - :public StdContainer, true, true> {}; +namespace traits { +template +struct ContainerTraits> + : public StdContainer, true, true> +{ +}; - //bool vector is not contiguous, do not copy it directly to buffer - template - struct ContainerTraits> - :public StdContainer, true, false> {}; +// bool vector is not contiguous, do not copy it directly to buffer +template +struct ContainerTraits> + : public StdContainer, true, false> +{ +}; - template - struct BufferAdapterTraits> - :public StdContainerForBufferAdapter> {}; - - } +template +struct BufferAdapterTraits> + : public StdContainerForBufferAdapter> +{ +}; } -#endif //BITSERY_TRAITS_STD_VECTOR_H +} + +#endif // BITSERY_TRAITS_STD_VECTOR_H diff --git a/tests/adapter.cpp b/tests/adapter.cpp index d9d58d3..1c188d2 100644 --- a/tests/adapter.cpp +++ b/tests/adapter.cpp @@ -1,39 +1,38 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. - +// 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 #include +#include #include -#include -#include -#include #include #include +#include +#include +#include #include -//some helper types +// some helper types using Buffer = std::vector; using OutputAdapter = bitsery::OutputBufferAdapter; using InputAdapter = bitsery::InputBufferAdapter; @@ -43,519 +42,562 @@ using bitsery::ReaderError; using testing::Eq; using testing::Ge; -struct DisableAdapterErrorsConfig { - static constexpr bitsery::EndiannessType Endianness = bitsery::DefaultConfig::Endianness; - static constexpr bool CheckAdapterErrors = false; - static constexpr bool CheckDataErrors = true; +struct DisableAdapterErrorsConfig +{ + static constexpr bitsery::EndiannessType Endianness = + bitsery::DefaultConfig::Endianness; + static constexpr bool CheckAdapterErrors = false; + static constexpr bool CheckDataErrors = true; }; -TEST(OutputBuffer, WhenSetWritePositionThenResizeUnderlyingBufferIfRequired) { - //setup data - Buffer buf{}; - OutputAdapter w{buf}; - const auto initialSize = buf.size(); - EXPECT_THAT(buf.size(), Eq(initialSize)); - EXPECT_THAT(w.currentWritePos(), Eq(0)); - w.currentWritePos(initialSize + 10); - EXPECT_THAT(w.currentWritePos(), Eq(initialSize + 10)); - EXPECT_THAT(buf.size(), Ge(initialSize + 10)); +TEST(OutputBuffer, WhenSetWritePositionThenResizeUnderlyingBufferIfRequired) +{ + // setup data + Buffer buf{}; + OutputAdapter w{ buf }; + const auto initialSize = buf.size(); + EXPECT_THAT(buf.size(), Eq(initialSize)); + EXPECT_THAT(w.currentWritePos(), Eq(0)); + w.currentWritePos(initialSize + 10); + EXPECT_THAT(w.currentWritePos(), Eq(initialSize + 10)); + EXPECT_THAT(buf.size(), Ge(initialSize + 10)); } -TEST(OutputBuffer, WhenSettingCurrentPositionBeforeBufferEndThenWrittenBytesCountIsNotAffected) { - //setup data - Buffer buf{}; - OutputAdapter w{buf}; - const auto initialSize = buf.size(); - EXPECT_THAT(buf.size(), Eq(initialSize)); - EXPECT_THAT(w.writtenBytesCount(), Eq(0)); - w.currentWritePos(initialSize + 10); - w.writeBytes<8>(static_cast(1)); - EXPECT_THAT(w.writtenBytesCount(), Eq(initialSize + 10 + 8)); - w.currentWritePos(0); - EXPECT_THAT(w.writtenBytesCount(), Eq(initialSize + 10 + 8)); +TEST( + OutputBuffer, + WhenSettingCurrentPositionBeforeBufferEndThenWrittenBytesCountIsNotAffected) +{ + // setup data + Buffer buf{}; + OutputAdapter w{ buf }; + const auto initialSize = buf.size(); + EXPECT_THAT(buf.size(), Eq(initialSize)); + EXPECT_THAT(w.writtenBytesCount(), Eq(0)); + w.currentWritePos(initialSize + 10); + w.writeBytes<8>(static_cast(1)); + EXPECT_THAT(w.writtenBytesCount(), Eq(initialSize + 10 + 8)); + w.currentWritePos(0); + EXPECT_THAT(w.writtenBytesCount(), Eq(initialSize + 10 + 8)); } -TEST(OutputBuffer, CanWorkWithFixedSizeBuffer) { - //setup data - std::array buf{}; - bitsery::OutputBufferAdapter> w{buf}; - const auto initialSize = buf.size(); - EXPECT_THAT(buf.size(), Eq(initialSize)); - EXPECT_THAT(w.currentWritePos(), Eq(0)); - w.currentWritePos(5); - EXPECT_THAT(w.currentWritePos(), Eq(5)); +TEST(OutputBuffer, CanWorkWithFixedSizeBuffer) +{ + // setup data + std::array buf{}; + bitsery::OutputBufferAdapter> w{ buf }; + const auto initialSize = buf.size(); + EXPECT_THAT(buf.size(), Eq(initialSize)); + EXPECT_THAT(w.currentWritePos(), Eq(0)); + w.currentWritePos(5); + EXPECT_THAT(w.currentWritePos(), Eq(5)); } -TEST(InputBuffer, CorrectlySetsAndGetsCurrentReadPosition) { +TEST(InputBuffer, CorrectlySetsAndGetsCurrentReadPosition) +{ - Buffer buf{}; - buf.resize(100); - InputAdapter r{buf.begin(), 10}; - r.currentReadPos(5); - EXPECT_THAT(r.currentReadPos(), Eq(5)); - r.currentReadPos(0); - EXPECT_THAT(r.currentReadPos(), Eq(0)); - uint8_t tmp; - r.readBytes<1>(tmp); - EXPECT_THAT(r.currentReadPos(), Eq(1)); + Buffer buf{}; + buf.resize(100); + InputAdapter r{ buf.begin(), 10 }; + r.currentReadPos(5); + EXPECT_THAT(r.currentReadPos(), Eq(5)); + r.currentReadPos(0); + EXPECT_THAT(r.currentReadPos(), Eq(0)); + uint8_t tmp; + r.readBytes<1>(tmp); + EXPECT_THAT(r.currentReadPos(), Eq(1)); } +TEST(InputBuffer, WhenSetReadPositionOutOfRangeThenDataOverflow) +{ -TEST(InputBuffer, WhenSetReadPositionOutOfRangeThenDataOverflow) { - - Buffer buf{}; - buf.resize(100); - InputAdapter r{buf.begin(), 10}; - r.currentReadPos(10); - EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); - r.currentReadPos(11); - EXPECT_THAT(r.error(), Eq(ReaderError::DataOverflow)); + Buffer buf{}; + buf.resize(100); + InputAdapter r{ buf.begin(), 10 }; + r.currentReadPos(10); + EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); + r.currentReadPos(11); + EXPECT_THAT(r.error(), Eq(ReaderError::DataOverflow)); } -TEST(InputBuffer, WhenSetReadEndPositionOutOfRangeThenDataOverflow) { - Buffer buf{}; - buf.resize(100); - InputAdapter r{buf.begin(), 10}; - r.currentReadEndPos(11); - EXPECT_THAT(r.error(), Eq(ReaderError::DataOverflow)); +TEST(InputBuffer, WhenSetReadEndPositionOutOfRangeThenDataOverflow) +{ + Buffer buf{}; + buf.resize(100); + InputAdapter r{ buf.begin(), 10 }; + r.currentReadEndPos(11); + EXPECT_THAT(r.error(), Eq(ReaderError::DataOverflow)); } -TEST(InputBuffer, WhenReadEndPositionIsNotSetThenReturnZeroAsBufferEndPosition) { - Buffer buf{}; - buf.resize(100); - InputAdapter r{buf.begin(), 10}; - EXPECT_THAT(r.currentReadEndPos(), Eq(0)); - r.currentReadEndPos(5); - EXPECT_THAT(r.currentReadEndPos(), Eq(5)); - EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); +TEST(InputBuffer, WhenReadEndPositionIsNotSetThenReturnZeroAsBufferEndPosition) +{ + Buffer buf{}; + buf.resize(100); + InputAdapter r{ buf.begin(), 10 }; + EXPECT_THAT(r.currentReadEndPos(), Eq(0)); + r.currentReadEndPos(5); + EXPECT_THAT(r.currentReadEndPos(), Eq(5)); + EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); } - -TEST(InputBuffer, WhenReadEndPositionIsNotZeroThenDataOverflowErrorWillBeIgnored) { - Buffer buf{}; - buf.resize(100); - InputAdapter r{buf.begin(), 1}; - r.currentReadEndPos(1); - uint32_t tmp{}; - r.readBytes<4>(tmp); - EXPECT_THAT(tmp, Eq(0)); - EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); - r.currentReadEndPos(0); - r.readBytes<4>(tmp); - EXPECT_THAT(tmp, Eq(0)); - EXPECT_THAT(r.error(), Eq(ReaderError::DataOverflow)); +TEST(InputBuffer, + WhenReadEndPositionIsNotZeroThenDataOverflowErrorWillBeIgnored) +{ + Buffer buf{}; + buf.resize(100); + InputAdapter r{ buf.begin(), 1 }; + r.currentReadEndPos(1); + uint32_t tmp{}; + r.readBytes<4>(tmp); + EXPECT_THAT(tmp, Eq(0)); + EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); + r.currentReadEndPos(0); + r.readBytes<4>(tmp); + EXPECT_THAT(tmp, Eq(0)); + EXPECT_THAT(r.error(), Eq(ReaderError::DataOverflow)); } - -TEST(InputBuffer, WhenReadingPastReadEndPositionOrBufferEndThenReadPositionDoesntChange) { - Buffer buf{}; - buf.resize(10); - InputAdapter r{buf.begin(), 3}; - uint32_t tmp{}; - r.currentReadEndPos(2); - r.readBytes<4>(tmp); - EXPECT_THAT(r.currentReadPos(), Eq(0)); - EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); - EXPECT_THAT(tmp, Eq(0)); - r.currentReadEndPos(0); - r.readBytes<4>(tmp); - EXPECT_THAT(r.currentReadPos(), Eq(0)); - EXPECT_THAT(r.error(), Eq(ReaderError::DataOverflow)); - EXPECT_THAT(tmp, Eq(0)); +TEST(InputBuffer, + WhenReadingPastReadEndPositionOrBufferEndThenReadPositionDoesntChange) +{ + Buffer buf{}; + buf.resize(10); + InputAdapter r{ buf.begin(), 3 }; + uint32_t tmp{}; + r.currentReadEndPos(2); + r.readBytes<4>(tmp); + EXPECT_THAT(r.currentReadPos(), Eq(0)); + EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); + EXPECT_THAT(tmp, Eq(0)); + r.currentReadEndPos(0); + r.readBytes<4>(tmp); + EXPECT_THAT(r.currentReadPos(), Eq(0)); + EXPECT_THAT(r.error(), Eq(ReaderError::DataOverflow)); + EXPECT_THAT(tmp, Eq(0)); } -TEST(InputBuffer, WhenReaderHasErrorsThenSettingReadPosAndReadEndPosIsIgnoredAndGettingAlwaysReturnsZero) { - Buffer buf{}; - buf.resize(10); - InputAdapter r{buf.begin(), 10}; - uint32_t tmp{}; - r.readBytes<4>(tmp); - r.currentReadEndPos(5); - EXPECT_THAT(r.currentReadPos(), Eq(4)); - EXPECT_THAT(r.currentReadEndPos(), Eq(5)); - EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); - r.currentReadEndPos(11); - EXPECT_THAT(r.error(), Eq(ReaderError::DataOverflow)); - EXPECT_THAT(r.currentReadPos(), Eq(0)); - EXPECT_THAT(r.currentReadEndPos(), Eq(0)); - r.currentReadPos(1); - r.currentReadEndPos(1); - EXPECT_THAT(r.currentReadPos(), Eq(0)); - EXPECT_THAT(r.currentReadEndPos(), Eq(0)); +TEST( + InputBuffer, + WhenReaderHasErrorsThenSettingReadPosAndReadEndPosIsIgnoredAndGettingAlwaysReturnsZero) +{ + Buffer buf{}; + buf.resize(10); + InputAdapter r{ buf.begin(), 10 }; + uint32_t tmp{}; + r.readBytes<4>(tmp); + r.currentReadEndPos(5); + EXPECT_THAT(r.currentReadPos(), Eq(4)); + EXPECT_THAT(r.currentReadEndPos(), Eq(5)); + EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); + r.currentReadEndPos(11); + EXPECT_THAT(r.error(), Eq(ReaderError::DataOverflow)); + EXPECT_THAT(r.currentReadPos(), Eq(0)); + EXPECT_THAT(r.currentReadEndPos(), Eq(0)); + r.currentReadPos(1); + r.currentReadEndPos(1); + EXPECT_THAT(r.currentReadPos(), Eq(0)); + EXPECT_THAT(r.currentReadEndPos(), Eq(0)); } -TEST(InputBuffer, ConstDataForBufferAllAdapters) { - //create and write to buffer - uint16_t data = 7549; - Buffer bufWrite{}; - OutputAdapter bw{bufWrite}; - bw.writeBytes<2>(data); - bw.flush(); - const Buffer buf{bufWrite}; +TEST(InputBuffer, ConstDataForBufferAllAdapters) +{ + // create and write to buffer + uint16_t data = 7549; + Buffer bufWrite{}; + OutputAdapter bw{ bufWrite }; + bw.writeBytes<2>(data); + bw.flush(); + const Buffer buf{ bufWrite }; - //read from buffer + // read from buffer - bitsery::InputBufferAdapter r1{buf.begin(), buf.end()}; + bitsery::InputBufferAdapter r1{ buf.begin(), buf.end() }; - uint16_t res1{}; - r1.readBytes<2>(res1); - EXPECT_THAT(res1, Eq(data)); + uint16_t res1{}; + r1.readBytes<2>(res1); + EXPECT_THAT(res1, Eq(data)); } #ifndef NDEBUG -TEST(InputBuffer, WhenAdapterErrorsIsDisabledThenCanChangeAnyReadPositionAndReadsAsserts) { - //create and write to buffer - uint64_t data = 0x1122334455667788; - Buffer buf{}; - OutputAdapter bw{buf}; - bw.writeBytes<8>(data); - bw.flush(); +TEST(InputBuffer, + WhenAdapterErrorsIsDisabledThenCanChangeAnyReadPositionAndReadsAsserts) +{ + // create and write to buffer + uint64_t data = 0x1122334455667788; + Buffer buf{}; + OutputAdapter bw{ buf }; + bw.writeBytes<8>(data); + bw.flush(); - bitsery::InputBufferAdapter r1{buf.begin(), 2}; - uint16_t res1{}; - r1.readBytes<2>(res1); - EXPECT_THAT(res1, Eq(0x7788)); // default config is little endian - EXPECT_THAT(r1.currentReadPos(), Eq(2)); - r1.currentReadPos(4); - EXPECT_THAT(r1.currentReadPos(), Eq(4)); - EXPECT_DEATH(r1.readBytes<2>(res1), ""); // default config is little endian + bitsery::InputBufferAdapter r1{ + buf.begin(), 2 + }; + uint16_t res1{}; + r1.readBytes<2>(res1); + EXPECT_THAT(res1, Eq(0x7788)); // default config is little endian + EXPECT_THAT(r1.currentReadPos(), Eq(2)); + r1.currentReadPos(4); + EXPECT_THAT(r1.currentReadPos(), Eq(4)); + EXPECT_DEATH(r1.readBytes<2>(res1), ""); // default config is little endian } #endif -TEST(InputStream, WhenAdapterErrorsIsDisabledThenReadingPastEndDoesntSetErrorAndDoesntReturnZero) { - //create and write to buffer - std::stringstream ss{}; - bitsery::OutputStreamAdapter bw{ss}; - uint32_t data = 0x12345678; - bw.writeBytes<4>(data); - bw.flush(); +TEST( + InputStream, + WhenAdapterErrorsIsDisabledThenReadingPastEndDoesntSetErrorAndDoesntReturnZero) +{ + // create and write to buffer + std::stringstream ss{}; + bitsery::OutputStreamAdapter bw{ ss }; + uint32_t data = 0x12345678; + bw.writeBytes<4>(data); + bw.flush(); - bitsery::BasicInputStreamAdapter> br{ss}; - uint32_t res{}; - br.readBytes<4>(res); - EXPECT_THAT(res, Eq(data)); - br.readBytes<4>(res); - EXPECT_THAT(res, Eq(data)); - EXPECT_THAT(br.isCompletedSuccessfully(), Eq(true)); + bitsery::BasicInputStreamAdapter> + br{ ss }; + uint32_t res{}; + br.readBytes<4>(res); + EXPECT_THAT(res, Eq(data)); + br.readBytes<4>(res); + EXPECT_THAT(res, Eq(data)); + EXPECT_THAT(br.isCompletedSuccessfully(), Eq(true)); } -template class TAdapter> -struct InBufferConfig { - using Data = std::vector; - using Adapter = TAdapter; +template class TAdapter> +struct InBufferConfig +{ + using Data = std::vector; + using Adapter = TAdapter; - Data data{}; - Adapter createReader(const std::vector& buffer) { - data = buffer; - return Adapter{data.begin(), data.size()}; - } + Data data{}; + Adapter createReader(const std::vector& buffer) + { + data = buffer; + return Adapter{ data.begin(), data.size() }; + } }; -template -struct InStreamConfig { - using Data = std::stringstream; - using Adapter = TAdapter; +template +struct InStreamConfig +{ + using Data = std::stringstream; + using Adapter = TAdapter; - Data data{}; - Adapter createReader(const std::vector& buffer) { - std::string str(buffer.begin(), buffer.end()); - data = std::stringstream{str}; - return Adapter{data}; - } + Data data{}; + Adapter createReader(const std::vector& buffer) + { + std::string str(buffer.begin(), buffer.end()); + data = std::stringstream{ str }; + return Adapter{ data }; + } }; template -class AdapterConfig : public testing::Test { +class AdapterConfig : public testing::Test +{ public: - - TAdapterWithData config{}; + TAdapterWithData config{}; }; -using AdapterInputTypes = ::testing::Types< - InBufferConfig, - InStreamConfig ->; +using AdapterInputTypes = + ::testing::Types, + InStreamConfig>; -template -class InputAll: public AdapterConfig { +template +class InputAll : public AdapterConfig +{ }; -TYPED_TEST_SUITE(InputAll, AdapterInputTypes,); +TYPED_TEST_SUITE(InputAll, AdapterInputTypes, ); - -TYPED_TEST(InputAll, SettingMultipleErrorsAlwaysReturnsFirstError) { - auto r = this->config.createReader({0,0,0,0}); - EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); - r.error(ReaderError::InvalidPointer); - EXPECT_THAT(r.error(), Eq(ReaderError::InvalidPointer)); - r.error(ReaderError::DataOverflow); - EXPECT_THAT(r.error(), Eq(ReaderError::InvalidPointer)); - r.error(ReaderError::NoError); - EXPECT_THAT(r.error(), Eq(ReaderError::InvalidPointer)); +TYPED_TEST(InputAll, SettingMultipleErrorsAlwaysReturnsFirstError) +{ + auto r = this->config.createReader({ 0, 0, 0, 0 }); + EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); + r.error(ReaderError::InvalidPointer); + EXPECT_THAT(r.error(), Eq(ReaderError::InvalidPointer)); + r.error(ReaderError::DataOverflow); + EXPECT_THAT(r.error(), Eq(ReaderError::InvalidPointer)); + r.error(ReaderError::NoError); + EXPECT_THAT(r.error(), Eq(ReaderError::InvalidPointer)); } -TYPED_TEST(InputAll, CanBeMoveConstructedAndMoveAssigned) { - auto r = this->config.createReader({1,2,3}); - uint8_t res{}; - r.template readBytes<1>(res); - EXPECT_THAT(res, Eq(1)); - // move construct - auto r1 = std::move(r); - r1.template readBytes<1>(res); - EXPECT_THAT(res, Eq(2)); - // move assign - r = std::move(r1); - r.template readBytes<1>(res); - EXPECT_THAT(res, Eq(3)); +TYPED_TEST(InputAll, CanBeMoveConstructedAndMoveAssigned) +{ + auto r = this->config.createReader({ 1, 2, 3 }); + uint8_t res{}; + r.template readBytes<1>(res); + EXPECT_THAT(res, Eq(1)); + // move construct + auto r1 = std::move(r); + r1.template readBytes<1>(res); + EXPECT_THAT(res, Eq(2)); + // move assign + r = std::move(r1); + r.template readBytes<1>(res); + EXPECT_THAT(res, Eq(3)); } +TYPED_TEST(InputAll, WhenAlignHasNonZerosThenInvalidDataError) +{ -TYPED_TEST(InputAll, WhenAlignHasNonZerosThenInvalidDataError) { + auto r = this->config.createReader({ 0x7F }); + bitsery::details::InputAdapterBitPackingWrapper bpr{ r }; - auto r = this->config.createReader({0x7F}); - bitsery::details::InputAdapterBitPackingWrapper bpr{r}; - - uint8_t tmp{0xFF}; - bpr.readBits(tmp,3); - bpr.align(); - EXPECT_THAT(bpr.error(), Eq(ReaderError::InvalidData)); + uint8_t tmp{ 0xFF }; + bpr.readBits(tmp, 3); + bpr.align(); + EXPECT_THAT(bpr.error(), Eq(ReaderError::InvalidData)); } +TYPED_TEST(InputAll, + WhenAllBytesAreReadWithoutErrorsThenIsCompletedSuccessfully) +{ + // setup data -TYPED_TEST(InputAll, WhenAllBytesAreReadWithoutErrorsThenIsCompletedSuccessfully) { - //setup data + uint32_t tb = 94545646; + int16_t tc = -8778; + uint8_t td = 200; - uint32_t tb = 94545646; - int16_t tc = -8778; - uint8_t td = 200; + // create and write to buffer + Buffer buf{}; + OutputAdapter bw{ buf }; - //create and write to buffer - Buffer buf{}; - OutputAdapter bw{buf}; + bw.writeBytes<4>(tb); + bw.writeBytes<2>(tc); + bw.writeBytes<1>(td); + bw.flush(); + buf.resize(bw.writtenBytesCount()); - bw.writeBytes<4>(tb); - bw.writeBytes<2>(tc); - bw.writeBytes<1>(td); - bw.flush(); - buf.resize(bw.writtenBytesCount()); + auto br = this->config.createReader(buf); - auto br = this->config.createReader(buf); + uint32_t rb = 94545646; + int16_t rc = -8778; + uint8_t rd = 200; - uint32_t rb = 94545646; - int16_t rc = -8778; - uint8_t rd = 200; + br.template readBytes<4>(rb); + EXPECT_THAT(br.error(), Eq(bitsery::ReaderError::NoError)); + br.template readBytes<2>(rc); + EXPECT_THAT(br.error(), Eq(bitsery::ReaderError::NoError)); + EXPECT_THAT(br.isCompletedSuccessfully(), Eq(false)); + br.template readBytes<1>(rd); + EXPECT_THAT(br.error(), Eq(bitsery::ReaderError::NoError)); + EXPECT_THAT(br.isCompletedSuccessfully(), Eq(true)); - br.template readBytes<4>(rb); - EXPECT_THAT(br.error(), Eq(bitsery::ReaderError::NoError)); - br.template readBytes<2>(rc); - EXPECT_THAT(br.error(), Eq(bitsery::ReaderError::NoError)); - EXPECT_THAT(br.isCompletedSuccessfully(), Eq(false)); - br.template readBytes<1>(rd); - EXPECT_THAT(br.error(), Eq(bitsery::ReaderError::NoError)); - EXPECT_THAT(br.isCompletedSuccessfully(), Eq(true)); - - EXPECT_THAT(rb, Eq(tb)); - EXPECT_THAT(rc, Eq(tc)); - EXPECT_THAT(rd, Eq(td)); + EXPECT_THAT(rb, Eq(tb)); + EXPECT_THAT(rc, Eq(tc)); + EXPECT_THAT(rd, Eq(td)); } +TYPED_TEST(InputAll, WhenReadingMoreThanAvailableThenDataOverflow) +{ + // setup data + uint8_t t1 = 111; -TYPED_TEST(InputAll, WhenReadingMoreThanAvailableThenDataOverflow) { - //setup data - uint8_t t1 = 111; + Buffer buf{}; + OutputAdapter w{ buf }; + w.writeBytes<1>(t1); + w.flush(); + buf.resize(w.writtenBytesCount()); - Buffer buf{}; - OutputAdapter w{buf}; - w.writeBytes<1>(t1); - w.flush(); - buf.resize(w.writtenBytesCount()); - - auto r = this->config.createReader(buf); - - uint8_t r1{}; - EXPECT_THAT(r.isCompletedSuccessfully(), Eq(false)); - EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); - r.template readBytes<1>(r1); - EXPECT_THAT(r.isCompletedSuccessfully(), Eq(true)); - EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); - EXPECT_THAT(r1, Eq(t1)); - r.template readBytes<1>(r1); - r.template readBytes<1>(r1); - EXPECT_THAT(r1, Eq(0)); - EXPECT_THAT(r.isCompletedSuccessfully(), Eq(false)); - EXPECT_THAT(r.error(), Eq(ReaderError::DataOverflow)); + auto r = this->config.createReader(buf); + uint8_t r1{}; + EXPECT_THAT(r.isCompletedSuccessfully(), Eq(false)); + EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); + r.template readBytes<1>(r1); + EXPECT_THAT(r.isCompletedSuccessfully(), Eq(true)); + EXPECT_THAT(r.error(), Eq(ReaderError::NoError)); + EXPECT_THAT(r1, Eq(t1)); + r.template readBytes<1>(r1); + r.template readBytes<1>(r1); + EXPECT_THAT(r1, Eq(0)); + EXPECT_THAT(r.isCompletedSuccessfully(), Eq(false)); + EXPECT_THAT(r.error(), Eq(ReaderError::DataOverflow)); } -TYPED_TEST(InputAll, WhenReaderHasErrorsAllThenReadsReturnZero) { - //setup data - uint8_t t1 = 111; +TYPED_TEST(InputAll, WhenReaderHasErrorsAllThenReadsReturnZero) +{ + // setup data + uint8_t t1 = 111; - Buffer buf{}; - OutputAdapter w{buf}; - w.writeBytes<1>(t1); - w.writeBytes<1>(t1); - w.flush(); - buf.resize(w.writtenBytesCount()); + Buffer buf{}; + OutputAdapter w{ buf }; + w.writeBytes<1>(t1); + w.writeBytes<1>(t1); + w.flush(); + buf.resize(w.writtenBytesCount()); - auto r = this->config.createReader(buf); + auto r = this->config.createReader(buf); - uint8_t r1{}; - r.template readBytes<1>(r1); - EXPECT_THAT(r1, Eq(t1)); - r.error(ReaderError::InvalidPointer); - r.template readBytes<1>(r1); - EXPECT_THAT(r1, Eq(0)); + uint8_t r1{}; + r.template readBytes<1>(r1); + EXPECT_THAT(r1, Eq(t1)); + r.error(ReaderError::InvalidPointer); + r.template readBytes<1>(r1); + EXPECT_THAT(r1, Eq(0)); } +template class TAdapter> +struct OutBufferConfig +{ + using Data = std::vector; + using Adapter = TAdapter; -template class TAdapter> -struct OutBufferConfig { - using Data = std::vector; - using Adapter = TAdapter; + Data data{}; + Adapter createWriter() { return Adapter{ data }; } - Data data{}; - Adapter createWriter() { - return Adapter{data}; - } - - bitsery::InputBufferAdapter getReader() { - return bitsery::InputBufferAdapter{data.begin(), data.end()}; - } + bitsery::InputBufferAdapter getReader() + { + return bitsery::InputBufferAdapter{ data.begin(), data.end() }; + } }; -template -struct OutStreamConfig { - using Data = std::stringstream; - using Adapter = TAdapter; +template +struct OutStreamConfig +{ + using Data = std::stringstream; + using Adapter = TAdapter; - Data data{}; - Adapter createWriter() { - return Adapter{data}; - } + Data data{}; + Adapter createWriter() { return Adapter{ data }; } - bitsery::InputStreamAdapter getReader() { - return bitsery::InputStreamAdapter{data}; - } + bitsery::InputStreamAdapter getReader() + { + return bitsery::InputStreamAdapter{ data }; + } }; -using AdapterOutputTypes = ::testing::Types< - OutBufferConfig, - OutStreamConfig, - OutStreamConfig ->; +using AdapterOutputTypes = + ::testing::Types, + OutStreamConfig, + OutStreamConfig>; -template -class OutputAll: public AdapterConfig { +template +class OutputAll : public AdapterConfig +{ }; -TYPED_TEST_SUITE(OutputAll, AdapterOutputTypes,); +TYPED_TEST_SUITE(OutputAll, AdapterOutputTypes, ); -TYPED_TEST(OutputAll, CanBeMoveConstructedAndMoveAssigned) { - auto w = this->config.createWriter(); - uint8_t data{1}; - w.template writeBytes<1>(data); - // move construct - auto w1 = std::move(w); - data = 2; - w1.template writeBytes<1>(data); - // move assignment - w = std::move(w1); - data = 3; - w.template writeBytes<1>(data); - w.flush(); +TYPED_TEST(OutputAll, CanBeMoveConstructedAndMoveAssigned) +{ + auto w = this->config.createWriter(); + uint8_t data{ 1 }; + w.template writeBytes<1>(data); + // move construct + auto w1 = std::move(w); + data = 2; + w1.template writeBytes<1>(data); + // move assignment + w = std::move(w1); + data = 3; + w.template writeBytes<1>(data); + w.flush(); - auto r = this->config.getReader(); - r.template readBytes<1>(data); - EXPECT_THAT(data, Eq(1)); - r.template readBytes<1>(data); - EXPECT_THAT(data, Eq(2)); - r.template readBytes<1>(data); - EXPECT_THAT(data, Eq(3)); + auto r = this->config.getReader(); + r.template readBytes<1>(data); + EXPECT_THAT(data, Eq(1)); + r.template readBytes<1>(data); + EXPECT_THAT(data, Eq(2)); + r.template readBytes<1>(data); + EXPECT_THAT(data, Eq(3)); } - template -class OutputStreamBuffered : public testing::Test { +class OutputStreamBuffered : public testing::Test +{ public: - using Buffer = T; - using Adapter = bitsery::BasicBufferedOutputStreamAdapter, Buffer>; + using Buffer = T; + using Adapter = + bitsery::BasicBufferedOutputStreamAdapter, + Buffer>; - static constexpr size_t InternalBufferSize = 128; + static constexpr size_t InternalBufferSize = 128; - std::stringstream stream{}; + std::stringstream stream{}; - Adapter writer{stream, 128}; + Adapter writer{ stream, 128 }; }; -using BufferedAdapterInternalBufferTypes = ::testing::Types< - std::vector, - std::array, - std::string ->; +using BufferedAdapterInternalBufferTypes = + ::testing::Types, std::array, std::string>; -TYPED_TEST_SUITE(OutputStreamBuffered, BufferedAdapterInternalBufferTypes,); +TYPED_TEST_SUITE(OutputStreamBuffered, BufferedAdapterInternalBufferTypes, ); -TYPED_TEST(OutputStreamBuffered, WhenInternalBufferIsFullThenWriteBufferAndValueToStream) { - uint8_t x{}; - for (auto i = 0u; i < TestFixture::InternalBufferSize; ++i) - this->writer.template writeBytes<1>(x); - EXPECT_TRUE(this->stream.str().empty()); +TYPED_TEST(OutputStreamBuffered, + WhenInternalBufferIsFullThenWriteBufferAndValueToStream) +{ + uint8_t x{}; + for (auto i = 0u; i < TestFixture::InternalBufferSize; ++i) this->writer.template writeBytes<1>(x); - EXPECT_THAT(this->stream.str().size(), Eq(TestFixture::InternalBufferSize + 1)); + EXPECT_TRUE(this->stream.str().empty()); + this->writer.template writeBytes<1>(x); + EXPECT_THAT(this->stream.str().size(), + Eq(TestFixture::InternalBufferSize + 1)); } -TYPED_TEST(OutputStreamBuffered, WhenFlushThenWriteImmediately) { - uint8_t x{}; - this->writer.template writeBytes<1>(x); - EXPECT_THAT(this->stream.str().size(), Eq(0)); - this->writer.flush(); - EXPECT_THAT(this->stream.str().size(), Eq(1)); - this->writer.flush(); - EXPECT_THAT(this->stream.str().size(), Eq(1)); +TYPED_TEST(OutputStreamBuffered, WhenFlushThenWriteImmediately) +{ + uint8_t x{}; + this->writer.template writeBytes<1>(x); + EXPECT_THAT(this->stream.str().size(), Eq(0)); + this->writer.flush(); + EXPECT_THAT(this->stream.str().size(), Eq(1)); + this->writer.flush(); + EXPECT_THAT(this->stream.str().size(), Eq(1)); } -TYPED_TEST(OutputStreamBuffered, WhenBufferIsStackAllocatedThenBufferSizeViaCtorHasNoEffect) { +TYPED_TEST(OutputStreamBuffered, + WhenBufferIsStackAllocatedThenBufferSizeViaCtorHasNoEffect) +{ - //create writer with half the internal buffer size - //for std::vector it should overflow, and for std::array it should have no effect - typename TestFixture::Adapter w{this->stream, TestFixture::InternalBufferSize / 2}; + // create writer with half the internal buffer size + // for std::vector it should overflow, and for std::array it should have no + // effect + typename TestFixture::Adapter w{ this->stream, + TestFixture::InternalBufferSize / 2 }; - uint8_t x{}; - for (auto i = 0u; i < TestFixture::InternalBufferSize; ++i) - w.template writeBytes<1>(x); - static constexpr bool ShouldWriteToStream = bitsery::traits::ContainerTraits::isResizable; - EXPECT_THAT(this->stream.str().empty(), ::testing::Ne(ShouldWriteToStream)); + uint8_t x{}; + for (auto i = 0u; i < TestFixture::InternalBufferSize; ++i) + w.template writeBytes<1>(x); + static constexpr bool ShouldWriteToStream = + bitsery::traits::ContainerTraits::isResizable; + EXPECT_THAT(this->stream.str().empty(), ::testing::Ne(ShouldWriteToStream)); } struct TestData { - uint32_t b4; - std::vector vb2; + uint32_t b4; + std::vector vb2; }; -template -void serialize(S &s, TestData &o) +template +void +serialize(S& s, TestData& o) { - s.value4b(o.b4); - s.enableBitPacking([&o](typename S::BPEnabledType &sbp) { - sbp.ext(o.b4, bitsery::ext::ValueRange{0,1023}); // 10 bits - sbp.value4b(o.b4); - sbp.container(o.vb2, 10, [](typename S::BPEnabledType& sbp, uint16_t& data) { - sbp.ext(data, bitsery::ext::ValueRange{0, 200}); // 7 bits - }); - }); - s.container2b(o.vb2, 10); + s.value4b(o.b4); + s.enableBitPacking([&o](typename S::BPEnabledType& sbp) { + sbp.ext(o.b4, bitsery::ext::ValueRange{ 0, 1023 }); // 10 bits + sbp.value4b(o.b4); + sbp.container( + o.vb2, 10, [](typename S::BPEnabledType& sbp, uint16_t& data) { + sbp.ext(data, bitsery::ext::ValueRange{ 0, 200 }); // 7 bits + }); + }); + s.container2b(o.vb2, 10); } - TEST(AdapterWriterMeasureSize, CorrectlyMeasuresBytesAndBitsSize) { - TestData data{456, {45, 98, 189, 4}}; + TestData data{ 456, { 45, 98, 189, 4 } }; - Buffer buf{}; - auto measuredSize = bitsery::quickSerialization(bitsery::MeasureSize{}, data); - auto writtenSize = bitsery::quickSerialization(OutputAdapter{buf}, data); - EXPECT_THAT(measuredSize, Eq(24)); - EXPECT_THAT(measuredSize, Eq(writtenSize)); + Buffer buf{}; + auto measuredSize = bitsery::quickSerialization(bitsery::MeasureSize{}, data); + auto writtenSize = bitsery::quickSerialization(OutputAdapter{ buf }, data); + EXPECT_THAT(measuredSize, Eq(24)); + EXPECT_THAT(measuredSize, Eq(writtenSize)); } diff --git a/tests/brief_syntax.cpp b/tests/brief_syntax.cpp index d564641..9db10c7 100644 --- a/tests/brief_syntax.cpp +++ b/tests/brief_syntax.cpp @@ -1,24 +1,24 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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 @@ -40,421 +40,464 @@ #include #include #elif defined(_MSC_VER) -#pragma message("C++17 and /Zc:__cplusplus option is required to enable std::tuple and std::variant brief syntax tests") +#pragma message( \ + "C++17 and /Zc:__cplusplus option is required to enable std::tuple and std::variant brief syntax tests") #else -#pragma message("C++17 is required to enable std::tuple and std::variant brief syntax tests") +#pragma message( \ + "C++17 is required to enable std::tuple and std::variant brief syntax tests") #endif -#include #include "serialization_test_utils.h" +#include #include #include using testing::Eq; -TEST(BriefSyntax, FundamentalTypesAndBool) { - int ti = 8745; - MyEnumClass te = MyEnumClass::E4; - float tf = 485.042f; - double td = -454184.48445; - bool tb = true; - SerializationContext ctx{}; - ctx.createSerializer()(ti, te, tf, td, tb); +TEST(BriefSyntax, FundamentalTypesAndBool) +{ + int ti = 8745; + MyEnumClass te = MyEnumClass::E4; + float tf = 485.042f; + double td = -454184.48445; + bool tb = true; + SerializationContext ctx{}; + ctx.createSerializer()(ti, te, tf, td, tb); - //result - int ri{}; - MyEnumClass re{}; - float rf{}; - double rd{}; - bool rb{}; - ctx.createDeserializer()(ri, re, rf, rd, rb); + // result + int ri{}; + MyEnumClass re{}; + float rf{}; + double rd{}; + bool rb{}; + ctx.createDeserializer()(ri, re, rf, rd, rb); - //test - EXPECT_THAT(ri, Eq(ti)); - EXPECT_THAT(re, Eq(te)); - EXPECT_THAT(rf, Eq(tf)); - EXPECT_THAT(rd, Eq(td)); - EXPECT_THAT(rb, Eq(tb)); + // test + EXPECT_THAT(ri, Eq(ti)); + EXPECT_THAT(re, Eq(te)); + EXPECT_THAT(rf, Eq(tf)); + EXPECT_THAT(rd, Eq(td)); + EXPECT_THAT(rb, Eq(tb)); } -TEST(BriefSyntax, UseObjectFncInsteadOfValueN) { - int ti = 8745; - MyEnumClass te = MyEnumClass::E4; - float tf = 485.042f; - double td = -454184.48445; - bool tb = true; - SerializationContext ctx; - auto& ser = ctx.createSerializer(); - ser.object(ti); - ser.object(te); - ser.object(tf); - ser.object(td); - ser.object(tb); +TEST(BriefSyntax, UseObjectFncInsteadOfValueN) +{ + int ti = 8745; + MyEnumClass te = MyEnumClass::E4; + float tf = 485.042f; + double td = -454184.48445; + bool tb = true; + SerializationContext ctx; + auto& ser = ctx.createSerializer(); + ser.object(ti); + ser.object(te); + ser.object(tf); + ser.object(td); + ser.object(tb); - //result - int ri{}; - MyEnumClass re{}; - float rf{}; - double rd{}; - bool rb{}; - auto& des = ctx.createDeserializer(); - des.object(ri); - des.object(re); - des.object(rf); - des.object(rd); - des.object(rb); + // result + int ri{}; + MyEnumClass re{}; + float rf{}; + double rd{}; + bool rb{}; + auto& des = ctx.createDeserializer(); + des.object(ri); + des.object(re); + des.object(rf); + des.object(rd); + des.object(rb); - //test - EXPECT_THAT(ri, Eq(ti)); - EXPECT_THAT(re, Eq(te)); - EXPECT_THAT(rf, Eq(tf)); - EXPECT_THAT(rd, Eq(td)); - EXPECT_THAT(rb, Eq(tb)); + // test + EXPECT_THAT(ri, Eq(ti)); + EXPECT_THAT(re, Eq(te)); + EXPECT_THAT(rf, Eq(tf)); + EXPECT_THAT(rd, Eq(td)); + EXPECT_THAT(rb, Eq(tb)); } -TEST(BriefSyntax, MixDifferentSyntax) { - int ti = 8745; - MyEnumClass te = MyEnumClass::E4; - float tf = 485.042f; - double td = -454184.48445; - bool tb = true; - SerializationContext ctx; - auto& ser = ctx.createSerializer(); - ser.value(ti); - ser(te, tf, td); - ser.object(tb); +TEST(BriefSyntax, MixDifferentSyntax) +{ + int ti = 8745; + MyEnumClass te = MyEnumClass::E4; + float tf = 485.042f; + double td = -454184.48445; + bool tb = true; + SerializationContext ctx; + auto& ser = ctx.createSerializer(); + ser.value(ti); + ser(te, tf, td); + ser.object(tb); - //result - int ri{}; - MyEnumClass re{}; - float rf{}; - double rd{}; - bool rb{}; - auto& des = ctx.createDeserializer(); - des(ri, re, rf); - des.value8b(rd); - des.object(rb); + // result + int ri{}; + MyEnumClass re{}; + float rf{}; + double rd{}; + bool rb{}; + auto& des = ctx.createDeserializer(); + des(ri, re, rf); + des.value8b(rd); + des.object(rb); - //test - EXPECT_THAT(ri, Eq(ti)); - EXPECT_THAT(re, Eq(te)); - EXPECT_THAT(rf, Eq(tf)); - EXPECT_THAT(rd, Eq(td)); - EXPECT_THAT(rb, Eq(tb)); + // test + EXPECT_THAT(ri, Eq(ti)); + EXPECT_THAT(re, Eq(te)); + EXPECT_THAT(rf, Eq(tf)); + EXPECT_THAT(rd, Eq(td)); + EXPECT_THAT(rb, Eq(tb)); } template -T procBriefSyntax(const T& testData) { - SerializationContext ctx; - ctx.createSerializer()(testData); - T res{}; - ctx.createDeserializer()(res); - return res; +T +procBriefSyntax(const T& testData) +{ + SerializationContext ctx; + ctx.createSerializer()(testData); + T res{}; + ctx.createDeserializer()(res); + return res; } template -T&& procBriefSyntaxRvalue(T&& init_value, const T& testData) { - SerializationContext ctx; - ctx.createSerializer()(testData); - ctx.createDeserializer()(init_value); - return std::move(init_value); +T&& +procBriefSyntaxRvalue(T&& init_value, const T& testData) +{ + SerializationContext ctx; + ctx.createSerializer()(testData); + ctx.createDeserializer()(init_value); + return std::move(init_value); } template -T procBriefSyntaxWithMaxSize(const T& testData) { - SerializationContext ctx; - ctx.createSerializer()(bitsery::maxSize(testData, 100)); - T res{}; - ctx.createDeserializer()(bitsery::maxSize(res, 100)); - return res; +T +procBriefSyntaxWithMaxSize(const T& testData) +{ + SerializationContext ctx; + ctx.createSerializer()(bitsery::maxSize(testData, 100)); + T res{}; + ctx.createDeserializer()(bitsery::maxSize(res, 100)); + return res; } -TEST(BriefSyntax, CStyleArrayForValueTypesAsContainer) { - const int t1[3]{8748, -484, 45}; - int r1[3]{0, 0, 0}; +TEST(BriefSyntax, CStyleArrayForValueTypesAsContainer) +{ + const int t1[3]{ 8748, -484, 45 }; + int r1[3]{ 0, 0, 0 }; - SerializationContext ctx; - ctx.createSerializer()(bitsery::asContainer(t1)); - ctx.createDeserializer()(bitsery::asContainer(r1)); + SerializationContext ctx; + ctx.createSerializer()(bitsery::asContainer(t1)); + ctx.createDeserializer()(bitsery::asContainer(r1)); - EXPECT_THAT(r1, ::testing::ContainerEq(t1)); + EXPECT_THAT(r1, ::testing::ContainerEq(t1)); } -TEST(BriefSyntax, CStyleArrayForIntegralTypesAsText) { - const char t1[3]{"hi"}; - char r1[3]{0, 0, 0}; +TEST(BriefSyntax, CStyleArrayForIntegralTypesAsText) +{ + const char t1[3]{ "hi" }; + char r1[3]{ 0, 0, 0 }; - SerializationContext ctx; - ctx.createSerializer()(bitsery::asText(t1)); - ctx.createDeserializer()(bitsery::asText(r1)); + SerializationContext ctx; + ctx.createSerializer()(bitsery::asText(t1)); + ctx.createDeserializer()(bitsery::asText(r1)); - EXPECT_THAT(r1, ::testing::ContainerEq(t1)); + EXPECT_THAT(r1, ::testing::ContainerEq(t1)); } -TEST(BriefSyntax, CStyleArray) { - const MyEnumClass t1[3]{MyEnumClass::E1, MyEnumClass::E4, MyEnumClass::E2}; - MyEnumClass r1[3]{}; +TEST(BriefSyntax, CStyleArray) +{ + const MyEnumClass t1[3]{ MyEnumClass::E1, MyEnumClass::E4, MyEnumClass::E2 }; + MyEnumClass r1[3]{}; - SerializationContext ctx; - ctx.createSerializer()(t1); - ctx.createDeserializer()(r1); + SerializationContext ctx; + ctx.createSerializer()(t1); + ctx.createDeserializer()(r1); - EXPECT_THAT(r1, ::testing::ContainerEq(t1)); + EXPECT_THAT(r1, ::testing::ContainerEq(t1)); } -TEST(BriefSyntax, StdString) { - std::string t1{"my nice string"}; - std::string t2{}; +TEST(BriefSyntax, StdString) +{ + std::string t1{ "my nice string" }; + std::string t2{}; - EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntax(t2), Eq(t2)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2)); + EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntax(t2), Eq(t2)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2)); } -TEST(BriefSyntax, StdArray) { - std::array t1{8748, -484, 45}; - std::array t2{}; +TEST(BriefSyntax, StdArray) +{ + std::array t1{ 8748, -484, 45 }; + std::array t2{}; - EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntax(t2), Eq(t2)); + EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntax(t2), Eq(t2)); } -TEST(BriefSyntax, StdVector) { - std::vector t1{8748, -484, 45}; - std::vector t2{5.f, 0.198f}; +TEST(BriefSyntax, StdVector) +{ + std::vector t1{ 8748, -484, 45 }; + std::vector t2{ 5.f, 0.198f }; - EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntax(t2), Eq(t2)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2)); + EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntax(t2), Eq(t2)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2)); } -TEST(BriefSyntax, StdList) { - std::list t1{8748, -484, 45}; - std::list t2{5.f, 0.198f}; +TEST(BriefSyntax, StdList) +{ + std::list t1{ 8748, -484, 45 }; + std::list t2{ 5.f, 0.198f }; - EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntax(t2), Eq(t2)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2)); + EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntax(t2), Eq(t2)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2)); } -TEST(BriefSyntax, StdForwardList) { - std::forward_list t1{8748, -484, 45}; - std::forward_list t2{5.f, 0.198f}; +TEST(BriefSyntax, StdForwardList) +{ + std::forward_list t1{ 8748, -484, 45 }; + std::forward_list t2{ 5.f, 0.198f }; - EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntax(t2), Eq(t2)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2)); + EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntax(t2), Eq(t2)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2)); } -TEST(BriefSyntax, StdDeque) { - std::deque t1{8748, -484, 45}; - std::deque t2{5.f, 0.198f}; +TEST(BriefSyntax, StdDeque) +{ + std::deque t1{ 8748, -484, 45 }; + std::deque t2{ 5.f, 0.198f }; - EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntax(t2), Eq(t2)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2)); + EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntax(t2), Eq(t2)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2)); } -TEST(BriefSyntax, StdQueue) { - std::queue t1; - t1.push("first"); - t1.push("second string"); +TEST(BriefSyntax, StdQueue) +{ + std::queue t1; + t1.push("first"); + t1.push("second string"); - EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); } -TEST(BriefSyntax, StdPriorityQueue) { - std::priority_queue t1; - t1.push("first"); - t1.push("second string"); - t1.push("third"); - t1.push("fourth"); - auto r1 = procBriefSyntax(t1); - //we cannot compare priority queue directly +TEST(BriefSyntax, StdPriorityQueue) +{ + std::priority_queue t1; + t1.push("first"); + t1.push("second string"); + t1.push("third"); + t1.push("fourth"); + auto r1 = procBriefSyntax(t1); + // we cannot compare priority queue directly - EXPECT_THAT(r1.size(), Eq(t1.size())); - for (auto i = 0u; i < r1.size(); ++i) { - EXPECT_THAT(r1.top(), Eq(t1.top())); - r1.pop(); - t1.pop(); - } + EXPECT_THAT(r1.size(), Eq(t1.size())); + for (auto i = 0u; i < r1.size(); ++i) { + EXPECT_THAT(r1.top(), Eq(t1.top())); + r1.pop(); + t1.pop(); + } } -TEST(BriefSyntax, StdStack) { - std::stack t1; - t1.push("first"); - t1.push("second string"); +TEST(BriefSyntax, StdStack) +{ + std::stack t1; + t1.push("first"); + t1.push("second string"); - EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); } -TEST(BriefSyntax, StdUnorderedMap) { - std::unordered_map t1; - t1.emplace(3423, 624); - t1.emplace(-5484, -845); +TEST(BriefSyntax, StdUnorderedMap) +{ + std::unordered_map t1; + t1.emplace(3423, 624); + t1.emplace(-5484, -845); - EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); } -TEST(BriefSyntax, StdUnorderedMultiMap) { - std::unordered_multimap t1; - t1.emplace("one", 624); - t1.emplace("two", -845); - t1.emplace("one", 897); +TEST(BriefSyntax, StdUnorderedMultiMap) +{ + std::unordered_multimap t1; + t1.emplace("one", 624); + t1.emplace("two", -845); + t1.emplace("one", 897); - EXPECT_TRUE(procBriefSyntax(t1) == t1); - EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1); + EXPECT_TRUE(procBriefSyntax(t1) == t1); + EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1); } -TEST(BriefSyntax, StdMap) { - std::map t1; - t1.emplace(3423, 624); - t1.emplace(-5484, -845); +TEST(BriefSyntax, StdMap) +{ + std::map t1; + t1.emplace(3423, 624); + t1.emplace(-5484, -845); - EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); } -TEST(BriefSyntax, StdMultiMap) { - std::multimap t1; - t1.emplace("one", 624); - t1.emplace("two", -845); - t1.emplace("one", 897); +TEST(BriefSyntax, StdMultiMap) +{ + std::multimap t1; + t1.emplace("one", 624); + t1.emplace("two", -845); + t1.emplace("one", 897); - auto res = procBriefSyntax(t1); - //same key values is not ordered, and operator == compares each element at same position - //so we need to compare our selves - EXPECT_THAT(res.size(), Eq(3)); - for (auto it = t1.begin(); it != t1.end();) { - const auto lr = t1.equal_range(it->first); - const auto rr = res.equal_range(it->first); - EXPECT_TRUE(std::distance(lr.first, lr.second) == std::distance(rr.first, rr.second)); - EXPECT_TRUE(std::is_permutation(lr.first, lr.second, rr.first)); - it = lr.second; - } + auto res = procBriefSyntax(t1); + // same key values is not ordered, and operator == compares each element at + // same position so we need to compare our selves + EXPECT_THAT(res.size(), Eq(3)); + for (auto it = t1.begin(); it != t1.end();) { + const auto lr = t1.equal_range(it->first); + const auto rr = res.equal_range(it->first); + EXPECT_TRUE(std::distance(lr.first, lr.second) == + std::distance(rr.first, rr.second)); + EXPECT_TRUE(std::is_permutation(lr.first, lr.second, rr.first)); + it = lr.second; + } } -TEST(BriefSyntax, StdUnorderedSet) { - std::unordered_set t1; - t1.emplace("one"); - t1.emplace("two"); - t1.emplace("three"); +TEST(BriefSyntax, StdUnorderedSet) +{ + std::unordered_set t1; + t1.emplace("one"); + t1.emplace("two"); + t1.emplace("three"); - EXPECT_TRUE(procBriefSyntax(t1) == t1); - EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1); + EXPECT_TRUE(procBriefSyntax(t1) == t1); + EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1); } -TEST(BriefSyntax, StdUnorderedMultiSet) { - std::unordered_multiset t1; - t1.emplace("one"); - t1.emplace("two"); - t1.emplace("three"); - t1.emplace("one"); +TEST(BriefSyntax, StdUnorderedMultiSet) +{ + std::unordered_multiset t1; + t1.emplace("one"); + t1.emplace("two"); + t1.emplace("three"); + t1.emplace("one"); - EXPECT_TRUE(procBriefSyntax(t1) == t1); - EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1); + EXPECT_TRUE(procBriefSyntax(t1) == t1); + EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1); } -TEST(BriefSyntax, StdSet) { - std::set t1; - t1.emplace("one"); - t1.emplace("two"); - t1.emplace("three"); +TEST(BriefSyntax, StdSet) +{ + std::set t1; + t1.emplace("one"); + t1.emplace("two"); + t1.emplace("three"); - EXPECT_TRUE(procBriefSyntax(t1) == t1); - EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1); + EXPECT_TRUE(procBriefSyntax(t1) == t1); + EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1); } -TEST(BriefSyntax, StdMultiSet) { - std::multiset t1; - t1.emplace("one"); - t1.emplace("two"); - t1.emplace("three"); - t1.emplace("one"); - t1.emplace("two"); +TEST(BriefSyntax, StdMultiSet) +{ + std::multiset t1; + t1.emplace("one"); + t1.emplace("two"); + t1.emplace("three"); + t1.emplace("one"); + t1.emplace("two"); - EXPECT_TRUE(procBriefSyntax(t1) == t1); - EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1); + EXPECT_TRUE(procBriefSyntax(t1) == t1); + EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1); } -TEST(BriefSyntax, StdSmartPtr) { - std::shared_ptr dataShared1(new int{4}); - std::weak_ptr dataWeak1(dataShared1); - std::unique_ptr dataUnique1{new std::string{"hello world"}}; +TEST(BriefSyntax, StdSmartPtr) +{ + std::shared_ptr dataShared1(new int{ 4 }); + std::weak_ptr dataWeak1(dataShared1); + std::unique_ptr dataUnique1{ new std::string{ "hello world" } }; - bitsery::ext::PointerLinkingContext plctx1{}; - BasicSerializationContext ctx; - ctx.createSerializer(plctx1)(dataShared1, dataWeak1, dataUnique1); + bitsery::ext::PointerLinkingContext plctx1{}; + BasicSerializationContext ctx; + ctx.createSerializer(plctx1)(dataShared1, dataWeak1, dataUnique1); - std::shared_ptr resShared1{}; - std::weak_ptr resWeak1{}; - std::unique_ptr resUnique1{}; - ctx.createDeserializer(plctx1)(resShared1, resWeak1, resUnique1); - //clear shared state from pointer linking context - plctx1.clearSharedState(); + std::shared_ptr resShared1{}; + std::weak_ptr resWeak1{}; + std::unique_ptr resUnique1{}; + ctx.createDeserializer(plctx1)(resShared1, resWeak1, resUnique1); + // clear shared state from pointer linking context + plctx1.clearSharedState(); - EXPECT_TRUE(plctx1.isValid()); - EXPECT_THAT(*resShared1, Eq(*dataShared1)); - EXPECT_THAT(*resWeak1.lock(), Eq(*dataWeak1.lock())); - EXPECT_THAT(*resUnique1, Eq(*dataUnique1)); + EXPECT_TRUE(plctx1.isValid()); + EXPECT_THAT(*resShared1, Eq(*dataShared1)); + EXPECT_THAT(*resWeak1.lock(), Eq(*dataWeak1.lock())); + EXPECT_THAT(*resUnique1, Eq(*dataUnique1)); } -TEST(BriefSyntax, StdDuration) { - std::chrono::duration t1{54654}; - EXPECT_TRUE(procBriefSyntax(t1) == t1); +TEST(BriefSyntax, StdDuration) +{ + std::chrono::duration t1{ 54654 }; + EXPECT_TRUE(procBriefSyntax(t1) == t1); } -TEST(BriefSyntax, StdTimePoint) { - using Duration = std::chrono::duration; - using TP = std::chrono::time_point; +TEST(BriefSyntax, StdTimePoint) +{ + using Duration = std::chrono::duration; + using TP = std::chrono::time_point; - TP data{Duration{874656.4798}}; - EXPECT_TRUE(procBriefSyntax(data) == data); + TP data{ Duration{ 874656.4798 } }; + EXPECT_TRUE(procBriefSyntax(data) == data); } -TEST(BriefSyntax, StdAtomic) { - std::atomic atm0{54654}; - EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic{}, atm0) == atm0); +TEST(BriefSyntax, StdAtomic) +{ + std::atomic atm0{ 54654 }; + EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic{}, atm0) == atm0); - std::atomic atm1{false}; - EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic{}, atm1) == atm1); + std::atomic atm1{ false }; + EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic{}, atm1) == atm1); - std::atomic atm2{true}; - EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic{}, atm2) == atm2); + std::atomic atm2{ true }; + EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic{}, atm2) == atm2); - std::atomic atm3; - atm3.store(0x1337); - EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic{}, atm3).load() == 0x1337); + std::atomic atm3; + atm3.store(0x1337); + EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic{}, atm3).load() == + 0x1337); } #if __cplusplus > 201402L -TEST(BriefSyntax, StdTuple) { - std::tuple> t1{5,"hello hello", {'A','B','C'}}; - EXPECT_TRUE(procBriefSyntax(t1) == t1); +TEST(BriefSyntax, StdTuple) +{ + std::tuple> t1{ 5, + "hello hello", + { 'A', 'B', 'C' } }; + EXPECT_TRUE(procBriefSyntax(t1) == t1); } -TEST(BriefSyntax, StdVariant) { - std::variant t1{std::string("hello hello")}; - EXPECT_TRUE(procBriefSyntax(t1) == t1); +TEST(BriefSyntax, StdVariant) +{ + std::variant t1{ std::string( + "hello hello") }; + EXPECT_TRUE(procBriefSyntax(t1) == t1); } #endif -TEST(BriefSyntax, NestedTypes) { - std::unordered_map> t1; - t1.emplace("my key", std::vector{"very", "nice", "string"}); - t1.emplace("other key", std::vector{"just a string"}); +TEST(BriefSyntax, NestedTypes) +{ + std::unordered_map> t1; + t1.emplace("my key", std::vector{ "very", "nice", "string" }); + t1.emplace("other key", std::vector{ "just a string" }); - EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); - EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntax(t1), Eq(t1)); + EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1)); } diff --git a/tests/data_endianness.cpp b/tests/data_endianness.cpp index a7a3599..4b386fe 100644 --- a/tests/data_endianness.cpp +++ b/tests/data_endianness.cpp @@ -1,184 +1,195 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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 "serialization_test_utils.h" +#include #include #include -#include -#include "serialization_test_utils.h" #include -using testing::Eq; -using testing::ContainerEq; -using bitsery::EndiannessType; using bitsery::DefaultConfig; +using bitsery::EndiannessType; +using testing::ContainerEq; +using testing::Eq; -constexpr EndiannessType getInverseEndianness(EndiannessType e) { - return e == EndiannessType::LittleEndian - ? EndiannessType::BigEndian - : EndiannessType::LittleEndian; +constexpr EndiannessType +getInverseEndianness(EndiannessType e) +{ + return e == EndiannessType::LittleEndian ? EndiannessType::BigEndian + : EndiannessType::LittleEndian; } -struct InverseEndiannessConfig { - static constexpr bitsery::EndiannessType Endianness = getInverseEndianness(DefaultConfig::Endianness); - static constexpr bool CheckDataErrors = true; - static constexpr bool CheckAdapterErrors = true; +struct InverseEndiannessConfig +{ + static constexpr bitsery::EndiannessType Endianness = + getInverseEndianness(DefaultConfig::Endianness); + static constexpr bool CheckDataErrors = true; + static constexpr bool CheckAdapterErrors = true; }; -struct IntegralTypes { - int64_t a; - uint32_t b; - int16_t c; - uint8_t d; - int8_t e; +struct IntegralTypes +{ + int64_t a; + uint32_t b; + int16_t c; + uint8_t d; + int8_t e; }; -using InverseReader = bitsery::InputBufferAdapter; +using InverseReader = + bitsery::InputBufferAdapter; +TEST(DataEndianness, WhenWriteBytesThenBytesAreSwapped) +{ + // fill initial values + IntegralTypes src{}; + src.a = static_cast(0x1122334455667788u); + src.b = 0xBBCCDDEEu; + src.c = static_cast(0xCCDDu); + src.d = static_cast(0xDDu); + src.e = static_cast(0xEEu); -TEST(DataEndianness, WhenWriteBytesThenBytesAreSwapped) { - //fill initial values - IntegralTypes src{}; - src.a = static_cast(0x1122334455667788u); - src.b = 0xBBCCDDEEu; - src.c = static_cast(0xCCDDu); - src.d = static_cast(0xDDu); - src.e = static_cast(0xEEu); + // fill expected result after swap + IntegralTypes resInv{}; + resInv.a = static_cast(0x8877665544332211u); + resInv.b = 0xEEDDCCBBu; + resInv.c = static_cast(0xDDCCu); + resInv.d = static_cast(0xDDu); + resInv.e = static_cast(0xEEu); - //fill expected result after swap - IntegralTypes resInv{}; - resInv.a = static_cast(0x8877665544332211u); - resInv.b = 0xEEDDCCBBu; - resInv.c = static_cast(0xDDCCu); - resInv.d = static_cast(0xDDu); - resInv.e = static_cast(0xEEu); - - //create and write to buffer - Buffer buf{}; - Writer bw{buf}; - bw.writeBytes<8>(src.a); - bw.writeBytes<4>(src.b); - bw.writeBytes<2>(src.c); - bw.writeBytes<1>(src.d); - bw.writeBytes<1>(src.e); - bw.flush(); - //read from buffer using inverse endianness config - InverseReader br{buf.begin(), bw.writtenBytesCount()}; - IntegralTypes res{}; - br.readBytes<8>(res.a); - br.readBytes<4>(res.b); - br.readBytes<2>(res.c); - br.readBytes<1>(res.d); - br.readBytes<1>(res.e); - //check results - EXPECT_THAT(res.a, Eq(resInv.a)); - EXPECT_THAT(res.b, Eq(resInv.b)); - EXPECT_THAT(res.c, Eq(resInv.c)); - EXPECT_THAT(res.d, Eq(resInv.d)); - EXPECT_THAT(res.e, Eq(resInv.e)); + // create and write to buffer + Buffer buf{}; + Writer bw{ buf }; + bw.writeBytes<8>(src.a); + bw.writeBytes<4>(src.b); + bw.writeBytes<2>(src.c); + bw.writeBytes<1>(src.d); + bw.writeBytes<1>(src.e); + bw.flush(); + // read from buffer using inverse endianness config + InverseReader br{ buf.begin(), bw.writtenBytesCount() }; + IntegralTypes res{}; + br.readBytes<8>(res.a); + br.readBytes<4>(res.b); + br.readBytes<2>(res.c); + br.readBytes<1>(res.d); + br.readBytes<1>(res.e); + // check results + EXPECT_THAT(res.a, Eq(resInv.a)); + EXPECT_THAT(res.b, Eq(resInv.b)); + EXPECT_THAT(res.c, Eq(resInv.c)); + EXPECT_THAT(res.d, Eq(resInv.d)); + EXPECT_THAT(res.e, Eq(resInv.e)); } -TEST(DataEndianness, WhenWrite1ByteValuesThenEndiannessIsIgnored) { - //fill initial values - constexpr size_t SIZE = 4; - uint8_t src[SIZE] = {0xAA, 0xBB, 0xCC, 0xDD}; - uint8_t res[SIZE] = {}; - //create and write to buffer - Buffer buf{}; - Writer bw{buf}; - bw.writeBuffer<1>(src, SIZE); - bw.flush(); - //read from buffer using inverse endianness config - InverseReader br{buf.begin(), bw.writtenBytesCount()}; - br.readBuffer<1>(res, SIZE); - //result is identical, because we write separate values, of size 1byte, that requires no swapping - //check results - EXPECT_THAT(res, ContainerEq(src)); +TEST(DataEndianness, WhenWrite1ByteValuesThenEndiannessIsIgnored) +{ + // fill initial values + constexpr size_t SIZE = 4; + uint8_t src[SIZE] = { 0xAA, 0xBB, 0xCC, 0xDD }; + uint8_t res[SIZE] = {}; + // create and write to buffer + Buffer buf{}; + Writer bw{ buf }; + bw.writeBuffer<1>(src, SIZE); + bw.flush(); + // read from buffer using inverse endianness config + InverseReader br{ buf.begin(), bw.writtenBytesCount() }; + br.readBuffer<1>(res, SIZE); + // result is identical, because we write separate values, of size 1byte, that + // requires no swapping check results + EXPECT_THAT(res, ContainerEq(src)); } -TEST(DataEndianness, WhenWriteMoreThan1ByteValuesThenValuesAreSwapped) { - //fill initial values - constexpr size_t SIZE = 4; - uint16_t src[SIZE] = {0xAA00, 0xBB11, 0xCC22, 0xDD33}; - uint16_t resInv[SIZE] = {0x00AA, 0x11BB, 0x22CC, 0x33DD}; - uint16_t res[SIZE] = {}; - //create and write to buffer - Buffer buf{}; - Writer bw{buf}; - bw.writeBuffer<2>(src, SIZE); - bw.flush(); - //read from buffer using inverse endianness config - InverseReader br{buf.begin(), bw.writtenBytesCount()}; - br.readBuffer<2>(res, SIZE); - //result is identical, because we write separate values, of size 1byte, that requires no swapping - //check results - EXPECT_THAT(res, ContainerEq(resInv)); +TEST(DataEndianness, WhenWriteMoreThan1ByteValuesThenValuesAreSwapped) +{ + // fill initial values + constexpr size_t SIZE = 4; + uint16_t src[SIZE] = { 0xAA00, 0xBB11, 0xCC22, 0xDD33 }; + uint16_t resInv[SIZE] = { 0x00AA, 0x11BB, 0x22CC, 0x33DD }; + uint16_t res[SIZE] = {}; + // create and write to buffer + Buffer buf{}; + Writer bw{ buf }; + bw.writeBuffer<2>(src, SIZE); + bw.flush(); + // read from buffer using inverse endianness config + InverseReader br{ buf.begin(), bw.writtenBytesCount() }; + br.readBuffer<2>(res, SIZE); + // result is identical, because we write separate values, of size 1byte, that + // requires no swapping check results + EXPECT_THAT(res, ContainerEq(resInv)); } - -template -constexpr size_t getBits(T v) { - return bitsery::details::calcRequiredBits({}, v); +template +constexpr size_t +getBits(T v) +{ + return bitsery::details::calcRequiredBits({}, v); } -struct IntegralUnsignedTypes { - uint64_t a; - uint32_t b; - uint16_t c; - uint8_t d; +struct IntegralUnsignedTypes +{ + uint64_t a; + uint32_t b; + uint16_t c; + uint8_t d; }; -TEST(DataEndianness, WhenValueTypeIs1ByteThenBitOperationsIsNotAffectedByEndianness) { - //fill initial values - constexpr IntegralUnsignedTypes src { - 0x0000334455667788, - 0x00CCDDEE, - 0x00DD, - 0x0F, - }; +TEST(DataEndianness, + WhenValueTypeIs1ByteThenBitOperationsIsNotAffectedByEndianness) +{ + // fill initial values + constexpr IntegralUnsignedTypes src{ + 0x0000334455667788, + 0x00CCDDEE, + 0x00DD, + 0x0F, + }; - constexpr size_t aBITS = getBits(src.a) + 8; - constexpr size_t bBITS = getBits(src.b) + 0; - constexpr size_t cBITS = getBits(src.c) + 5; - constexpr size_t dBITS = getBits(src.d) + 2; - //create and write to buffer - Buffer buf{}; - Writer bw{buf}; - bitsery::details::OutputAdapterBitPackingWrapper bpw{bw}; - bpw.writeBits(src.a, aBITS); - bpw.writeBits(src.b, bBITS); - bpw.writeBits(src.c, cBITS); - bpw.writeBits(src.d, dBITS); - bpw.flush(); - //read from buffer using inverse endianness config - InverseReader br{buf.begin(), bpw.writtenBytesCount()}; - bitsery::details::InputAdapterBitPackingWrapper bpr{br}; - IntegralUnsignedTypes res{}; - bpr.readBits(res.a, aBITS); - bpr.readBits(res.b, bBITS); - bpr.readBits(res.c, cBITS); - bpr.readBits(res.d, dBITS); - //check results - EXPECT_THAT(res.a, Eq(src.a)); - EXPECT_THAT(res.b, Eq(src.b)); - EXPECT_THAT(res.c, Eq(src.c)); - EXPECT_THAT(res.d, Eq(src.d)); + constexpr size_t aBITS = getBits(src.a) + 8; + constexpr size_t bBITS = getBits(src.b) + 0; + constexpr size_t cBITS = getBits(src.c) + 5; + constexpr size_t dBITS = getBits(src.d) + 2; + // create and write to buffer + Buffer buf{}; + Writer bw{ buf }; + bitsery::details::OutputAdapterBitPackingWrapper bpw{ bw }; + bpw.writeBits(src.a, aBITS); + bpw.writeBits(src.b, bBITS); + bpw.writeBits(src.c, cBITS); + bpw.writeBits(src.d, dBITS); + bpw.flush(); + // read from buffer using inverse endianness config + InverseReader br{ buf.begin(), bpw.writtenBytesCount() }; + bitsery::details::InputAdapterBitPackingWrapper bpr{ br }; + IntegralUnsignedTypes res{}; + bpr.readBits(res.a, aBITS); + bpr.readBits(res.b, bBITS); + bpr.readBits(res.c, cBITS); + bpr.readBits(res.d, dBITS); + // check results + EXPECT_THAT(res.a, Eq(src.a)); + EXPECT_THAT(res.b, Eq(src.b)); + EXPECT_THAT(res.c, Eq(src.c)); + EXPECT_THAT(res.d, Eq(src.d)); } diff --git a/tests/data_operations.cpp b/tests/data_operations.cpp index fbee660..7984985 100644 --- a/tests/data_operations.cpp +++ b/tests/data_operations.cpp @@ -1,410 +1,419 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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 "serialization_test_utils.h" +#include #include #include -#include #include -#include "serialization_test_utils.h" - -using testing::Eq; using testing::ContainerEq; +using testing::Eq; -using AdapterBitPackingWriter = bitsery::details::OutputAdapterBitPackingWrapper; -using AdapterBitPackingReader = bitsery::details::InputAdapterBitPackingWrapper; +using AdapterBitPackingWriter = + bitsery::details::OutputAdapterBitPackingWrapper; +using AdapterBitPackingReader = + bitsery::details::InputAdapterBitPackingWrapper; - -struct IntegralUnsignedTypes { - uint32_t a; - uint16_t b; - uint8_t c; - uint8_t d; - uint64_t e; +struct IntegralUnsignedTypes +{ + uint32_t a; + uint16_t b; + uint8_t c; + uint8_t d; + uint64_t e; }; -template -constexpr size_t getBits(T v) { - return bitsery::details::calcRequiredBits({}, v); +template +constexpr size_t +getBits(T v) +{ + return bitsery::details::calcRequiredBits({}, v); } // *** bits operations -TEST(DataBitsAndBytesOperations, WriteAndReadBitsMaxTypeValues) { - Buffer buf; - Writer bw{buf}; - AdapterBitPackingWriter bpw{bw}; - bpw.writeBits(std::numeric_limits::max(), 64); - bpw.writeBits(std::numeric_limits::max(), 32); - bpw.writeBits(std::numeric_limits::max(), 16); - bpw.writeBits(std::numeric_limits::max(), 8); - bpw.flush(); +TEST(DataBitsAndBytesOperations, WriteAndReadBitsMaxTypeValues) +{ + Buffer buf; + Writer bw{ buf }; + AdapterBitPackingWriter bpw{ bw }; + bpw.writeBits(std::numeric_limits::max(), 64); + bpw.writeBits(std::numeric_limits::max(), 32); + bpw.writeBits(std::numeric_limits::max(), 16); + bpw.writeBits(std::numeric_limits::max(), 8); + bpw.flush(); - Reader br{buf.begin(), bpw.writtenBytesCount()}; - AdapterBitPackingReader bpr{br}; - uint64_t v64{}; - uint32_t v32{}; - uint16_t v16{}; - uint8_t v8{}; - bpr.readBits(v64, 64); - bpr.readBits(v32, 32); - bpr.readBits(v16, 16); - bpr.readBits(v8, 8); + Reader br{ buf.begin(), bpw.writtenBytesCount() }; + AdapterBitPackingReader bpr{ br }; + uint64_t v64{}; + uint32_t v32{}; + uint16_t v16{}; + uint8_t v8{}; + bpr.readBits(v64, 64); + bpr.readBits(v32, 32); + bpr.readBits(v16, 16); + bpr.readBits(v8, 8); - EXPECT_THAT(v64, Eq(std::numeric_limits::max())); - EXPECT_THAT(v32, Eq(std::numeric_limits::max())); - EXPECT_THAT(v16, Eq(std::numeric_limits::max())); - EXPECT_THAT(v8, Eq(std::numeric_limits::max())); + EXPECT_THAT(v64, Eq(std::numeric_limits::max())); + EXPECT_THAT(v32, Eq(std::numeric_limits::max())); + EXPECT_THAT(v16, Eq(std::numeric_limits::max())); + EXPECT_THAT(v8, Eq(std::numeric_limits::max())); } -TEST(DataBitsAndBytesOperations, WriteAndReadBits) { - //setup data - constexpr IntegralUnsignedTypes data{ - 485454,//bits 19 - 45978,//bits 16 - 0,//bits 1 - 36,//bits 6 - 479845648946//bits 39 - }; +TEST(DataBitsAndBytesOperations, WriteAndReadBits) +{ + // setup data + constexpr IntegralUnsignedTypes data{ + 485454, // bits 19 + 45978, // bits 16 + 0, // bits 1 + 36, // bits 6 + 479845648946 // bits 39 + }; - constexpr size_t aBITS = getBits(data.a) + 2; - constexpr size_t bBITS = getBits(data.b) + 0; - constexpr size_t cBITS = getBits(data.c) + 2; - constexpr size_t dBITS = getBits(data.d) + 1; - constexpr size_t eBITS = getBits(data.e) + 8; + constexpr size_t aBITS = getBits(data.a) + 2; + constexpr size_t bBITS = getBits(data.b) + 0; + constexpr size_t cBITS = getBits(data.c) + 2; + constexpr size_t dBITS = getBits(data.d) + 1; + constexpr size_t eBITS = getBits(data.e) + 8; - //create and write to buffer - Buffer buf; - Writer bw{buf}; - AdapterBitPackingWriter bpw{bw}; + // create and write to buffer + Buffer buf; + Writer bw{ buf }; + AdapterBitPackingWriter bpw{ bw }; - bpw.writeBits(data.a, aBITS); - bpw.writeBits(data.b, bBITS); - bpw.writeBits(data.c, cBITS); - bpw.writeBits(data.d, dBITS); - bpw.writeBits(data.e, eBITS); - bpw.flush(); - auto writtenSize = bpw.writtenBytesCount(); - auto bytesCount = ((aBITS + bBITS + cBITS + dBITS + eBITS) / 8) +1 ; - EXPECT_THAT(writtenSize, Eq(bytesCount)); - //read from buffer - Reader br{buf.begin(), writtenSize}; - AdapterBitPackingReader bpr{br}; + bpw.writeBits(data.a, aBITS); + bpw.writeBits(data.b, bBITS); + bpw.writeBits(data.c, cBITS); + bpw.writeBits(data.d, dBITS); + bpw.writeBits(data.e, eBITS); + bpw.flush(); + auto writtenSize = bpw.writtenBytesCount(); + auto bytesCount = ((aBITS + bBITS + cBITS + dBITS + eBITS) / 8) + 1; + EXPECT_THAT(writtenSize, Eq(bytesCount)); + // read from buffer + Reader br{ buf.begin(), writtenSize }; + AdapterBitPackingReader bpr{ br }; - IntegralUnsignedTypes res{}; + IntegralUnsignedTypes res{}; - bpr.readBits(res.a, aBITS); - bpr.readBits(res.b, bBITS); - bpr.readBits(res.c, cBITS); - bpr.readBits(res.d, dBITS); - bpr.readBits(res.e, eBITS); - - EXPECT_THAT(res.a, Eq(data.a)); - EXPECT_THAT(res.b, Eq(data.b)); - EXPECT_THAT(res.c, Eq(data.c)); - EXPECT_THAT(res.d, Eq(data.d)); - EXPECT_THAT(res.e, Eq(data.e)); + bpr.readBits(res.a, aBITS); + bpr.readBits(res.b, bBITS); + bpr.readBits(res.c, cBITS); + bpr.readBits(res.d, dBITS); + bpr.readBits(res.e, eBITS); + EXPECT_THAT(res.a, Eq(data.a)); + EXPECT_THAT(res.b, Eq(data.b)); + EXPECT_THAT(res.c, Eq(data.c)); + EXPECT_THAT(res.d, Eq(data.d)); + EXPECT_THAT(res.e, Eq(data.e)); } -TEST(DataBitsAndBytesOperations, WrittenSizeIsCountedPerByteNotPerBit) { - //setup data +TEST(DataBitsAndBytesOperations, WrittenSizeIsCountedPerByteNotPerBit) +{ + // setup data - //create and write to buffer - Buffer buf; - Writer bw{buf}; - AdapterBitPackingWriter bpw{bw}; + // create and write to buffer + Buffer buf; + Writer bw{ buf }; + AdapterBitPackingWriter bpw{ bw }; - bpw.writeBits(7u,3); - bpw.flush(); - auto writtenSize = bpw.writtenBytesCount(); - EXPECT_THAT(writtenSize, Eq(1)); + bpw.writeBits(7u, 3); + bpw.flush(); + auto writtenSize = bpw.writtenBytesCount(); + EXPECT_THAT(writtenSize, Eq(1)); - //read from buffer - Reader br{buf.begin(), writtenSize}; - AdapterBitPackingReader bpr{br}; - uint16_t tmp; - bpr.readBits(tmp,4); - bpr.readBits(tmp,2); - bpr.readBits(tmp,2); - EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError)); - bpr.readBits(tmp,2); - EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::DataOverflow));//false + // read from buffer + Reader br{ buf.begin(), writtenSize }; + AdapterBitPackingReader bpr{ br }; + uint16_t tmp; + bpr.readBits(tmp, 4); + bpr.readBits(tmp, 2); + bpr.readBits(tmp, 2); + EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError)); + bpr.readBits(tmp, 2); + EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::DataOverflow)); // false - //part of next byte - Reader br1{buf.begin(), writtenSize}; - AdapterBitPackingReader bpr1{br1}; - bpr1.readBits(tmp,2); - EXPECT_THAT(bpr1.error(), Eq(bitsery::ReaderError::NoError)); - bpr1.readBits(tmp,7); - EXPECT_THAT(bpr1.error(), Eq(bitsery::ReaderError::DataOverflow));//false + // part of next byte + Reader br1{ buf.begin(), writtenSize }; + AdapterBitPackingReader bpr1{ br1 }; + bpr1.readBits(tmp, 2); + EXPECT_THAT(bpr1.error(), Eq(bitsery::ReaderError::NoError)); + bpr1.readBits(tmp, 7); + EXPECT_THAT(bpr1.error(), Eq(bitsery::ReaderError::DataOverflow)); // false - //bigger than byte - Reader br2{buf.begin(), writtenSize}; - AdapterBitPackingReader bpr2{br2}; - bpr2.readBits(tmp,9); - EXPECT_THAT(bpr2.error(), Eq(bitsery::ReaderError::DataOverflow));//false + // bigger than byte + Reader br2{ buf.begin(), writtenSize }; + AdapterBitPackingReader bpr2{ br2 }; + bpr2.readBits(tmp, 9); + EXPECT_THAT(bpr2.error(), Eq(bitsery::ReaderError::DataOverflow)); // false } -TEST(DataBitsAndBytesOperations, ConsecutiveCallsToAlignHasNoEffect) { - Buffer buf; - Writer bw{buf}; - AdapterBitPackingWriter bpw{bw}; +TEST(DataBitsAndBytesOperations, ConsecutiveCallsToAlignHasNoEffect) +{ + Buffer buf; + Writer bw{ buf }; + AdapterBitPackingWriter bpw{ bw }; - bpw.writeBits(3u, 2); - //3 calls to align after 1st data - bpw.align(); - bpw.align(); - bpw.align(); - bpw.writeBits(7u, 3); - //1 call to align after 2nd data - bpw.align(); - bpw.writeBits(15u, 4); - bpw.flush(); + bpw.writeBits(3u, 2); + // 3 calls to align after 1st data + bpw.align(); + bpw.align(); + bpw.align(); + bpw.writeBits(7u, 3); + // 1 call to align after 2nd data + bpw.align(); + bpw.writeBits(15u, 4); + bpw.flush(); - unsigned char tmp; - Reader br{buf.begin(), bpw.writtenBytesCount()}; - AdapterBitPackingReader bpr{br}; - bpr.readBits(tmp,2); - EXPECT_THAT(tmp, Eq(3u)); - bpr.align(); - EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError)); - bpr.readBits(tmp,3); - bpr.align(); - bpr.align(); - bpr.align(); - EXPECT_THAT(tmp, Eq(7u)); - EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError)); + unsigned char tmp; + Reader br{ buf.begin(), bpw.writtenBytesCount() }; + AdapterBitPackingReader bpr{ br }; + bpr.readBits(tmp, 2); + EXPECT_THAT(tmp, Eq(3u)); + bpr.align(); + EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError)); + bpr.readBits(tmp, 3); + bpr.align(); + bpr.align(); + bpr.align(); + EXPECT_THAT(tmp, Eq(7u)); + EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError)); - bpr.readBits(tmp,4); - EXPECT_THAT(tmp, Eq(15u)); - EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError)); + bpr.readBits(tmp, 4); + EXPECT_THAT(tmp, Eq(15u)); + EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError)); } -TEST(DataBitsAndBytesOperations, AlignWritesZerosBits) { - //setup data +TEST(DataBitsAndBytesOperations, AlignWritesZerosBits) +{ + // setup data - //create and write to buffer - Buffer buf; - Writer bw{buf}; - AdapterBitPackingWriter bpw{bw}; + // create and write to buffer + Buffer buf; + Writer bw{ buf }; + AdapterBitPackingWriter bpw{ bw }; - //write 2 bits and align - bpw.writeBits(3u, 2); - bpw.align(); - bpw.flush(); - auto writtenSize = bpw.writtenBytesCount(); - EXPECT_THAT(writtenSize, Eq(1)); - unsigned char tmp; - Reader br1{buf.begin(), writtenSize}; - AdapterBitPackingReader bpr1{br1}; - bpr1.readBits(tmp,2); - //read aligned bits - bpr1.readBits(tmp,6); - EXPECT_THAT(tmp, Eq(0)); + // write 2 bits and align + bpw.writeBits(3u, 2); + bpw.align(); + bpw.flush(); + auto writtenSize = bpw.writtenBytesCount(); + EXPECT_THAT(writtenSize, Eq(1)); + unsigned char tmp; + Reader br1{ buf.begin(), writtenSize }; + AdapterBitPackingReader bpr1{ br1 }; + bpr1.readBits(tmp, 2); + // read aligned bits + bpr1.readBits(tmp, 6); + EXPECT_THAT(tmp, Eq(0)); - Reader br2{buf.begin(), writtenSize}; - AdapterBitPackingReader bpr2{br2}; - //read 2 bits - bpr2.readBits(tmp,2); - bpr2.align(); - EXPECT_THAT(bpr2.error(), Eq(bitsery::ReaderError::NoError)); + Reader br2{ buf.begin(), writtenSize }; + AdapterBitPackingReader bpr2{ br2 }; + // read 2 bits + bpr2.readBits(tmp, 2); + bpr2.align(); + EXPECT_THAT(bpr2.error(), Eq(bitsery::ReaderError::NoError)); } - // *** bytes operations -struct IntegralTypes { - int64_t a; - uint32_t b; - int16_t c; - uint8_t d; - int8_t e; - int8_t f[2]; +struct IntegralTypes +{ + int64_t a; + uint32_t b; + int16_t c; + uint8_t d; + int8_t e; + int8_t f[2]; }; -TEST(DataBitsAndBytesOperations, WriteAndReadBytes) { - //setup data - IntegralTypes data; - data.a = -4894541654564; - data.b = 94545646; - data.c = -8778; - data.d = 200; - data.e = -98; - data.f[0] = 43; - data.f[1] = -45; +TEST(DataBitsAndBytesOperations, WriteAndReadBytes) +{ + // setup data + IntegralTypes data; + data.a = -4894541654564; + data.b = 94545646; + data.c = -8778; + data.d = 200; + data.e = -98; + data.f[0] = 43; + data.f[1] = -45; - //create and write to buffer - Buffer buf{}; - Writer bw{buf}; - bw.writeBytes<4>(data.b); - bw.writeBytes<2>(data.c); - bw.writeBytes<1>(data.d); - bw.writeBytes<8>(data.a); - bw.writeBytes<1>(data.e); - bw.writeBuffer<1>(data.f, 2); - bw.flush(); - auto writtenSize = bw.writtenBytesCount(); + // create and write to buffer + Buffer buf{}; + Writer bw{ buf }; + bw.writeBytes<4>(data.b); + bw.writeBytes<2>(data.c); + bw.writeBytes<1>(data.d); + bw.writeBytes<8>(data.a); + bw.writeBytes<1>(data.e); + bw.writeBuffer<1>(data.f, 2); + bw.flush(); + auto writtenSize = bw.writtenBytesCount(); - EXPECT_THAT(writtenSize, Eq(18)); - //read from buffer - Reader br{buf.begin(), writtenSize}; - IntegralTypes res{}; - br.readBytes<4>(res.b); - br.readBytes<2>(res.c); - br.readBytes<1>(res.d); - br.readBytes<8>(res.a); - br.readBytes<1>(res.e); - br.readBuffer<1>(res.f, 2); - EXPECT_THAT(br.error(), Eq(bitsery::ReaderError::NoError)); - //assert results - - EXPECT_THAT(data.a, Eq(res.a)); - EXPECT_THAT(data.b, Eq(res.b)); - EXPECT_THAT(data.c, Eq(res.c)); - EXPECT_THAT(data.d, Eq(res.d)); - EXPECT_THAT(data.e, Eq(res.e)); - EXPECT_THAT(data.f, ContainerEq(res.f)); + EXPECT_THAT(writtenSize, Eq(18)); + // read from buffer + Reader br{ buf.begin(), writtenSize }; + IntegralTypes res{}; + br.readBytes<4>(res.b); + br.readBytes<2>(res.c); + br.readBytes<1>(res.d); + br.readBytes<8>(res.a); + br.readBytes<1>(res.e); + br.readBuffer<1>(res.f, 2); + EXPECT_THAT(br.error(), Eq(bitsery::ReaderError::NoError)); + // assert results + EXPECT_THAT(data.a, Eq(res.a)); + EXPECT_THAT(data.b, Eq(res.b)); + EXPECT_THAT(data.c, Eq(res.c)); + EXPECT_THAT(data.d, Eq(res.d)); + EXPECT_THAT(data.e, Eq(res.e)); + EXPECT_THAT(data.f, ContainerEq(res.f)); } -TEST(DataBitsAndBytesOperations, WriteAndReadBytesWithBitPackingWrapper) { - //setup data - IntegralTypes data; - data.a = -4894541654564; - data.b = 94545646; - data.c = -8778; - data.d = 200; - data.e = -98; - data.f[0] = 43; - data.f[1] = -45; +TEST(DataBitsAndBytesOperations, WriteAndReadBytesWithBitPackingWrapper) +{ + // setup data + IntegralTypes data; + data.a = -4894541654564; + data.b = 94545646; + data.c = -8778; + data.d = 200; + data.e = -98; + data.f[0] = 43; + data.f[1] = -45; - //create and write to buffer - Buffer buf{}; - Writer bw{buf}; - AdapterBitPackingWriter bpw{bw}; - bpw.writeBytes<4>(data.b); - bpw.writeBytes<2>(data.c); - bpw.writeBytes<1>(data.d); - bpw.writeBytes<8>(data.a); - bpw.writeBytes<1>(data.e); - bpw.writeBuffer<1>(data.f, 2); - bpw.flush(); - auto writtenSize = bpw.writtenBytesCount(); + // create and write to buffer + Buffer buf{}; + Writer bw{ buf }; + AdapterBitPackingWriter bpw{ bw }; + bpw.writeBytes<4>(data.b); + bpw.writeBytes<2>(data.c); + bpw.writeBytes<1>(data.d); + bpw.writeBytes<8>(data.a); + bpw.writeBytes<1>(data.e); + bpw.writeBuffer<1>(data.f, 2); + bpw.flush(); + auto writtenSize = bpw.writtenBytesCount(); - EXPECT_THAT(writtenSize, Eq(18)); - //read from buffer - Reader br{buf.begin(), writtenSize}; - AdapterBitPackingReader bpr{br}; - IntegralTypes res{}; - bpr.readBytes<4>(res.b); - bpr.readBytes<2>(res.c); - bpr.readBytes<1>(res.d); - bpr.readBytes<8>(res.a); - bpr.readBytes<1>(res.e); - bpr.readBuffer<1>(res.f, 2); - EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError)); - //assert results - - EXPECT_THAT(data.a, Eq(res.a)); - EXPECT_THAT(data.b, Eq(res.b)); - EXPECT_THAT(data.c, Eq(res.c)); - EXPECT_THAT(data.d, Eq(res.d)); - EXPECT_THAT(data.e, Eq(res.e)); - EXPECT_THAT(data.f, ContainerEq(res.f)); + EXPECT_THAT(writtenSize, Eq(18)); + // read from buffer + Reader br{ buf.begin(), writtenSize }; + AdapterBitPackingReader bpr{ br }; + IntegralTypes res{}; + bpr.readBytes<4>(res.b); + bpr.readBytes<2>(res.c); + bpr.readBytes<1>(res.d); + bpr.readBytes<8>(res.a); + bpr.readBytes<1>(res.e); + bpr.readBuffer<1>(res.f, 2); + EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError)); + // assert results + EXPECT_THAT(data.a, Eq(res.a)); + EXPECT_THAT(data.b, Eq(res.b)); + EXPECT_THAT(data.c, Eq(res.c)); + EXPECT_THAT(data.d, Eq(res.d)); + EXPECT_THAT(data.e, Eq(res.e)); + EXPECT_THAT(data.f, ContainerEq(res.f)); } -TEST(DataBitsAndBytesOperations, ReadWriteFncCanAcceptSignedData) { - //setup data - constexpr size_t DATA_SIZE = 3; - int16_t src[DATA_SIZE] {54,-4877,30067}; - //create and write to buffer - Buffer buf{}; - Writer bw{buf}; - bw.writeBuffer<2>(src, DATA_SIZE); - bw.flush(); - //read from buffer - Reader br1{buf.begin(), bw.writtenBytesCount()}; - int16_t dst[DATA_SIZE]{}; - br1.readBuffer<2>(dst, DATA_SIZE); - EXPECT_THAT(br1.error(), Eq(bitsery::ReaderError::NoError)); - EXPECT_THAT(dst, ContainerEq(src)); +TEST(DataBitsAndBytesOperations, ReadWriteFncCanAcceptSignedData) +{ + // setup data + constexpr size_t DATA_SIZE = 3; + int16_t src[DATA_SIZE]{ 54, -4877, 30067 }; + // create and write to buffer + Buffer buf{}; + Writer bw{ buf }; + bw.writeBuffer<2>(src, DATA_SIZE); + bw.flush(); + // read from buffer + Reader br1{ buf.begin(), bw.writtenBytesCount() }; + int16_t dst[DATA_SIZE]{}; + br1.readBuffer<2>(dst, DATA_SIZE); + EXPECT_THAT(br1.error(), Eq(bitsery::ReaderError::NoError)); + EXPECT_THAT(dst, ContainerEq(src)); } -TEST(DataBitsAndBytesOperations, ReadWriteCanWorkOnUnalignedData) { - //setup data - constexpr size_t DATA_SIZE = 3; - int16_t src[DATA_SIZE] {54,-4877,30067}; - //create and write to buffer - Buffer buf{}; - Writer bw{buf}; - AdapterBitPackingWriter bpw{bw}; - bpw.writeBits(15u, 4); - bpw.writeBuffer<2>(src, DATA_SIZE); - bpw.writeBits(12u, 4); - bpw.flush(); - auto writtenSize = bpw.writtenBytesCount(); - EXPECT_THAT(writtenSize, Eq(sizeof(src) + 1)); +TEST(DataBitsAndBytesOperations, ReadWriteCanWorkOnUnalignedData) +{ + // setup data + constexpr size_t DATA_SIZE = 3; + int16_t src[DATA_SIZE]{ 54, -4877, 30067 }; + // create and write to buffer + Buffer buf{}; + Writer bw{ buf }; + AdapterBitPackingWriter bpw{ bw }; + bpw.writeBits(15u, 4); + bpw.writeBuffer<2>(src, DATA_SIZE); + bpw.writeBits(12u, 4); + bpw.flush(); + auto writtenSize = bpw.writtenBytesCount(); + EXPECT_THAT(writtenSize, Eq(sizeof(src) + 1)); - //read from buffer - Reader br1{buf.begin(), writtenSize}; - AdapterBitPackingReader bpr1{br1}; - int16_t dst[DATA_SIZE]{}; - uint8_t tmp{}; - bpr1.readBits(tmp, 4); - EXPECT_THAT(tmp, Eq(15)); - bpr1.readBuffer<2>(dst, DATA_SIZE); - EXPECT_THAT(bpr1.error(), Eq(bitsery::ReaderError::NoError)); - EXPECT_THAT(dst, ContainerEq(src)); - bpr1.readBits(tmp, 4); - EXPECT_THAT(tmp, Eq(12)); + // read from buffer + Reader br1{ buf.begin(), writtenSize }; + AdapterBitPackingReader bpr1{ br1 }; + int16_t dst[DATA_SIZE]{}; + uint8_t tmp{}; + bpr1.readBits(tmp, 4); + EXPECT_THAT(tmp, Eq(15)); + bpr1.readBuffer<2>(dst, DATA_SIZE); + EXPECT_THAT(bpr1.error(), Eq(bitsery::ReaderError::NoError)); + EXPECT_THAT(dst, ContainerEq(src)); + bpr1.readBits(tmp, 4); + EXPECT_THAT(tmp, Eq(12)); } -TEST(DataBitsAndBytesOperations, RegressionTestReadBytesAfterReadBitsWithLotsOfZeroBits) { - //setup data - int16_t data[2]{0x0000, 0x7FFF}; - int16_t res[2]{}; - //create and write to buffer - Buffer buf{}; - Writer bw{buf}; - AdapterBitPackingWriter bpw{bw}; - bpw.writeBits(2u, 2); - bpw.writeBytes<2>(data[0]); - bpw.writeBytes<2>(data[1]); - bpw.align(); - bpw.flush(); +TEST(DataBitsAndBytesOperations, + RegressionTestReadBytesAfterReadBitsWithLotsOfZeroBits) +{ + // setup data + int16_t data[2]{ 0x0000, 0x7FFF }; + int16_t res[2]{}; + // create and write to buffer + Buffer buf{}; + Writer bw{ buf }; + AdapterBitPackingWriter bpw{ bw }; + bpw.writeBits(2u, 2); + bpw.writeBytes<2>(data[0]); + bpw.writeBytes<2>(data[1]); + bpw.align(); + bpw.flush(); - //read from buffer - Reader br{buf.begin(), bpw.writtenBytesCount()}; - AdapterBitPackingReader bpr{br}; - uint8_t tmp{}; - bpr.readBits(tmp, 2); - EXPECT_THAT(tmp, Eq(2)); - bpr.readBytes<2>(res[0]); - bpr.readBytes<2>(res[1]); - bpr.align(); - EXPECT_THAT(res[0], Eq(data[0])); - EXPECT_THAT(res[1], Eq(data[1])); + // read from buffer + Reader br{ buf.begin(), bpw.writtenBytesCount() }; + AdapterBitPackingReader bpr{ br }; + uint8_t tmp{}; + bpr.readBits(tmp, 2); + EXPECT_THAT(tmp, Eq(2)); + bpr.readBytes<2>(res[0]); + bpr.readBytes<2>(res[1]); + bpr.align(); + EXPECT_THAT(res[0], Eq(data[0])); + EXPECT_THAT(res[1], Eq(data[1])); } - diff --git a/tests/data_writing.cpp b/tests/data_writing.cpp index b52ca3c..8dd1c1f 100644 --- a/tests/data_writing.cpp +++ b/tests/data_writing.cpp @@ -1,111 +1,117 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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 -#include #include "serialization_test_utils.h" +#include -using testing::Eq; -using testing::ContainerEq; using bitsery::EndiannessType; +using testing::ContainerEq; +using testing::Eq; -template -class DataWriting:public testing::Test { +template +class DataWriting : public testing::Test +{ public: - using TWriter = bitsery::OutputBufferAdapter; - using TBuffer = BufType; + using TWriter = bitsery::OutputBufferAdapter; + using TBuffer = BufType; }; using NonFixedContainer = std::vector; using FixedContainer = std::array; -using ContainerTypes = ::testing::Types; +using ContainerTypes = ::testing::Types; -TYPED_TEST_SUITE(DataWriting, ContainerTypes,); +TYPED_TEST_SUITE(DataWriting, ContainerTypes, ); static constexpr size_t DATA_SIZE = 14u; -template -void writeData(BW& bw) { - uint16_t tmp1{45}, tmp2{6543}, tmp3{46533}; - uint32_t tmp4{8979445}, tmp5{7987564}; - bw.template writeBytes<2>(tmp1); - bw.template writeBytes<2>(tmp2); - bw.template writeBytes<2>(tmp3); - bw.template writeBytes<4>(tmp4); - bw.template writeBytes<4>(tmp5); +template +void +writeData(BW& bw) +{ + uint16_t tmp1{ 45 }, tmp2{ 6543 }, tmp3{ 46533 }; + uint32_t tmp4{ 8979445 }, tmp5{ 7987564 }; + bw.template writeBytes<2>(tmp1); + bw.template writeBytes<2>(tmp2); + bw.template writeBytes<2>(tmp3); + bw.template writeBytes<4>(tmp4); + bw.template writeBytes<4>(tmp5); } -TYPED_TEST(DataWriting, GetWrittenBytesCountReturnsActualBytesWritten) { - using TWriter = typename TestFixture::TWriter; - using TBuffer = typename TestFixture::TBuffer; - TBuffer buf{}; - TWriter bw{buf}; - writeData(bw); - bw.flush(); - auto writtenSize = bw.writtenBytesCount(); - EXPECT_THAT(writtenSize, DATA_SIZE); - EXPECT_THAT(buf.size(), ::testing::Ge(DATA_SIZE)); +TYPED_TEST(DataWriting, GetWrittenBytesCountReturnsActualBytesWritten) +{ + using TWriter = typename TestFixture::TWriter; + using TBuffer = typename TestFixture::TBuffer; + TBuffer buf{}; + TWriter bw{ buf }; + writeData(bw); + bw.flush(); + auto writtenSize = bw.writtenBytesCount(); + EXPECT_THAT(writtenSize, DATA_SIZE); + EXPECT_THAT(buf.size(), ::testing::Ge(DATA_SIZE)); } -TYPED_TEST(DataWriting, WhenWritingBitsThenMustFlushWriter) { - using TWriter = typename TestFixture::TWriter; - using TBuffer = typename TestFixture::TBuffer; - TBuffer buf{}; - TWriter bw{buf}; - bitsery::details::OutputAdapterBitPackingWrapper bpw{bw}; - bpw.writeBits(3u, 2); - auto writtenSize1 = bpw.writtenBytesCount(); - bpw.flush(); - auto writtenSize2 = bpw.writtenBytesCount(); - EXPECT_THAT(writtenSize1, Eq(0)); - EXPECT_THAT(writtenSize2, Eq(1)); +TYPED_TEST(DataWriting, WhenWritingBitsThenMustFlushWriter) +{ + using TWriter = typename TestFixture::TWriter; + using TBuffer = typename TestFixture::TBuffer; + TBuffer buf{}; + TWriter bw{ buf }; + bitsery::details::OutputAdapterBitPackingWrapper bpw{ bw }; + bpw.writeBits(3u, 2); + auto writtenSize1 = bpw.writtenBytesCount(); + bpw.flush(); + auto writtenSize2 = bpw.writtenBytesCount(); + EXPECT_THAT(writtenSize1, Eq(0)); + EXPECT_THAT(writtenSize2, Eq(1)); } -TYPED_TEST(DataWriting, WhenDataAlignedThenFlushHasNoEffect) { - using TWriter = typename TestFixture::TWriter; - using TBuffer = typename TestFixture::TBuffer; - TBuffer buf{}; - TWriter bw{buf}; - bitsery::details::OutputAdapterBitPackingWrapper bpw{bw}; - bpw.writeBits(3u, 2); - bpw.align(); - auto writtenSize1 = bpw.writtenBytesCount(); - bpw.flush(); - auto writtenSize2 = bpw.writtenBytesCount(); - EXPECT_THAT(writtenSize1, Eq(1)); - EXPECT_THAT(writtenSize2, Eq(1)); - +TYPED_TEST(DataWriting, WhenDataAlignedThenFlushHasNoEffect) +{ + using TWriter = typename TestFixture::TWriter; + using TBuffer = typename TestFixture::TBuffer; + TBuffer buf{}; + TWriter bw{ buf }; + bitsery::details::OutputAdapterBitPackingWrapper bpw{ bw }; + bpw.writeBits(3u, 2); + bpw.align(); + auto writtenSize1 = bpw.writtenBytesCount(); + bpw.flush(); + auto writtenSize2 = bpw.writtenBytesCount(); + EXPECT_THAT(writtenSize1, Eq(1)); + EXPECT_THAT(writtenSize2, Eq(1)); } -TEST(DataWritingNonFixedBufferContainer, ContainerIsAlwaysResizedToCapacity) { - NonFixedContainer buf{}; - bitsery::OutputBufferAdapter bw{buf}; - for (auto i = 0; i < 5; ++i) { - uint32_t tmp{}; - bw.writeBytes<4>(tmp); - bw.writeBytes<4>(tmp); - EXPECT_TRUE(buf.size() == buf.capacity()); - } +TEST(DataWritingNonFixedBufferContainer, ContainerIsAlwaysResizedToCapacity) +{ + NonFixedContainer buf{}; + bitsery::OutputBufferAdapter bw{ buf }; + for (auto i = 0; i < 5; ++i) { + uint32_t tmp{}; + bw.writeBytes<4>(tmp); + bw.writeBytes<4>(tmp); + EXPECT_TRUE(buf.size() == buf.capacity()); + } } diff --git a/tests/not_default_constructible.cpp b/tests/not_default_constructible.cpp index bfccbde..3bd8033 100644 --- a/tests/not_default_constructible.cpp +++ b/tests/not_default_constructible.cpp @@ -1,351 +1,394 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. +// 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 -#include -#include #include +#include +#include #include +#include +#include -#include #include "serialization_test_utils.h" - +#include using testing::ContainerEq; using testing::Eq; -//forward declare, for testing with std::unordered_map +// forward declare, for testing with std::unordered_map class HasherForNonDefaultConstructible; -class NonDefaultConstructible { - int32_t i{0}; - friend class HasherForNonDefaultConstructible; +class NonDefaultConstructible +{ + int32_t i{ 0 }; + friend class HasherForNonDefaultConstructible; + friend class bitsery::Access; + NonDefaultConstructible() = default; - - - friend class bitsery::Access; - NonDefaultConstructible() = default; - - template - void serialize(S& s) { - s.value4b(i); - } + template + void serialize(S& s) + { + s.value4b(i); + } public: + explicit NonDefaultConstructible(int32_t v) + : i{ v } + { + } - explicit NonDefaultConstructible(int32_t v):i{v} {} + bool operator==(const NonDefaultConstructible& other) const + { + return i == other.i; + } - bool operator == (const NonDefaultConstructible& other) const { - return i == other.i; - } - - bool operator < (const NonDefaultConstructible& other) const { - return i < other.i; - } + bool operator<(const NonDefaultConstructible& other) const + { + return i < other.i; + } }; -class HasherForNonDefaultConstructible { +class HasherForNonDefaultConstructible +{ public: - size_t operator()(const NonDefaultConstructible& o) const { - return std::hash()(o.i); - } + size_t operator()(const NonDefaultConstructible& o) const + { + return std::hash()(o.i); + } }; +TEST(DeserializeNonDefaultConstructible, Container) +{ + SerializationContext ctx{}; + std::vector data{}; + data.emplace_back(1); + data.emplace_back(2); + data.emplace_back(3); + std::vector res{}; + ctx.createSerializer().container(data, 10); + ctx.createDeserializer().container(res, 10); + EXPECT_THAT(res, ContainerEq(data)); +} +// this test is here, because when object is not constructible we cannot simple +// "resize" container +TEST(DeserializeNonDefaultConstructible, ResultContainerShouldShrink) +{ + SerializationContext ctx{}; + std::vector data{}; + data.emplace_back(1); + std::vector res{}; + res.emplace_back(2); + res.emplace_back(3); + res.emplace_back(4); -TEST(DeserializeNonDefaultConstructible, Container) { + ctx.createSerializer().container(data, 10); + ctx.createDeserializer().container(res, 10); + + EXPECT_THAT(res, ContainerEq(data)); +} + +TEST(DeserializeNonDefaultConstructible, ResultStdForwardListShouldShrink) +{ + // forward list doesn't have .erase function, bet has erase_after + // in this case, if new size is 0 it must call clear, so we need to check two + // cases + { + // 1) when result should have more than 0 elements SerializationContext ctx{}; - std::vector data{}; - data.emplace_back(1); - data.emplace_back(2); - data.emplace_back(3); - std::vector res{}; + std::forward_list data{}; + data.push_front(NonDefaultConstructible{ 1 }); + std::forward_list res{}; + res.push_front(NonDefaultConstructible{ 21 }); + res.push_front(NonDefaultConstructible{ 14 }); ctx.createSerializer().container(data, 10); ctx.createDeserializer().container(res, 10); - EXPECT_THAT(res, ContainerEq(data)); -} -//this test is here, because when object is not constructible we cannot simple "resize" container -TEST(DeserializeNonDefaultConstructible, ResultContainerShouldShrink) { + auto resIt = res.begin(); + for (auto it = data.begin(); it != data.end(); ++it, ++resIt) { + EXPECT_THAT(*resIt, Eq(*it)); + } + EXPECT_THAT(resIt, Eq(res.end())); + } + { + // 1) when result should have 0 elements SerializationContext ctx{}; - std::vector data{}; - data.emplace_back(1); - std::vector res{}; - res.emplace_back(2); - res.emplace_back(3); - res.emplace_back(4); + std::forward_list data{}; + std::forward_list res{}; + res.push_front(NonDefaultConstructible{ 1 }); + res.push_front(NonDefaultConstructible{ 14 }); ctx.createSerializer().container(data, 10); ctx.createDeserializer().container(res, 10); - EXPECT_THAT(res, ContainerEq(data)); -} + EXPECT_THAT(res.begin(), Eq(res.end())); + } -TEST(DeserializeNonDefaultConstructible, ResultStdForwardListShouldShrink) { - // forward list doesn't have .erase function, bet has erase_after - // in this case, if new size is 0 it must call clear, so we need to check two cases - { - // 1) when result should have more than 0 elements - SerializationContext ctx{}; - std::forward_list data{}; - data.push_front(NonDefaultConstructible{1}); - std::forward_list res{}; - res.push_front(NonDefaultConstructible{21}); - res.push_front(NonDefaultConstructible{14}); - - ctx.createSerializer().container(data, 10); - ctx.createDeserializer().container(res, 10); - - auto resIt = res.begin(); - for (auto it = data.begin(); it != data.end(); ++it, ++resIt) { - EXPECT_THAT(*resIt, Eq(*it)); - } - EXPECT_THAT(resIt, Eq(res.end())); - - } - { - // 1) when result should have 0 elements - SerializationContext ctx{}; - std::forward_list data{}; - std::forward_list res{}; - res.push_front(NonDefaultConstructible{1}); - res.push_front(NonDefaultConstructible{14}); - - ctx.createSerializer().container(data, 10); - ctx.createDeserializer().container(res, 10); - - EXPECT_THAT(res.begin(), Eq(res.end())); - - } - - { - // also check if correctly expands if source is bigger than destination - SerializationContext ctx{}; - std::forward_list data{}; - data.push_front(NonDefaultConstructible{1}); - data.push_front(NonDefaultConstructible{14}); - std::forward_list res{}; - - ctx.createSerializer().container(data, 10); - ctx.createDeserializer().container(res, 10); - - auto resIt = res.begin(); - for (auto it = data.begin(); it != data.end(); ++it, ++resIt) { - EXPECT_THAT(*resIt, Eq(*it)); - } - EXPECT_THAT(resIt, Eq(res.end())); - } -} - -TEST(DeserializeNonDefaultConstructible, StdSet) { + { + // also check if correctly expands if source is bigger than destination SerializationContext ctx{}; - std::set data; - data.insert(NonDefaultConstructible{1}); - data.insert(NonDefaultConstructible{2}); - std::set res{}; - data.insert(NonDefaultConstructible{3}); + std::forward_list data{}; + data.push_front(NonDefaultConstructible{ 1 }); + data.push_front(NonDefaultConstructible{ 14 }); + std::forward_list res{}; - ctx.createSerializer().ext(data, bitsery::ext::StdSet{10}); - ctx.createDeserializer().ext(res, bitsery::ext::StdSet{10}); + ctx.createSerializer().container(data, 10); + ctx.createDeserializer().container(res, 10); - EXPECT_THAT(res, ContainerEq(data)); + auto resIt = res.begin(); + for (auto it = data.begin(); it != data.end(); ++it, ++resIt) { + EXPECT_THAT(*resIt, Eq(*it)); + } + EXPECT_THAT(resIt, Eq(res.end())); + } } -TEST(DeserializeNonDefaultConstructible, StdMap) { - SerializationContext ctx{}; - std::unordered_map data; - data.emplace(NonDefaultConstructible{2}, NonDefaultConstructible{3}); +TEST(DeserializeNonDefaultConstructible, StdSet) +{ + SerializationContext ctx{}; + std::set data; + data.insert(NonDefaultConstructible{ 1 }); + data.insert(NonDefaultConstructible{ 2 }); + std::set res{}; + data.insert(NonDefaultConstructible{ 3 }); - std::unordered_map res{}; - data.emplace(NonDefaultConstructible{2}, NonDefaultConstructible{3}); - data.emplace(NonDefaultConstructible{4}, NonDefaultConstructible{4}); + ctx.createSerializer().ext(data, bitsery::ext::StdSet{ 10 }); + ctx.createDeserializer().ext(res, bitsery::ext::StdSet{ 10 }); - auto& ser = ctx.createSerializer(); - ser.ext(data, bitsery::ext::StdMap{10},[](decltype(ser)& ser, NonDefaultConstructible& key, NonDefaultConstructible& value) { - ser.object(key); - ser.object(value); - }); - auto& des = ctx.createDeserializer(); - des.ext(res, bitsery::ext::StdMap{10},[](decltype(des)& des, NonDefaultConstructible& key, NonDefaultConstructible& value) { - des.object(key); - des.object(value); - }); - - EXPECT_THAT(res, ContainerEq(data)); + EXPECT_THAT(res, ContainerEq(data)); } +TEST(DeserializeNonDefaultConstructible, StdMap) +{ + SerializationContext ctx{}; + std::unordered_map + data; + data.emplace(NonDefaultConstructible{ 2 }, NonDefaultConstructible{ 3 }); -struct NonPolymorphicPointers { - NonDefaultConstructible* pp; - std::unique_ptr up; - std::shared_ptr sp; - std::weak_ptr wp; + std::unordered_map + res{}; + data.emplace(NonDefaultConstructible{ 2 }, NonDefaultConstructible{ 3 }); + data.emplace(NonDefaultConstructible{ 4 }, NonDefaultConstructible{ 4 }); + + auto& ser = ctx.createSerializer(); + ser.ext(data, + bitsery::ext::StdMap{ 10 }, + [](decltype(ser)& ser, + NonDefaultConstructible& key, + NonDefaultConstructible& value) { + ser.object(key); + ser.object(value); + }); + auto& des = ctx.createDeserializer(); + des.ext(res, + bitsery::ext::StdMap{ 10 }, + [](decltype(des)& des, + NonDefaultConstructible& key, + NonDefaultConstructible& value) { + des.object(key); + des.object(value); + }); + + EXPECT_THAT(res, ContainerEq(data)); +} + +struct NonPolymorphicPointers +{ + NonDefaultConstructible* pp; + std::unique_ptr up; + std::shared_ptr sp; + std::weak_ptr wp; }; -template -void serialize(S& s, NonPolymorphicPointers& o) { - s.ext(o.pp, bitsery::ext::PointerOwner{}); - s.ext(o.up, bitsery::ext::StdSmartPtr{}); - s.ext(o.sp, bitsery::ext::StdSmartPtr{}); - s.ext(o.wp, bitsery::ext::StdSmartPtr{}); +template +void +serialize(S& s, NonPolymorphicPointers& o) +{ + s.ext(o.pp, bitsery::ext::PointerOwner{}); + s.ext(o.up, bitsery::ext::StdSmartPtr{}); + s.ext(o.sp, bitsery::ext::StdSmartPtr{}); + s.ext(o.wp, bitsery::ext::StdSmartPtr{}); } -TEST(DeserializeNonDefaultConstructible, NonPolymorphicPointerAndSmartPointer) { - using SerContext = BasicSerializationContext; - SerContext ctx{}; - NonPolymorphicPointers data{}; - data.pp = new NonDefaultConstructible{3}; - data.up = std::unique_ptr(new NonDefaultConstructible{54}); - data.sp = std::shared_ptr(new NonDefaultConstructible{-481}); - data.wp = data.sp; +TEST(DeserializeNonDefaultConstructible, NonPolymorphicPointerAndSmartPointer) +{ + using SerContext = + BasicSerializationContext; + SerContext ctx{}; + NonPolymorphicPointers data{}; + data.pp = new NonDefaultConstructible{ 3 }; + data.up = + std::unique_ptr(new NonDefaultConstructible{ 54 }); + data.sp = std::shared_ptr( + new NonDefaultConstructible{ -481 }); + data.wp = data.sp; - NonPolymorphicPointers res{}; - bitsery::ext::PointerLinkingContext plctx1{}; - ctx.createSerializer(plctx1).object(data); - ctx.createDeserializer(plctx1).object(res); + NonPolymorphicPointers res{}; + bitsery::ext::PointerLinkingContext plctx1{}; + ctx.createSerializer(plctx1).object(data); + ctx.createDeserializer(plctx1).object(res); - EXPECT_THAT(*res.pp, Eq(*data.pp)); - delete res.pp; - delete data.pp; - EXPECT_THAT(*res.up, Eq(*data.up)); - EXPECT_THAT(*res.sp, Eq(*data.sp)); - EXPECT_THAT(*(res.wp.lock()), Eq(*(data.wp.lock()))); + EXPECT_THAT(*res.pp, Eq(*data.pp)); + delete res.pp; + delete data.pp; + EXPECT_THAT(*res.up, Eq(*data.up)); + EXPECT_THAT(*res.sp, Eq(*data.sp)); + EXPECT_THAT(*(res.wp.lock()), Eq(*(data.wp.lock()))); } -class PolymorphicNDCBase { +class PolymorphicNDCBase +{ public: - virtual ~PolymorphicNDCBase() = 0; - template - void serialize(S& ) {} + virtual ~PolymorphicNDCBase() = 0; + template + void serialize(S&) + { + } }; - PolymorphicNDCBase::~PolymorphicNDCBase() = default; -class PolymorphicNDC1:public PolymorphicNDCBase { - int8_t i{}; - friend class bitsery::Access; +class PolymorphicNDC1 : public PolymorphicNDCBase +{ + int8_t i{}; + friend class bitsery::Access; + + template + void serialize(S& s) + { + s.value1b(i); + } - template - void serialize(S& s) { - s.value1b(i); - } public: - PolymorphicNDC1() = default; - PolymorphicNDC1(int8_t v):i{v} {} - bool operator == (const PolymorphicNDC1& other) const { - return i == other.i; - } + PolymorphicNDC1() = default; + PolymorphicNDC1(int8_t v) + : i{ v } + { + } + bool operator==(const PolymorphicNDC1& other) const { return i == other.i; } }; -class PolymorphicNDC2:public PolymorphicNDCBase { - uint16_t ui{}; +class PolymorphicNDC2 : public PolymorphicNDCBase +{ + uint16_t ui{}; - friend class bitsery::Access; + friend class bitsery::Access; + + template + void serialize(S& s) + { + s.value2b(ui); + } - template - void serialize(S& s) { - s.value2b(ui); - } public: - PolymorphicNDC2() = default; - PolymorphicNDC2(uint16_t v):ui{v} {} - bool operator == (const PolymorphicNDC2& other) const { - return ui == other.ui; - } - + PolymorphicNDC2() = default; + PolymorphicNDC2(uint16_t v) + : ui{ v } + { + } + bool operator==(const PolymorphicNDC2& other) const { return ui == other.ui; } }; - namespace bitsery { - namespace ext { +namespace ext { - template<> - struct PolymorphicBaseClass : PolymorphicDerivedClasses { - }; - } +template<> +struct PolymorphicBaseClass + : PolymorphicDerivedClasses +{ +}; +} } - -struct PolymorphicPointers { - PolymorphicNDCBase* pp; - std::unique_ptr up; - std::shared_ptr sp; - std::weak_ptr wp; +struct PolymorphicPointers +{ + PolymorphicNDCBase* pp; + std::unique_ptr up; + std::shared_ptr sp; + std::weak_ptr wp; }; -template -void serialize(S& s, PolymorphicPointers& o) { - s.ext(o.pp, bitsery::ext::PointerOwner{}); - s.ext(o.up, bitsery::ext::StdSmartPtr{}); - s.ext(o.sp, bitsery::ext::StdSmartPtr{}); - s.ext(o.wp, bitsery::ext::StdSmartPtr{}); +template +void +serialize(S& s, PolymorphicPointers& o) +{ + s.ext(o.pp, bitsery::ext::PointerOwner{}); + s.ext(o.up, bitsery::ext::StdSmartPtr{}); + s.ext(o.sp, bitsery::ext::StdSmartPtr{}); + s.ext(o.wp, bitsery::ext::StdSmartPtr{}); } -TEST(DeserializeNonDefaultConstructible, PolymorphicPointerAndSmartPointer) { - using TContext = std::tuple>; - using SerContext = BasicSerializationContext; - SerContext ctx{}; - PolymorphicPointers data{}; - data.pp = new PolymorphicNDC1{-4}; - data.up = std::unique_ptr(new PolymorphicNDC2{54}); - data.sp = std::shared_ptr(new PolymorphicNDC1{15}); - data.wp = data.sp; +TEST(DeserializeNonDefaultConstructible, PolymorphicPointerAndSmartPointer) +{ + using TContext = + std::tuple>; + using SerContext = BasicSerializationContext; + SerContext ctx{}; + PolymorphicPointers data{}; + data.pp = new PolymorphicNDC1{ -4 }; + data.up = std::unique_ptr(new PolymorphicNDC2{ 54 }); + data.sp = std::shared_ptr(new PolymorphicNDC1{ 15 }); + data.wp = data.sp; - PolymorphicPointers res{}; + PolymorphicPointers res{}; - TContext serCtx{}; - TContext desCtx{}; + TContext serCtx{}; + TContext desCtx{}; - std::get<1>(serCtx).registerBasesList(bitsery::ext::PolymorphicClassesList{}); - std::get<1>(desCtx).registerBasesList(bitsery::ext::PolymorphicClassesList{}); + std::get<1>(serCtx).registerBasesList( + bitsery::ext::PolymorphicClassesList{}); + std::get<1>(desCtx).registerBasesList( + bitsery::ext::PolymorphicClassesList{}); - ctx.createSerializer(serCtx).object(data); - ctx.createDeserializer(desCtx).object(res); - auto respp = dynamic_cast(res.pp); - auto resup = dynamic_cast(res.up.get()); - auto ressp = dynamic_cast(res.sp.get()); - auto reswp = dynamic_cast(res.wp.lock().get()); + ctx.createSerializer(serCtx).object(data); + ctx.createDeserializer(desCtx).object(res); + auto respp = dynamic_cast(res.pp); + auto resup = dynamic_cast(res.up.get()); + auto ressp = dynamic_cast(res.sp.get()); + auto reswp = dynamic_cast(res.wp.lock().get()); - auto datapp = dynamic_cast(data.pp); - auto dataup = dynamic_cast(data.up.get()); - auto datasp = dynamic_cast(data.sp.get()); - auto datawp = dynamic_cast(data.wp.lock().get()); + auto datapp = dynamic_cast(data.pp); + auto dataup = dynamic_cast(data.up.get()); + auto datasp = dynamic_cast(data.sp.get()); + auto datawp = dynamic_cast(data.wp.lock().get()); - EXPECT_THAT(respp, ::testing::Ne(nullptr)); - EXPECT_THAT(resup, ::testing::Ne(nullptr)); - EXPECT_THAT(ressp, ::testing::Ne(nullptr)); - EXPECT_THAT(reswp, ::testing::Ne(nullptr)); + EXPECT_THAT(respp, ::testing::Ne(nullptr)); + EXPECT_THAT(resup, ::testing::Ne(nullptr)); + EXPECT_THAT(ressp, ::testing::Ne(nullptr)); + EXPECT_THAT(reswp, ::testing::Ne(nullptr)); - EXPECT_THAT(*respp, Eq(*datapp)); - delete res.pp; - delete data.pp; - EXPECT_THAT(*resup, Eq(*dataup)); - EXPECT_THAT(*ressp, Eq(*datasp)); - EXPECT_THAT(*reswp, Eq(*datawp)); - std::get<0>(serCtx).clearSharedState(); - std::get<0>(desCtx).clearSharedState(); + EXPECT_THAT(*respp, Eq(*datapp)); + delete res.pp; + delete data.pp; + EXPECT_THAT(*resup, Eq(*dataup)); + EXPECT_THAT(*ressp, Eq(*datasp)); + EXPECT_THAT(*reswp, Eq(*datawp)); + std::get<0>(serCtx).clearSharedState(); + std::get<0>(desCtx).clearSharedState(); } diff --git a/tests/serialization.cpp b/tests/serialization.cpp index d1a6625..4e3d021 100644 --- a/tests/serialization.cpp +++ b/tests/serialization.cpp @@ -1,48 +1,48 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. +// 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::Eq; -TEST(Serialization, AdapterCanBeMovedInAndOut) { - Buffer buf{}; - bitsery::Serializer ser1{buf}; - ser1.object(MyStruct1{1, 2}); - auto writeAdapter = std::move(ser1).adapter(); - bitsery::Serializer ser2(std::move(writeAdapter)); - ser2.object(MyStruct1{3, 4}); - auto writtenBytesCount = ser2.adapter().writtenBytesCount(); - EXPECT_THAT(writtenBytesCount, Eq(MyStruct1::SIZE + MyStruct1::SIZE)); +TEST(Serialization, AdapterCanBeMovedInAndOut) +{ + Buffer buf{}; + bitsery::Serializer ser1{ buf }; + ser1.object(MyStruct1{ 1, 2 }); + auto writeAdapter = std::move(ser1).adapter(); + bitsery::Serializer ser2(std::move(writeAdapter)); + ser2.object(MyStruct1{ 3, 4 }); + auto writtenBytesCount = ser2.adapter().writtenBytesCount(); + EXPECT_THAT(writtenBytesCount, Eq(MyStruct1::SIZE + MyStruct1::SIZE)); - MyStruct1 res{}; - bitsery::Deserializer des1{buf.begin(), writtenBytesCount}; - des1.object(res); - EXPECT_THAT(res, Eq(MyStruct1{1, 2})); - auto readerAdapter = std::move(des1).adapter(); - bitsery::Deserializer des2(std::move(readerAdapter)); - des2.object(res); - EXPECT_THAT(res, Eq(MyStruct1{3, 4})); - EXPECT_TRUE(des2.adapter().isCompletedSuccessfully()); + MyStruct1 res{}; + bitsery::Deserializer des1{ buf.begin(), writtenBytesCount }; + des1.object(res); + EXPECT_THAT(res, Eq(MyStruct1{ 1, 2 })); + auto readerAdapter = std::move(des1).adapter(); + bitsery::Deserializer des2(std::move(readerAdapter)); + des2.object(res); + EXPECT_THAT(res, Eq(MyStruct1{ 3, 4 })); + EXPECT_TRUE(des2.adapter().isCompletedSuccessfully()); } diff --git a/tests/serialization_bool.cpp b/tests/serialization_bool.cpp index 47b5949..7f3c79f 100644 --- a/tests/serialization_bool.cpp +++ b/tests/serialization_bool.cpp @@ -1,83 +1,88 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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::Eq; +TEST(SerializeBooleans, BoolAsBit) +{ -TEST(SerializeBooleans, BoolAsBit) { - - SerializationContext ctx{}; - bool t1{true}; - bool t2{false}; - bool res1; - bool res2; - auto& ser = ctx.createSerializer(); - ser.enableBitPacking([&t1, &t2](SerializationContext::TSerializerBPEnabled& sbp) { - sbp.boolValue(t1); - sbp.boolValue(t2); + SerializationContext ctx{}; + bool t1{ true }; + bool t2{ false }; + bool res1; + bool res2; + auto& ser = ctx.createSerializer(); + ser.enableBitPacking( + [&t1, &t2](SerializationContext::TSerializerBPEnabled& sbp) { + sbp.boolValue(t1); + sbp.boolValue(t2); }); - auto& des = ctx.createDeserializer(); - des.enableBitPacking([&res1, &res2](SerializationContext::TDeserializerBPEnabled& sbp) { - sbp.boolValue(res1); - sbp.boolValue(res2); + auto& des = ctx.createDeserializer(); + des.enableBitPacking( + [&res1, &res2](SerializationContext::TDeserializerBPEnabled& sbp) { + sbp.boolValue(res1); + sbp.boolValue(res2); }); - EXPECT_THAT(res1, Eq(t1)); - EXPECT_THAT(res2, Eq(t2)); - EXPECT_THAT(ctx.getBufferSize(), Eq(1)); + EXPECT_THAT(res1, Eq(t1)); + EXPECT_THAT(res2, Eq(t2)); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); } -TEST(SerializeBooleans, BoolAsByte) { - SerializationContext ctx; - bool t1{true}; - bool t2{false}; - bool res1; - bool res2; - auto& ser = ctx.createSerializer(); - ser.boolValue(t1); - ser.boolValue(t2); - auto& des = ctx.createDeserializer(); - des.boolValue(res1); - des.boolValue(res2); +TEST(SerializeBooleans, BoolAsByte) +{ + SerializationContext ctx; + bool t1{ true }; + bool t2{ false }; + bool res1; + bool res2; + auto& ser = ctx.createSerializer(); + ser.boolValue(t1); + ser.boolValue(t2); + auto& des = ctx.createDeserializer(); + des.boolValue(res1); + des.boolValue(res2); - EXPECT_THAT(res1, Eq(t1)); - EXPECT_THAT(res2, Eq(t2)); - EXPECT_THAT(ctx.getBufferSize(), Eq(2)); + EXPECT_THAT(res1, Eq(t1)); + EXPECT_THAT(res2, Eq(t2)); + EXPECT_THAT(ctx.getBufferSize(), Eq(2)); } -TEST(SerializeBooleans, WhenReadingBoolByteReadsMoreThanOneThenInvalidDataErrorAndResultIsFalse) { - SerializationContext ctx; - auto& ser = ctx.createSerializer(); - ser.value1b(uint8_t{1}); - ser.value1b(uint8_t{2}); - bool res{}; - auto& des = ctx.createDeserializer(); - des.boolValue(res); - EXPECT_THAT(res, Eq(true)); - des.boolValue(res); - EXPECT_THAT(res, Eq(false)); - EXPECT_THAT(ctx.des->adapter().error(), Eq(bitsery::ReaderError::InvalidData)); +TEST(SerializeBooleans, + WhenReadingBoolByteReadsMoreThanOneThenInvalidDataErrorAndResultIsFalse) +{ + SerializationContext ctx; + auto& ser = ctx.createSerializer(); + ser.value1b(uint8_t{ 1 }); + ser.value1b(uint8_t{ 2 }); + bool res{}; + auto& des = ctx.createDeserializer(); + des.boolValue(res); + EXPECT_THAT(res, Eq(true)); + des.boolValue(res); + EXPECT_THAT(res, Eq(false)); + EXPECT_THAT(ctx.des->adapter().error(), + Eq(bitsery::ReaderError::InvalidData)); } \ No newline at end of file diff --git a/tests/serialization_container.cpp b/tests/serialization_container.cpp index 8a2fd08..9c14205 100644 --- a/tests/serialization_container.cpp +++ b/tests/serialization_container.cpp @@ -1,74 +1,68 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - - +// 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 #include #include +#include -#include #include "serialization_test_utils.h" +#include using testing::ContainerEq; using testing::Eq; - /* * overload to get container of types */ template -Container getFilledContainer() { - return {1, 2, 3, 4, 5, 78, 456, 8, 54}; +Container +getFilledContainer() +{ + return { 1, 2, 3, 4, 5, 78, 456, 8, 54 }; } template<> -std::vector getFilledContainer>() { - return { - {0, 1}, - {2, 3}, - {4, 5}, - {6, 7}, - {8, 9}, - {11, 34}, - {5134, 1532} - }; +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}} - }; +std::list +getFilledContainer>() +{ + return { { MyStruct2::V1, { 0, 1 } }, { MyStruct2::V3, { -45, 45 } } }; } -struct EmptyFtor { - template - void operator() (S& , T& ) { - - } +struct EmptyFtor +{ + template + void operator()(S&, T&) + { + } }; /* @@ -76,197 +70,228 @@ struct EmptyFtor { */ template -class SerializeContainerDynamicSizeArthmeticTypes : public testing::Test { +class SerializeContainerDynamicSizeArthmeticTypes : public testing::Test +{ public: - using TContainer = T; - using TValue = typename T::value_type; + using TContainer = T; + using TValue = typename T::value_type; - const TContainer src = getFilledContainer(); - TContainer res{}; + const TContainer src = getFilledContainer(); + TContainer res{}; - size_t getExpectedBufSize(const SerializationContext &ctx) const { - auto size = bitsery::traits::ContainerTraits::size(src); - return ctx.containerSizeSerializedBytesCount(size) + size * sizeof(TValue); - } + size_t getExpectedBufSize(const SerializationContext& ctx) const + { + auto size = bitsery::traits::ContainerTraits::size(src); + return ctx.containerSizeSerializedBytesCount(size) + 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::forward_list, - std::deque>; +// std::forward_list is not supported, because it doesn't have size() method +using SequenceContainersWithArthmeticTypes = + ::testing::Types, + std::list, + std::forward_list, + std::deque>; -TYPED_TEST_SUITE(SerializeContainerDynamicSizeArthmeticTypes, SequenceContainersWithArthmeticTypes,); +TYPED_TEST_SUITE(SerializeContainerDynamicSizeArthmeticTypes, + SequenceContainersWithArthmeticTypes, ); -TYPED_TEST(SerializeContainerDynamicSizeArthmeticTypes, Values) { - SerializationContext ctx{}; - using TValue = typename TestFixture::TValue; +TYPED_TEST(SerializeContainerDynamicSizeArthmeticTypes, Values) +{ + SerializationContext ctx{}; + using TValue = typename TestFixture::TValue; - ctx.createSerializer().container(this->src, 1000); - ctx.createDeserializer().container(this->res, 1000); + 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)); + EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx))); + EXPECT_THAT(this->res, ContainerEq(this->src)); } -TYPED_TEST(SerializeContainerDynamicSizeArthmeticTypes, CustomFunctionIncrements) { - SerializationContext ctx{}; - using TValue = typename TestFixture::TValue; +TYPED_TEST(SerializeContainerDynamicSizeArthmeticTypes, + CustomFunctionIncrements) +{ + SerializationContext ctx{}; + using TValue = typename TestFixture::TValue; - auto& ser = ctx.createSerializer(); - ser.container(this->src, 1000, [](decltype(ser)& ser, TValue& v) { - ser.template value(v); - }); - auto& des = ctx.createDeserializer(); - des.container(this->res, 1000, [](decltype(des)& des, TValue &v) { - des.template value(v); - //increment by 1 after reading - v++; - }); - //decrement result by 1, before comparing for eq - for (auto &v:this->res) - v = static_cast(v-1); + auto& ser = ctx.createSerializer(); + ser.container(this->src, 1000, [](decltype(ser)& ser, TValue& v) { + ser.template value(v); + }); + auto& des = ctx.createDeserializer(); + des.container(this->res, 1000, [](decltype(des)& des, TValue& v) { + des.template value(v); + // increment by 1 after reading + v++; + }); + // decrement result by 1, before comparing for eq + for (auto& v : this->res) + v = static_cast(v - 1); - EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx))); - EXPECT_THAT(this->res, ContainerEq(this->src)); -} - - -template -class SerializeContainerDynamicSizeCompositeTypes : 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; - } -}; - - -using SerializeContainerDynamicSizeWithCompositeTypes = ::testing::Types< - std::vector, - std::list>; - -TYPED_TEST_SUITE(SerializeContainerDynamicSizeCompositeTypes, SerializeContainerDynamicSizeWithCompositeTypes,); - -TYPED_TEST(SerializeContainerDynamicSizeCompositeTypes, 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(SerializeContainerDynamicSizeCompositeTypes, CustomFunctionThatDoNothing) { - SerializationContext ctx{}; - - ctx.createSerializer().container(this->src, 1000, EmptyFtor{}); - ctx.createDeserializer().container(this->res, 1000, EmptyFtor{}); - - EXPECT_THAT(ctx.getBufferSize(), Eq(ctx.containerSizeSerializedBytesCount(this->src.size()))); + EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx))); + EXPECT_THAT(this->res, ContainerEq(this->src)); } template -class SerializeContainerFixedSizeArithmeticTypes : public testing::Test { +class SerializeContainerDynamicSizeCompositeTypes : public testing::Test +{ public: - using TContainer = T; + using TContainer = T; + using TValue = typename T::value_type; - size_t getContainerSize() { - T tmp{}; - return static_cast(std::distance(std::begin(tmp), std::end(tmp))); - } + const TContainer src = getFilledContainer(); + TContainer res{}; + + size_t getExpectedBufSize(const SerializationContext& ctx) const + { + return ctx.containerSizeSerializedBytesCount(src.size()) + + src.size() * TValue::SIZE; + } }; -using StaticContainersWithIntegralTypes = ::testing::Types< - std::array, - int16_t[4]>; +using SerializeContainerDynamicSizeWithCompositeTypes = + ::testing::Types, std::list>; -TYPED_TEST_SUITE(SerializeContainerFixedSizeArithmeticTypes, StaticContainersWithIntegralTypes,); +TYPED_TEST_SUITE(SerializeContainerDynamicSizeCompositeTypes, + SerializeContainerDynamicSizeWithCompositeTypes, ); -TYPED_TEST(SerializeContainerFixedSizeArithmeticTypes, ArithmeticValues) { - using Container = typename TestFixture::TContainer; - Container src{5, 9, 15, -459}; - Container res{}; +TYPED_TEST(SerializeContainerDynamicSizeCompositeTypes, + DefaultSerializeFunction) +{ + SerializationContext ctx{}; - SerializationContext ctx; - ctx.createSerializer().container<2>(src); - ctx.createDeserializer().container<2>(res); - - EXPECT_THAT(ctx.getBufferSize(), Eq(this->getContainerSize() * 2)); - EXPECT_THAT(res, ContainerEq(src)); + 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(SerializeContainerDynamicSizeCompositeTypes, + CustomFunctionThatDoNothing) +{ + SerializationContext ctx{}; + + ctx.createSerializer().container(this->src, 1000, EmptyFtor{}); + ctx.createDeserializer().container(this->res, 1000, EmptyFtor{}); + + EXPECT_THAT(ctx.getBufferSize(), + Eq(ctx.containerSizeSerializedBytesCount(this->src.size()))); +} template -class SerializeContainerFixedSizeCompositeTypes : public SerializeContainerFixedSizeArithmeticTypes { +class SerializeContainerFixedSizeArithmeticTypes : public testing::Test +{ +public: + using TContainer = T; + size_t getContainerSize() + { + T tmp{}; + return static_cast(std::distance(std::begin(tmp), std::end(tmp))); + } }; -using StaticContainersWithCompositeTypes = ::testing::Types< - std::array, MyStruct1[4]>; +using StaticContainersWithIntegralTypes = + ::testing::Types, int16_t[4]>; -TYPED_TEST_SUITE(SerializeContainerFixedSizeCompositeTypes, StaticContainersWithCompositeTypes,); +TYPED_TEST_SUITE(SerializeContainerFixedSizeArithmeticTypes, + StaticContainersWithIntegralTypes, ); -TYPED_TEST(SerializeContainerFixedSizeCompositeTypes, DefaultSerializationFunction) { - using Container = typename TestFixture::TContainer; - Container src{MyStruct1{0, 1}, MyStruct1{8, 9}, MyStruct1{11, 34}, MyStruct1{5134, 1532}}; - Container res{}; +TYPED_TEST(SerializeContainerFixedSizeArithmeticTypes, ArithmeticValues) +{ + using Container = typename TestFixture::TContainer; + Container src{ 5, 9, 15, -459 }; + Container res{}; - SerializationContext ctx{}; - ctx.createSerializer().container(src); - ctx.createDeserializer().container(res); + SerializationContext ctx; + ctx.createSerializer().container<2>(src); + ctx.createDeserializer().container<2>(res); - EXPECT_THAT(ctx.getBufferSize(), Eq(this->getContainerSize() * MyStruct1::SIZE)); - EXPECT_THAT(res, ContainerEq(src)); + EXPECT_THAT(ctx.getBufferSize(), Eq(this->getContainerSize() * 2)); + EXPECT_THAT(res, ContainerEq(src)); } -TYPED_TEST(SerializeContainerFixedSizeCompositeTypes, CustomFunctionThatSerializesAnEmptyByteEveryElement) { - using Container = typename TestFixture::TContainer; - Container src{MyStruct1{0, 1}, MyStruct1{2, 3}, MyStruct1{4, 5}, MyStruct1{5134, 1532}}; - Container res{}; - - using TValue = decltype(*std::begin(res)); - - SerializationContext ctx{}; - auto& ser = ctx.createSerializer(); - ser.container(src, [](decltype(ser)& ser, TValue &v) { - char tmp{}; - ser.object(v); - ser.value1b(tmp); - }); - auto& des = ctx.createDeserializer(); - des.container(res, [](decltype(des)& des, TValue &v) { - char tmp{}; - des.object(v); - des.value1b(tmp); - }); - - EXPECT_THAT(ctx.getBufferSize(), Eq(this->getContainerSize() * (MyStruct1::SIZE + sizeof(char)))); - EXPECT_THAT(res, ContainerEq(src)); -} - -class SerializeContainer : public ::testing::TestWithParam { +template +class SerializeContainerFixedSizeCompositeTypes + : public SerializeContainerFixedSizeArithmeticTypes +{ }; -TEST_P(SerializeContainer, SizeHasVariableLength) { - SerializationContext ctx{}; +using StaticContainersWithCompositeTypes = + ::testing::Types, MyStruct1[4]>; - std::vector src(GetParam()); - std::vector res{}; - ctx.createSerializer().container(src, std::numeric_limits::max(), EmptyFtor{}); - ctx.createDeserializer().container(res, std::numeric_limits::max(), EmptyFtor{}); +TYPED_TEST_SUITE(SerializeContainerFixedSizeCompositeTypes, + StaticContainersWithCompositeTypes, ); - EXPECT_THAT(res.size(), Eq(src.size())); - EXPECT_THAT(ctx.getBufferSize(), Eq(ctx.containerSizeSerializedBytesCount(src.size()))); +TYPED_TEST(SerializeContainerFixedSizeCompositeTypes, + DefaultSerializationFunction) +{ + using Container = typename TestFixture::TContainer; + Container src{ MyStruct1{ 0, 1 }, + MyStruct1{ 8, 9 }, + MyStruct1{ 11, 34 }, + MyStruct1{ 5134, 1532 } }; + Container res{}; + + SerializationContext ctx{}; + ctx.createSerializer().container(src); + ctx.createDeserializer().container(res); + + EXPECT_THAT(ctx.getBufferSize(), + Eq(this->getContainerSize() * MyStruct1::SIZE)); + EXPECT_THAT(res, ContainerEq(src)); } -INSTANTIATE_TEST_SUITE_P(LargeContainerSize, SerializeContainer, ::testing::Values(0x01, 0x80, 0x4000)); +TYPED_TEST(SerializeContainerFixedSizeCompositeTypes, + CustomFunctionThatSerializesAnEmptyByteEveryElement) +{ + using Container = typename TestFixture::TContainer; + Container src{ MyStruct1{ 0, 1 }, + MyStruct1{ 2, 3 }, + MyStruct1{ 4, 5 }, + MyStruct1{ 5134, 1532 } }; + Container res{}; + using TValue = decltype(*std::begin(res)); + + SerializationContext ctx{}; + auto& ser = ctx.createSerializer(); + ser.container(src, [](decltype(ser)& ser, TValue& v) { + char tmp{}; + ser.object(v); + ser.value1b(tmp); + }); + auto& des = ctx.createDeserializer(); + des.container(res, [](decltype(des)& des, TValue& v) { + char tmp{}; + des.object(v); + des.value1b(tmp); + }); + + EXPECT_THAT(ctx.getBufferSize(), + Eq(this->getContainerSize() * (MyStruct1::SIZE + sizeof(char)))); + EXPECT_THAT(res, ContainerEq(src)); +} + +class SerializeContainer : public ::testing::TestWithParam +{}; + +TEST_P(SerializeContainer, SizeHasVariableLength) +{ + SerializationContext ctx{}; + + std::vector src(GetParam()); + std::vector res{}; + ctx.createSerializer().container( + src, std::numeric_limits::max(), EmptyFtor{}); + ctx.createDeserializer().container( + res, std::numeric_limits::max(), EmptyFtor{}); + + EXPECT_THAT(res.size(), Eq(src.size())); + EXPECT_THAT(ctx.getBufferSize(), + Eq(ctx.containerSizeSerializedBytesCount(src.size()))); +} + +INSTANTIATE_TEST_SUITE_P(LargeContainerSize, + SerializeContainer, + ::testing::Values(0x01, 0x80, 0x4000)); diff --git a/tests/serialization_context.cpp b/tests/serialization_context.cpp index 22fffd9..d4f2581 100644 --- a/tests/serialization_context.cpp +++ b/tests/serialization_context.cpp @@ -1,28 +1,27 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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::Eq; @@ -31,78 +30,89 @@ using bitsery::DefaultConfig; using SingleTypeContext = int; using MultipleTypesContext = std::tuple; -TEST(SerializationContext, WhenContextIsNotTupleThenReturnThisContext) { - SingleTypeContext ctx{54}; - BasicSerializationContext c1; - auto& ser1 = c1.createSerializer(ctx); +TEST(SerializationContext, WhenContextIsNotTupleThenReturnThisContext) +{ + SingleTypeContext ctx{ 54 }; + BasicSerializationContext c1; + auto& ser1 = c1.createSerializer(ctx); - EXPECT_THAT(ser1.context(), Eq(ctx)); + EXPECT_THAT(ser1.context(), Eq(ctx)); } -TEST(SerializationContext, WhenContextIsTupleThenReturnsTupleElements) { +TEST(SerializationContext, WhenContextIsTupleThenReturnsTupleElements) +{ - MultipleTypesContext ctx{5, 798.654f, 'F'}; - BasicSerializationContext c1; - auto& ser1 = c1.createSerializer(ctx); + MultipleTypesContext ctx{ 5, 798.654f, 'F' }; + BasicSerializationContext c1; + auto& ser1 = c1.createSerializer(ctx); - EXPECT_THAT(ser1.context(), std::get<0>(ctx)); - EXPECT_THAT(ser1.context(), std::get<1>(ctx)); - EXPECT_THAT(ser1.context(), std::get<2>(ctx)); + EXPECT_THAT(ser1.context(), std::get<0>(ctx)); + EXPECT_THAT(ser1.context(), std::get<1>(ctx)); + EXPECT_THAT(ser1.context(), std::get<2>(ctx)); } -TEST(SerializationContext, WhenContextDoesntExistsThenContextOrNullReturnsNull) { - SingleTypeContext ctx1= 32; - BasicSerializationContext c1; +TEST(SerializationContext, WhenContextDoesntExistsThenContextOrNullReturnsNull) +{ + SingleTypeContext ctx1 = 32; + BasicSerializationContext c1; + auto& ser = c1.createSerializer(ctx1); + EXPECT_THAT(ser.contextOrNull(), ::testing::IsNull()); + EXPECT_THAT(ser.contextOrNull(), ::testing::NotNull()); + *ser.contextOrNull() = 2; + EXPECT_THAT(ctx1, Eq(2)); + + MultipleTypesContext ctx2{ 5, 798.654f, 'F' }; + BasicSerializationContext c2; + auto& des = c2.createDeserializer(ctx2); + EXPECT_THAT(des.contextOrNull(), ::testing::IsNull()); + EXPECT_THAT(des.contextOrNull(), ::testing::NotNull()); + EXPECT_THAT(*des.contextOrNull(), Eq('F')); + EXPECT_THAT(*des.contextOrNull(), Eq(5)); +} + +struct Base +{ + int value{}; +}; +struct Derived : Base +{}; + +TEST(SerializationContext, ContextWillTryToConvertIfTypeIsConvertible) +{ + Derived ctx1{}; + BasicSerializationContext c1; + auto& ser = c1.createSerializer(ctx1); + EXPECT_THAT(ser.contextOrNull(), ::testing::NotNull()); + EXPECT_THAT(ser.contextOrNull(), ::testing::NotNull()); + ser.context(); + ser.context(); +} + +TEST(SerializationContext, + WhenMultipleConvertibleTypesExistsThenFirstMatchIsTaken) +{ + { + using CTX1 = std::tuple; + CTX1 ctx1{}; + std::get<0>(ctx1).value = 1; + std::get<2>(ctx1).value = 2; + BasicSerializationContext c1; auto& ser = c1.createSerializer(ctx1); - EXPECT_THAT(ser.contextOrNull(), ::testing::IsNull()); - EXPECT_THAT(ser.contextOrNull(), ::testing::NotNull()); - *ser.contextOrNull() = 2; - EXPECT_THAT(ctx1, Eq(2)); + EXPECT_THAT(ser.context().value, Eq(std::get<2>(ctx1).value)); + EXPECT_THAT(ser.context().value, Eq(std::get<0>(ctx1).value)); + } - MultipleTypesContext ctx2{5, 798.654f, 'F'}; - BasicSerializationContext c2; - auto& des = c2.createDeserializer(ctx2); - EXPECT_THAT(des.contextOrNull(), ::testing::IsNull()); - EXPECT_THAT(des.contextOrNull(), ::testing::NotNull()); - EXPECT_THAT(*des.contextOrNull(), Eq('F')); - EXPECT_THAT(*des.contextOrNull(), Eq(5)); -} - -struct Base { int value{}; }; -struct Derived: Base{}; - -TEST(SerializationContext, ContextWillTryToConvertIfTypeIsConvertible) { - Derived ctx1{}; - BasicSerializationContext c1; - auto& ser = c1.createSerializer(ctx1); - EXPECT_THAT(ser.contextOrNull(), ::testing::NotNull()); - EXPECT_THAT(ser.contextOrNull(), ::testing::NotNull()); - ser.context(); - ser.context(); -} - -TEST(SerializationContext, WhenMultipleConvertibleTypesExistsThenFirstMatchIsTaken) { - { - using CTX1 = std::tuple; - CTX1 ctx1{}; - std::get<0>(ctx1).value = 1; - std::get<2>(ctx1).value = 2; - BasicSerializationContext c1; - auto& ser = c1.createSerializer(ctx1); - EXPECT_THAT(ser.context().value, Eq(std::get<2>(ctx1).value)); - EXPECT_THAT(ser.context().value, Eq(std::get<0>(ctx1).value)); - } - - { - using CTX2 = std::tuple; - CTX2 ctx2{}; - std::get<1>(ctx2).value = 1; - std::get<2>(ctx2).value = 2; - BasicSerializationContext c2; - auto& des = c2.createSerializer(ctx2); - - EXPECT_THAT(des.context().value, Eq(std::get<1>(ctx2).value)); - //Base will not be accessable in this case, because Derived is first valid match - EXPECT_THAT(des.context().value, Eq(std::get<1>(ctx2).value)); - } + { + using CTX2 = std::tuple; + CTX2 ctx2{}; + std::get<1>(ctx2).value = 1; + std::get<2>(ctx2).value = 2; + BasicSerializationContext c2; + auto& des = c2.createSerializer(ctx2); + + EXPECT_THAT(des.context().value, Eq(std::get<1>(ctx2).value)); + // Base will not be accessable in this case, because Derived is first valid + // match + EXPECT_THAT(des.context().value, Eq(std::get<1>(ctx2).value)); + } } diff --git a/tests/serialization_ext_compact_value.cpp b/tests/serialization_ext_compact_value.cpp index 43ab008..dc90eb0 100644 --- a/tests/serialization_ext_compact_value.cpp +++ b/tests/serialization_ext_compact_value.cpp @@ -1,244 +1,276 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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 "serialization_test_utils.h" #include #include -#include "serialization_test_utils.h" #include #include #include -using testing::Eq; +using bitsery::EndiannessType; using bitsery::ext::CompactValue; using bitsery::ext::CompactValueAsObject; -using bitsery::EndiannessType; +using testing::Eq; // helper function, that gets value filled with specified number of bits -template -TValue getValue(bool isPositive, size_t significantBits) { - TValue v = isPositive ? 0 : static_cast(-1); - if (significantBits == 0) - return v; +template +TValue +getValue(bool isPositive, size_t significantBits) +{ + TValue v = isPositive ? 0 : static_cast(-1); + if (significantBits == 0) + return v; - using TUnsigned = typename std::make_unsigned::type; - TUnsigned mask = {}; - mask = static_cast(~mask); // invert shiftByBits - auto shiftBy = bitsery::details::BitsSize::value - significantBits; - mask = static_cast(mask >> shiftBy); - //cast to unsigned when applying mask - return v ^ static_cast(mask); + using TUnsigned = typename std::make_unsigned::type; + TUnsigned mask = {}; + mask = static_cast(~mask); // invert shiftByBits + auto shiftBy = bitsery::details::BitsSize::value - significantBits; + mask = static_cast(mask >> shiftBy); + // cast to unsigned when applying mask + return v ^ static_cast(mask); } // helper function, that serialize and return deserialized value -template -std::pair serializeAndGetDeserialized(TValue data) { - Buffer buf{}; - bitsery::Serializer> ser{buf}; - ser.template ext(data, CompactValue{}); +template +std::pair +serializeAndGetDeserialized(TValue data) +{ + Buffer buf{}; + bitsery::Serializer> ser{ buf }; + ser.template ext(data, CompactValue{}); - bitsery::Deserializer> des{buf.begin(), ser.adapter().writtenBytesCount()}; - TValue res; - des.template ext(res, CompactValue{}); - return {res, ser.adapter().writtenBytesCount()}; + bitsery::Deserializer> des{ + buf.begin(), ser.adapter().writtenBytesCount() + }; + TValue res; + des.template ext(res, CompactValue{}); + return { res, ser.adapter().writtenBytesCount() }; } -struct LittleEndianConfig { - static constexpr EndiannessType Endianness = EndiannessType::LittleEndian; - static constexpr bool CheckDataErrors = true; - static constexpr bool CheckAdapterErrors = true; +struct LittleEndianConfig +{ + static constexpr EndiannessType Endianness = EndiannessType::LittleEndian; + static constexpr bool CheckDataErrors = true; + static constexpr bool CheckAdapterErrors = true; }; -struct BigEndianConfig { - static constexpr EndiannessType Endianness = EndiannessType::BigEndian; - static constexpr bool CheckDataErrors = true; - static constexpr bool CheckAdapterErrors = true; +struct BigEndianConfig +{ + static constexpr EndiannessType Endianness = EndiannessType::BigEndian; + static constexpr bool CheckDataErrors = true; + static constexpr bool CheckAdapterErrors = true; }; -template -struct TC { - static_assert(isPositiveNr || std::is_signed::value, ""); +template +struct TC +{ + static_assert(isPositiveNr || std::is_signed::value, ""); - using Value = TValue; - using Config = TConfig; - bool isPositive = isPositiveNr; + using Value = TValue; + using Config = TConfig; + bool isPositive = isPositiveNr; }; template -class SerializeExtensionCompactValueCorrectness : public testing::Test { +class SerializeExtensionCompactValueCorrectness : public testing::Test +{ public: - using TestCase = T; + using TestCase = T; }; +using AllValueSizesTestCases = + ::testing::Types, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC, + TC>; -using AllValueSizesTestCases = ::testing::Types< - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC, - TC ->; +TYPED_TEST_SUITE(SerializeExtensionCompactValueCorrectness, + AllValueSizesTestCases, ); -TYPED_TEST_SUITE(SerializeExtensionCompactValueCorrectness, AllValueSizesTestCases,); +TYPED_TEST(SerializeExtensionCompactValueCorrectness, TestDifferentSizeValues) +{ + using TCase = typename TestFixture::TestCase; + using TValue = typename TCase::Value; + TCase tc{}; -TYPED_TEST(SerializeExtensionCompactValueCorrectness, TestDifferentSizeValues) { - using TCase = typename TestFixture::TestCase; - using TValue = typename TCase::Value; - TCase tc{}; - - for (auto i = 0u; i < bitsery::details::BitsSize::value + 1; ++i) { - auto data = getValue(tc.isPositive, i); - auto res = serializeAndGetDeserialized(data); - EXPECT_THAT(res.first, Eq(data)); - } + for (auto i = 0u; i < bitsery::details::BitsSize::value + 1; ++i) { + auto data = getValue(tc.isPositive, i); + auto res = serializeAndGetDeserialized(data); + EXPECT_THAT(res.first, Eq(data)); + } } - // this stucture will contain test data and result, as type paramters -template -struct SizeTC { - static_assert(isPositiveNr || std::is_signed::value, ""); - static_assert(bitsery::details::BitsSize::value >= significantBits, ""); +template +struct SizeTC +{ + static_assert(isPositiveNr || std::is_signed::value, ""); + static_assert(bitsery::details::BitsSize::value >= significantBits, + ""); - using Value = TValue; - bool isPositive = isPositiveNr; - size_t fillBits = significantBits; - size_t bytesCount = resultBytes; + using Value = TValue; + bool isPositive = isPositiveNr; + size_t fillBits = significantBits; + size_t bytesCount = resultBytes; }; template -class SerializeExtensionCompactValueRequiredBytes : public testing::Test { +class SerializeExtensionCompactValueRequiredBytes : public testing::Test +{ public: - using TestCase = T; + using TestCase = T; }; using RequiredBytesTestCases = ::testing::Types< - //1 byte always writes to 1 byte - SizeTC, - SizeTC, - SizeTC, - SizeTC, + // 1 byte always writes to 1 byte + SizeTC, + SizeTC, + SizeTC, + SizeTC, - //2 byte, +1 byte after 15 significant bits - SizeTC, - SizeTC, - SizeTC, - SizeTC, - //2 byte, +1 byte after 15-1 significant bits (1 bit for sign) - SizeTC, - SizeTC, - SizeTC, - SizeTC, + // 2 byte, +1 byte after 15 significant bits + SizeTC, + SizeTC, + SizeTC, + SizeTC, + // 2 byte, +1 byte after 15-1 significant bits (1 bit for sign) + SizeTC, + SizeTC, + SizeTC, + SizeTC, - //4 byte, +1 byte after 29 significant bits - SizeTC, - SizeTC, - SizeTC, - SizeTC, - SizeTC, - //4 byte - SizeTC, - SizeTC, - SizeTC, - SizeTC, - SizeTC, + // 4 byte, +1 byte after 29 significant bits + SizeTC, + SizeTC, + SizeTC, + SizeTC, + SizeTC, + // 4 byte + SizeTC, + SizeTC, + SizeTC, + SizeTC, + SizeTC, - //8 byte, +1 byte after 57 significant bits, or +2 byte when all bits are significant - SizeTC, - SizeTC, - SizeTC, - SizeTC, - SizeTC, - SizeTC, - SizeTC, - SizeTC, - //8 byte, - SizeTC, - SizeTC, - SizeTC, - SizeTC, - SizeTC, - SizeTC, - SizeTC, - SizeTC ->; + // 8 byte, +1 byte after 57 significant bits, or +2 byte when all bits are + // significant + SizeTC, + SizeTC, + SizeTC, + SizeTC, + SizeTC, + SizeTC, + SizeTC, + SizeTC, + // 8 byte, + SizeTC, + SizeTC, + SizeTC, + SizeTC, + SizeTC, + SizeTC, + SizeTC, + SizeTC>; -TYPED_TEST_SUITE(SerializeExtensionCompactValueRequiredBytes, RequiredBytesTestCases,); +TYPED_TEST_SUITE(SerializeExtensionCompactValueRequiredBytes, + RequiredBytesTestCases, ); -TYPED_TEST(SerializeExtensionCompactValueRequiredBytes, Test) { - using TCase = typename TestFixture::TestCase; - using TValue = typename TCase::Value; - TCase tc{}; - TValue data = getValue(tc.isPositive, tc.fillBits); - auto res = serializeAndGetDeserialized(data); - EXPECT_THAT(res.first, Eq(data)); - EXPECT_THAT(res.second, tc.bytesCount); +TYPED_TEST(SerializeExtensionCompactValueRequiredBytes, Test) +{ + using TCase = typename TestFixture::TestCase; + using TValue = typename TCase::Value; + TCase tc{}; + TValue data = getValue(tc.isPositive, tc.fillBits); + auto res = serializeAndGetDeserialized(data); + EXPECT_THAT(res.first, Eq(data)); + EXPECT_THAT(res.second, tc.bytesCount); } -enum b1En: uint8_t { - A,B,C,D=54,E +enum b1En : uint8_t +{ + A, + B, + C, + D = 54, + E }; -enum class b8En: int64_t { - A=-874987489,B,C=0,D,E=489748978, F,G +enum class b8En : int64_t +{ + A = -874987489, + B, + C = 0, + D, + E = 489748978, + F, + G }; -TEST(SerializeExtensionCompactValueEnum, TestEnums) { - auto d1 = b1En::E; - auto d2 = b8En::B; - auto d3 = b8En::F; - EXPECT_THAT(serializeAndGetDeserialized(d1).first, Eq(d1)); - EXPECT_THAT(serializeAndGetDeserialized(d2).first, Eq(d2)); - EXPECT_THAT(serializeAndGetDeserialized(d3).first, Eq(d3)); +TEST(SerializeExtensionCompactValueEnum, TestEnums) +{ + auto d1 = b1En::E; + auto d2 = b8En::B; + auto d3 = b8En::F; + EXPECT_THAT(serializeAndGetDeserialized(d1).first, + Eq(d1)); + EXPECT_THAT(serializeAndGetDeserialized(d2).first, + Eq(d2)); + EXPECT_THAT(serializeAndGetDeserialized(d3).first, + Eq(d3)); } -TEST(SerializeExtensionCompactValueAsObjectDeserializeOverflow, TestEnums) { - SerializationContext ctx; - auto data = getValue(true, 17); - uint16_t res{}; - ctx.createSerializer().ext(data, CompactValueAsObject{}); - ctx.createDeserializer().ext(res, CompactValueAsObject{}); - EXPECT_THAT(data, ::testing::Ne(res)); - EXPECT_THAT(ctx.des->adapter().error(), Eq(bitsery::ReaderError::InvalidData)); +TEST(SerializeExtensionCompactValueAsObjectDeserializeOverflow, TestEnums) +{ + SerializationContext ctx; + auto data = getValue(true, 17); + uint16_t res{}; + ctx.createSerializer().ext(data, CompactValueAsObject{}); + ctx.createDeserializer().ext(res, CompactValueAsObject{}); + EXPECT_THAT(data, ::testing::Ne(res)); + EXPECT_THAT(ctx.des->adapter().error(), + Eq(bitsery::ReaderError::InvalidData)); } - - diff --git a/tests/serialization_ext_entropy.cpp b/tests/serialization_ext_entropy.cpp index 9423d11..b6f99ed 100644 --- a/tests/serialization_ext_entropy.cpp +++ b/tests/serialization_ext_entropy.cpp @@ -1,31 +1,30 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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 -#include #include "serialization_test_utils.h" +#include using namespace testing; @@ -34,167 +33,195 @@ using bitsery::ext::Entropy; using BPSer = SerializationContext::TSerializerBPEnabled; using BPDes = SerializationContext::TDeserializerBPEnabled; +TEST(SerializeExtensionEntropy, + WhenEntropyEncodedThenOnlyWriteIndexUsingMinRequiredBits) +{ + int32_t v = 4849; + int32_t res; + int32_t values[3] = { 485, 4849, 89 }; + SerializationContext ctx{}; + ctx.createSerializer().enableBitPacking( + [&v, &values](BPSer& ser) { ser.ext4b(v, Entropy{ values }); }); + ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) { + des.ext4b(res, Entropy{ values }); + }); -TEST(SerializeExtensionEntropy, WhenEntropyEncodedThenOnlyWriteIndexUsingMinRequiredBits) { - int32_t v = 4849; - int32_t res; - int32_t values[3] = {485,4849,89}; - SerializationContext ctx{}; - ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) { - ser.ext4b(v, Entropy{values}); - }); - ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) { - des.ext4b(res, Entropy{values}); - }); + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); - EXPECT_THAT(res, Eq(v)); - EXPECT_THAT(ctx.getBufferSize(), Eq(1)); - - SerializationContext ctx1{}; - ctx1.createSerializer().enableBitPacking([&v, &values](BPSer& ser) { - ser.ext4b(v, Entropy{values}); - }); - ctx1.createDeserializer().enableBitPacking([&res](BPDes& des) { - des.ext(res, bitsery::ext::ValueRange{0, static_cast(3 + 1)}); - }); - EXPECT_THAT(res, Eq(2)); + SerializationContext ctx1{}; + ctx1.createSerializer().enableBitPacking( + [&v, &values](BPSer& ser) { ser.ext4b(v, Entropy{ values }); }); + ctx1.createDeserializer().enableBitPacking([&res](BPDes& des) { + des.ext( + res, bitsery::ext::ValueRange{ 0, static_cast(3 + 1) }); + }); + EXPECT_THAT(res, Eq(2)); } -TEST(SerializeExtensionEntropy, WhenNoEntropyEncodedThenWriteZeroBitsAndValueOrObject) { - int16_t v = 8945; - int16_t res; - std::initializer_list values{485,4849,89}; - SerializationContext ctx{}; - ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) { - ser.ext2b(v, Entropy>{values}); - }); - ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) { - des.ext2b(res, Entropy>{values}); - }); +TEST(SerializeExtensionEntropy, + WhenNoEntropyEncodedThenWriteZeroBitsAndValueOrObject) +{ + int16_t v = 8945; + int16_t res; + std::initializer_list values{ 485, 4849, 89 }; + SerializationContext ctx{}; + ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) { + ser.ext2b(v, Entropy>{ values }); + }); + ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) { + des.ext2b(res, Entropy>{ values }); + }); - EXPECT_THAT(res, Eq(v)); - EXPECT_THAT(ctx.getBufferSize(), Eq(sizeof(int16_t)+1)); + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq(sizeof(int16_t) + 1)); } -TEST(SerializeExtensionEntropy, CustomTypeEntropyEncoded) { - MyStruct1 v = {12,10}; - MyStruct1 res; - constexpr size_t N = 4; +TEST(SerializeExtensionEntropy, CustomTypeEntropyEncoded) +{ + MyStruct1 v = { 12, 10 }; + MyStruct1 res; + constexpr size_t N = 4; - MyStruct1 values[N]{ - MyStruct1{12, 10}, MyStruct1{485, 454}, - MyStruct1{4849, 89}, MyStruct1{0, 1}}; - SerializationContext ctx{}; - ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) { - ser.ext(v, Entropy{values}); - }); - ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) { - des.ext(res, Entropy{values}); - }); - EXPECT_THAT(res, Eq(v)); - EXPECT_THAT(ctx.getBufferSize(), Eq(1)); + MyStruct1 values[N]{ MyStruct1{ 12, 10 }, + MyStruct1{ 485, 454 }, + MyStruct1{ 4849, 89 }, + MyStruct1{ 0, 1 } }; + SerializationContext ctx{}; + ctx.createSerializer().enableBitPacking( + [&v, &values](BPSer& ser) { ser.ext(v, Entropy{ values }); }); + ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) { + des.ext(res, Entropy{ values }); + }); + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); } -TEST(SerializeExtensionEntropy, CustomTypeNotEntropyEncoded) { - MyStruct1 v = {8945,4456}; - MyStruct1 res; +TEST(SerializeExtensionEntropy, CustomTypeNotEntropyEncoded) +{ + MyStruct1 v = { 8945, 4456 }; + MyStruct1 res; - std::initializer_list values { - MyStruct1{12,10}, MyStruct1{485, 454}, - MyStruct1{4849,89}, MyStruct1{0,1}}; - SerializationContext ctx{}; - ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) { - ser.ext(v, Entropy>{values}); - }); - ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) { - des.ext(res, Entropy>{values}); - }); + std::initializer_list values{ MyStruct1{ 12, 10 }, + MyStruct1{ 485, 454 }, + MyStruct1{ 4849, 89 }, + MyStruct1{ 0, 1 } }; + SerializationContext ctx{}; + ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) { + ser.ext(v, Entropy>{ values }); + }); + ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) { + des.ext(res, Entropy>{ values }); + }); - EXPECT_THAT(res, Eq(v)); - EXPECT_THAT(ctx.getBufferSize(), Eq(MyStruct1::SIZE + 1)); + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq(MyStruct1::SIZE + 1)); } -TEST(SerializeExtensionEntropy, CustomFunctionNotEntropyEncodedWithNoAlignBeforeData) { - MyStruct1 v = {8945,4456}; - MyStruct1 res; - constexpr size_t N = 4; +TEST(SerializeExtensionEntropy, + CustomFunctionNotEntropyEncodedWithNoAlignBeforeData) +{ + MyStruct1 v = { 8945, 4456 }; + MyStruct1 res; + constexpr size_t N = 4; - std::vector values{ - MyStruct1{12,10}, MyStruct1{485, 454}, - MyStruct1{4849,89}, MyStruct1{0,1}}; + std::vector values{ MyStruct1{ 12, 10 }, + MyStruct1{ 485, 454 }, + MyStruct1{ 4849, 89 }, + MyStruct1{ 0, 1 } }; - auto rangeForValue = bitsery::ext::ValueRange{0, 10000}; + auto rangeForValue = bitsery::ext::ValueRange{ 0, 10000 }; - SerializationContext ctx; - ctx.createSerializer().enableBitPacking([&v, &values, &rangeForValue](BPSer& ser){ - //lambdas differ only in capture clauses, it would make sense to use std::bind, but debugger crashes when it sees std::bind... - auto serLambda = [&rangeForValue](BPSer& ser, MyStruct1& data) { - ser.ext(data.i1, rangeForValue); - ser.ext(data.i2, rangeForValue); - }; - ser.ext(v, Entropy>(values, false), serLambda); + SerializationContext ctx; + ctx.createSerializer().enableBitPacking( + [&v, &values, &rangeForValue](BPSer& ser) { + // lambdas differ only in capture clauses, it would make sense to use + // std::bind, but debugger crashes when it sees std::bind... + auto serLambda = [&rangeForValue](BPSer& ser, MyStruct1& data) { + ser.ext(data.i1, rangeForValue); + ser.ext(data.i2, rangeForValue); + }; + ser.ext(v, Entropy>(values, false), serLambda); }); - ctx.createDeserializer().enableBitPacking([&res, &values, &rangeForValue](BPDes& des) { - auto desLambda = [&rangeForValue](BPDes& des, MyStruct1& data) { - des.ext(data.i1, rangeForValue); - des.ext(data.i2, rangeForValue); - }; - des.ext(res, Entropy>(values, false), desLambda); + ctx.createDeserializer().enableBitPacking( + [&res, &values, &rangeForValue](BPDes& des) { + auto desLambda = [&rangeForValue](BPDes& des, MyStruct1& data) { + des.ext(data.i1, rangeForValue); + des.ext(data.i2, rangeForValue); + }; + des.ext(res, Entropy>(values, false), desLambda); }); - EXPECT_THAT(res, Eq(v)); - auto rangeForIndex = bitsery::ext::ValueRange{0u, N+1}; - EXPECT_THAT(ctx.getBufferSize(), Eq((rangeForIndex.getRequiredBits() + rangeForValue.getRequiredBits() * 2 - 1) / 8 + 1 )); + EXPECT_THAT(res, Eq(v)); + auto rangeForIndex = bitsery::ext::ValueRange{ 0u, N + 1 }; + EXPECT_THAT(ctx.getBufferSize(), + Eq((rangeForIndex.getRequiredBits() + + rangeForValue.getRequiredBits() * 2 - 1) / + 8 + + 1)); } -TEST(SerializeExtensionEntropy, CustomFunctionNotEntropyEncodedWithAlignBeforeData) { - MyStruct1 v = {8945,4456}; - MyStruct1 res; +TEST(SerializeExtensionEntropy, + CustomFunctionNotEntropyEncodedWithAlignBeforeData) +{ + MyStruct1 v = { 8945, 4456 }; + MyStruct1 res; - std::vector values{ - MyStruct1{12,10}, MyStruct1{485, 454}, - MyStruct1{4849,89}, MyStruct1{0,1}}; + std::vector values{ MyStruct1{ 12, 10 }, + MyStruct1{ 485, 454 }, + MyStruct1{ 4849, 89 }, + MyStruct1{ 0, 1 } }; - auto rangeForValue = bitsery::ext::ValueRange{0, 10000}; + auto rangeForValue = bitsery::ext::ValueRange{ 0, 10000 }; - SerializationContext ctx; - ctx.createSerializer().enableBitPacking([&v, &values, &rangeForValue](BPSer& ser){ - //lambdas differ only in capture clauses, it would make sense to use std::bind, but debugger crashes when it sees std::bind... - auto serLambda = [&rangeForValue](BPSer& ser, MyStruct1& data) { - ser.ext(data.i1, rangeForValue); - ser.ext(data.i2, rangeForValue); - }; - ser.ext(v, Entropy>(values, true), serLambda); + SerializationContext ctx; + ctx.createSerializer().enableBitPacking( + [&v, &values, &rangeForValue](BPSer& ser) { + // lambdas differ only in capture clauses, it would make sense to use + // std::bind, but debugger crashes when it sees std::bind... + auto serLambda = [&rangeForValue](BPSer& ser, MyStruct1& data) { + ser.ext(data.i1, rangeForValue); + ser.ext(data.i2, rangeForValue); + }; + ser.ext(v, Entropy>(values, true), serLambda); }); - ctx.createDeserializer().enableBitPacking([&res, &values, &rangeForValue](BPDes& des) { - auto desLambda = [&rangeForValue](BPDes& des, MyStruct1& data) { - des.ext(data.i1, rangeForValue); - des.ext(data.i2, rangeForValue); - }; - des.ext(res, Entropy>(values, true), desLambda); + ctx.createDeserializer().enableBitPacking( + [&res, &values, &rangeForValue](BPDes& des) { + auto desLambda = [&rangeForValue](BPDes& des, MyStruct1& data) { + des.ext(data.i1, rangeForValue); + des.ext(data.i2, rangeForValue); + }; + des.ext(res, Entropy>(values, true), desLambda); }); - EXPECT_THAT(res, Eq(v)); - auto bitsForIndex = 8u; //because aligned - EXPECT_THAT(ctx.getBufferSize(), Eq((bitsForIndex + rangeForValue.getRequiredBits() * 2 - 1) / 8 + 1 )); + EXPECT_THAT(res, Eq(v)); + auto bitsForIndex = 8u; // because aligned + EXPECT_THAT( + ctx.getBufferSize(), + Eq((bitsForIndex + rangeForValue.getRequiredBits() * 2 - 1) / 8 + 1)); } -TEST(SerializeExtensionEntropy, WhenEntropyEncodedThenCustomFunctionNotInvoked) { - MyStruct1 v = {4849,89}; - MyStruct1 res; +TEST(SerializeExtensionEntropy, WhenEntropyEncodedThenCustomFunctionNotInvoked) +{ + MyStruct1 v = { 4849, 89 }; + MyStruct1 res; - std::list values {MyStruct1{12,10}, MyStruct1{485, 454}, - MyStruct1{4849,89}, MyStruct1{0,1}}; + std::list values{ MyStruct1{ 12, 10 }, + MyStruct1{ 485, 454 }, + MyStruct1{ 4849, 89 }, + MyStruct1{ 0, 1 } }; - SerializationContext ctx; - ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) { - ser.ext(v, Entropy>{values}, [](BPSer& ,MyStruct1& ) {}); - }); - ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) { - des.ext(res, Entropy>{values}, [](BPDes& , MyStruct1& ) {}); - }); + SerializationContext ctx; + ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) { + ser.ext( + v, Entropy>{ values }, [](BPSer&, MyStruct1&) {}); + }); + ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) { + des.ext( + res, Entropy>{ values }, [](BPDes&, MyStruct1&) {}); + }); - EXPECT_THAT(res, Eq(v)); - EXPECT_THAT(ctx.getBufferSize(), Eq(1)); + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); } diff --git a/tests/serialization_ext_growable.cpp b/tests/serialization_ext_growable.cpp index b087f07..9dd6db9 100644 --- a/tests/serialization_ext_growable.cpp +++ b/tests/serialization_ext_growable.cpp @@ -1,238 +1,253 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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 "serialization_test_utils.h" #include #include -#include "serialization_test_utils.h" using namespace testing; using bitsery::ext::Growable; -struct DataV1 { - int32_t v1; +struct DataV1 +{ + int32_t v1; }; -template -void serialize(S& s, DataV1& o) { - s.value4b(o.v1); +template +void +serialize(S& s, DataV1& o) +{ + s.value4b(o.v1); } -struct DataV2 { - int32_t v1; - int32_t v2; +struct DataV2 +{ + int32_t v1; + int32_t v2; }; -template -void serialize(S& s, DataV2& o) { - s.value4b(o.v1); - s.value4b(o.v2); +template +void +serialize(S& s, DataV2& o) +{ + s.value4b(o.v1); + s.value4b(o.v2); } -struct DataV3 { - int32_t v1; - int32_t v2; - int32_t v3; - template - void serialize(S& s) { - s.value4b(v1); - s.value4b(v2); - s.value4b(v3); - } - +struct DataV3 +{ + int32_t v1; + int32_t v2; + int32_t v3; + template + void serialize(S& s) + { + s.value4b(v1); + s.value4b(v2); + s.value4b(v3); + } }; -TEST(SerializeExtensionGrowable, SessionsLengthIsStoredWith4BytesBeforeSessionDataStarts) { - SerializationContext ctx; - auto& ser = ctx.createSerializer(); - //session cannot be empty - ser.value2b(int16_t{1}); - ser.ext(int8_t{2}, Growable{}, [] (decltype(ser)& ser, int8_t& v) { - ser.value1b(v); +TEST(SerializeExtensionGrowable, + SessionsLengthIsStoredWith4BytesBeforeSessionDataStarts) +{ + SerializationContext ctx; + auto& ser = ctx.createSerializer(); + // session cannot be empty + ser.value2b(int16_t{ 1 }); + ser.ext(int8_t{ 2 }, Growable{}, [](decltype(ser)& ser, int8_t& v) { + ser.value1b(v); + }); + ser.value1b(int8_t{ 3 }); + + auto& des = ctx.createDeserializer(); + uint8_t res1b{}; + uint16_t res2b{}; + uint32_t res4b{}; + des.value2b(res2b); + EXPECT_THAT(res2b, Eq(1)); + des.value4b(res4b); + EXPECT_THAT(res4b, Eq(1 + 4)); // size + 4bytes + des.value1b(res1b); + EXPECT_THAT(res1b, Eq(2)); + des.value1b(res1b); + EXPECT_THAT(res1b, Eq(3)); + EXPECT_THAT(ctx.ser->adapter().writtenBytesCount(), Eq(8)); +} + +TEST(SerializeExtensionGrowable, MultipleSessionsReadSameVersionData) +{ + SerializationContext ctx; + DataV2 data{ 8454, 987451 }; + auto& ser = ctx.createSerializer(); + + for (auto i = 0; i < 10; ++i) { + ser.ext(data, Growable{}); + } + ctx.createDeserializer(); + DataV2 res{}; + auto& des = ctx.createDeserializer(); + for (auto i = 0; i < 10; ++i) { + des.ext(res, Growable{}); + EXPECT_THAT(res.v1, Eq(data.v1)); + EXPECT_THAT(res.v2, Eq(data.v2)); + } + EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true)); +} + +TEST(SerializeExtensionGrowable, MultipleSessionsReadNewerVersionData) +{ + SerializationContext ctx; + DataV3 data{ 8454, 987451, 45612 }; + auto& ser = ctx.createSerializer(); + + for (auto i = 0; i < 10; ++i) { + ser.ext(data, Growable{}); + } + ctx.createDeserializer(); + DataV2 res{}; + auto& des = ctx.createDeserializer(); + for (auto i = 0; i < 10; ++i) { + des.ext(res, Growable{}); + EXPECT_THAT(res.v1, Eq(data.v1)); + EXPECT_THAT(res.v2, Eq(data.v2)); + } + EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true)); +} + +TEST(SerializeExtensionGrowable, MultipleSessionsReadOlderVersionData) +{ + SerializationContext ctx; + DataV2 data{ 8454, 987451 }; + auto& ser = ctx.createSerializer(); + + for (auto i = 0; i < 10; ++i) { + ser.ext(data, Growable{}); + } + ctx.createDeserializer(); + DataV3 res{}; + auto& des = ctx.createDeserializer(); + for (auto i = 0; i < 10; ++i) { + des.ext(res, Growable{}); + EXPECT_THAT(res.v1, Eq(data.v1)); + EXPECT_THAT(res.v2, Eq(data.v2)); + EXPECT_THAT(res.v3, Eq(0)); + } + EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true)); +} + +TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadSameVersionData) +{ + SerializationContext ctx; + DataV2 data{ 8454, 987451 }; + auto& ser = ctx.createSerializer(); + + for (auto i = 0; i < 10; ++i) { + ser.ext(data, Growable{}, [](decltype(ser)& ser, DataV2& o) { + ser.value4b(o.v1); + ser.value4b(o.v2); + ser.ext(o, Growable{}); }); - ser.value1b(int8_t{3}); - - auto& des = ctx.createDeserializer(); - uint8_t res1b{}; - uint16_t res2b{}; - uint32_t res4b{}; - des.value2b(res2b); - EXPECT_THAT(res2b, Eq(1)); - des.value4b(res4b); - EXPECT_THAT(res4b, Eq(1+4));//size + 4bytes - des.value1b(res1b); - EXPECT_THAT(res1b, Eq(2)); - des.value1b(res1b); - EXPECT_THAT(res1b, Eq(3)); - EXPECT_THAT(ctx.ser->adapter().writtenBytesCount(), Eq(8)); + } + ctx.createDeserializer(); + DataV2 res{}; + auto& des = ctx.createDeserializer(); + for (auto i = 0; i < 10; ++i) { + des.ext(res, Growable{}, [&res, &data](decltype(des)& des, DataV2& o) { + des.value4b(o.v1); + des.value4b(o.v2); + EXPECT_THAT(res.v1, Eq(data.v1)); + EXPECT_THAT(res.v2, Eq(data.v2)); + des.ext(o, Growable{}); + EXPECT_THAT(res.v1, Eq(data.v1)); + EXPECT_THAT(res.v2, Eq(data.v2)); + }); + } + EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true)); } -TEST(SerializeExtensionGrowable, MultipleSessionsReadSameVersionData) { - SerializationContext ctx; - DataV2 data{8454,987451}; - auto& ser = ctx.createSerializer(); +TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadNewerVersionData) +{ + SerializationContext ctx; + DataV3 data{ 8454, 987451, 54124 }; + auto& ser = ctx.createSerializer(); - for (auto i = 0; i < 10; ++i) { - ser.ext(data, Growable{}); - } - ctx.createDeserializer(); - DataV2 res{}; - auto& des = ctx.createDeserializer(); - for (auto i = 0; i < 10; ++i) { - des.ext(res, Growable{}); - EXPECT_THAT(res.v1, Eq(data.v1)); - EXPECT_THAT(res.v2, Eq(data.v2)); - } - EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true)); + for (auto i = 0; i < 10; ++i) { + ser.ext(data, Growable{}, [](decltype(ser)& ser, DataV3& o) { + ser.value4b(o.v1); + ser.value4b(o.v2); + ser.ext(o, Growable{}); + // new fields can only be added at the end + ser.value4b(o.v3); + }); + } + ctx.createDeserializer(); + DataV2 res{}; + auto& des = ctx.createDeserializer(); + for (auto i = 0; i < 10; ++i) { + des.ext(res, Growable{}, [&res, &data](decltype(des)& des, DataV2& o) { + des.value4b(o.v1); + des.value4b(o.v2); + EXPECT_THAT(res.v1, Eq(data.v1)); + EXPECT_THAT(res.v2, Eq(data.v2)); + des.ext(o, Growable{}); + EXPECT_THAT(res.v1, Eq(data.v1)); + EXPECT_THAT(res.v2, Eq(data.v2)); + }); + } + EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true)); } -TEST(SerializeExtensionGrowable, MultipleSessionsReadNewerVersionData) { - SerializationContext ctx; - DataV3 data{8454,987451, 45612}; - auto& ser = ctx.createSerializer(); +TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadOlderVersionData) +{ + SerializationContext ctx; + DataV2 data{ 8454, 987451 }; + auto& ser = ctx.createSerializer(); - for (auto i = 0; i < 10; ++i) { - ser.ext(data, Growable{}); - } - ctx.createDeserializer(); - DataV2 res{}; - auto& des = ctx.createDeserializer(); - for (auto i = 0; i < 10; ++i) { - des.ext(res, Growable{}); - EXPECT_THAT(res.v1, Eq(data.v1)); - EXPECT_THAT(res.v2, Eq(data.v2)); - } - EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true)); -} - -TEST(SerializeExtensionGrowable, MultipleSessionsReadOlderVersionData) { - SerializationContext ctx; - DataV2 data{8454,987451}; - auto& ser = ctx.createSerializer(); - - for (auto i = 0; i < 10; ++i) { - ser.ext(data, Growable{}); - } - ctx.createDeserializer(); - DataV3 res{}; - auto& des = ctx.createDeserializer(); - for (auto i = 0; i < 10; ++i) { - des.ext(res, Growable{}); - EXPECT_THAT(res.v1, Eq(data.v1)); - EXPECT_THAT(res.v2, Eq(data.v2)); - EXPECT_THAT(res.v3, Eq(0)); - } - EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true)); -} - -TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadSameVersionData) { - SerializationContext ctx; - DataV2 data{8454,987451}; - auto& ser = ctx.createSerializer(); - - for (auto i = 0; i < 10; ++i) { - ser.ext(data, Growable{}, [](decltype(ser)& ser, DataV2& o) { - ser.value4b(o.v1); - ser.value4b(o.v2); - ser.ext(o, Growable{}); - }); - } - ctx.createDeserializer(); - DataV2 res{}; - auto& des = ctx.createDeserializer(); - for (auto i = 0; i < 10; ++i) { - des.ext(res, Growable{}, [&res, &data](decltype(des)& des, DataV2& o) { - des.value4b(o.v1); - des.value4b(o.v2); - EXPECT_THAT(res.v1, Eq(data.v1)); - EXPECT_THAT(res.v2, Eq(data.v2)); - des.ext(o, Growable{}); - EXPECT_THAT(res.v1, Eq(data.v1)); - EXPECT_THAT(res.v2, Eq(data.v2)); - }); - } - EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true)); -} - -TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadNewerVersionData) { - SerializationContext ctx; - DataV3 data{8454,987451, 54124}; - auto& ser = ctx.createSerializer(); - - for (auto i = 0; i < 10; ++i) { - ser.ext(data, Growable{}, [](decltype(ser)& ser, DataV3& o) { - ser.value4b(o.v1); - ser.value4b(o.v2); - ser.ext(o, Growable{}); - //new fields can only be added at the end - ser.value4b(o.v3); - }); - } - ctx.createDeserializer(); - DataV2 res{}; - auto& des = ctx.createDeserializer(); - for (auto i = 0; i < 10; ++i) { - des.ext(res, Growable{}, [&res, &data](decltype(des)& des, DataV2& o) { - des.value4b(o.v1); - des.value4b(o.v2); - EXPECT_THAT(res.v1, Eq(data.v1)); - EXPECT_THAT(res.v2, Eq(data.v2)); - des.ext(o, Growable{}); - EXPECT_THAT(res.v1, Eq(data.v1)); - EXPECT_THAT(res.v2, Eq(data.v2)); - }); - } - EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true)); -} - -TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadOlderVersionData) { - SerializationContext ctx; - DataV2 data{8454,987451}; - auto& ser = ctx.createSerializer(); - - for (auto i = 0; i < 10; ++i) { - ser.ext(data, Growable{}, [](decltype(ser)& ser, DataV2& o) { - ser.value4b(o.v1); - ser.value4b(o.v2); - ser.ext(o, Growable{}); - }); - } - ctx.createDeserializer(); - DataV3 res{}; - auto& des = ctx.createDeserializer(); - for (auto i = 0; i < 10; ++i) { - des.ext(res, Growable{}, [&res, &data](decltype(des)& des, DataV3& o) { - des.value4b(o.v1); - des.value4b(o.v2); - EXPECT_THAT(res.v1, Eq(data.v1)); - EXPECT_THAT(res.v2, Eq(data.v2)); - des.ext(o, Growable{}); - EXPECT_THAT(res.v1, Eq(data.v1)); - EXPECT_THAT(res.v2, Eq(data.v2)); - EXPECT_THAT(res.v3, Eq(0)); - //new fields can only be added at the end - des.value4b(o.v3); - EXPECT_THAT(res.v3, Eq(0)); - }); - } - EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true)); + for (auto i = 0; i < 10; ++i) { + ser.ext(data, Growable{}, [](decltype(ser)& ser, DataV2& o) { + ser.value4b(o.v1); + ser.value4b(o.v2); + ser.ext(o, Growable{}); + }); + } + ctx.createDeserializer(); + DataV3 res{}; + auto& des = ctx.createDeserializer(); + for (auto i = 0; i < 10; ++i) { + des.ext(res, Growable{}, [&res, &data](decltype(des)& des, DataV3& o) { + des.value4b(o.v1); + des.value4b(o.v2); + EXPECT_THAT(res.v1, Eq(data.v1)); + EXPECT_THAT(res.v2, Eq(data.v2)); + des.ext(o, Growable{}); + EXPECT_THAT(res.v1, Eq(data.v1)); + EXPECT_THAT(res.v2, Eq(data.v2)); + EXPECT_THAT(res.v3, Eq(0)); + // new fields can only be added at the end + des.value4b(o.v3); + EXPECT_THAT(res.v3, Eq(0)); + }); + } + EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true)); } diff --git a/tests/serialization_ext_inheritance.cpp b/tests/serialization_ext_inheritance.cpp index 60498ab..644e3e2 100644 --- a/tests/serialization_ext_inheritance.cpp +++ b/tests/serialization_ext_inheritance.cpp @@ -1,28 +1,28 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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 "serialization_test_utils.h" #include #include -#include "serialization_test_utils.h" using bitsery::ext::BaseClass; using bitsery::ext::VirtualBaseClass; @@ -34,332 +34,400 @@ using testing::Eq; /* * base class */ -struct Base { - uint8_t x{}; - virtual ~Base() = default; +struct Base +{ + uint8_t x{}; + virtual ~Base() = default; }; -template -void serialize(S& s, Base& o) { - s.value1b(o.x); +template +void +serialize(S& s, Base& o) +{ + s.value1b(o.x); } /* * non virtual inheritance from base */ -struct Derive1NonVirtually:Base { - uint8_t y1{}; +struct Derive1NonVirtually : Base +{ + uint8_t y1{}; }; -template -void serialize(S& s, Derive1NonVirtually& o) { - s.ext(o, BaseClass{}); - s.value1b(o.y1); +template +void +serialize(S& s, Derive1NonVirtually& o) +{ + s.ext(o, BaseClass{}); + s.value1b(o.y1); } -struct Derive2NonVirtually:Base { - uint8_t y2{}; +struct Derive2NonVirtually : Base +{ + uint8_t y2{}; }; -template -void serialize(S& s, Derive2NonVirtually& o) { - //use lambda to serialize base - s.ext(o, BaseClass{}, [](S& s, Base& b) { - s.object(b); - }); - s.value1b(o.y2); +template +void +serialize(S& s, Derive2NonVirtually& o) +{ + // use lambda to serialize base + s.ext(o, BaseClass{}, [](S& s, Base& b) { s.object(b); }); + s.value1b(o.y2); } -struct MultipleInheritanceNonVirtualBase: Derive1NonVirtually, Derive2NonVirtually { - uint8_t z{}; +struct MultipleInheritanceNonVirtualBase + : Derive1NonVirtually + , Derive2NonVirtually +{ + uint8_t z{}; }; -template -void serialize(S& s, MultipleInheritanceNonVirtualBase& o) { - s.ext(o, BaseClass{}); - s.ext(o, BaseClass{}); - s.value1b(o.z); +template +void +serialize(S& s, MultipleInheritanceNonVirtualBase& o) +{ + s.ext(o, BaseClass{}); + s.ext(o, BaseClass{}); + s.value1b(o.z); } /* * virtual inheritance from base */ -struct Derive1Virtually:virtual Base { - uint8_t y1{}; +struct Derive1Virtually : virtual Base +{ + uint8_t y1{}; }; -template -void serialize(S& s, Derive1Virtually& o) { - s.ext(o, VirtualBaseClass{}); - s.value1b(o.y1); +template +void +serialize(S& s, Derive1Virtually& o) +{ + s.ext(o, VirtualBaseClass{}); + s.value1b(o.y1); } -struct Derive2Virtually:virtual Base { - uint8_t y2{}; +struct Derive2Virtually : virtual Base +{ + uint8_t y2{}; }; -template -void serialize(S& s, Derive2Virtually& o) { - s.ext(o, VirtualBaseClass{}); - s.value1b(o.y2); +template +void +serialize(S& s, Derive2Virtually& o) +{ + s.ext(o, VirtualBaseClass{}); + s.value1b(o.y2); } -struct MultipleInheritanceVirtualBase: Derive1Virtually, Derive2Virtually { - uint8_t z{}; - MultipleInheritanceVirtualBase() = default; +struct MultipleInheritanceVirtualBase + : Derive1Virtually + , Derive2Virtually +{ + uint8_t z{}; + MultipleInheritanceVirtualBase() = default; - MultipleInheritanceVirtualBase(uint8_t x_, uint8_t y1_, uint8_t y2_, uint8_t z_) { - x = x_; - y1 = y1_; - y2 = y2_; - z = z_; - } - - template - void serialize(S& s) { - s.ext(*this, BaseClass{}); - s.ext(*this, BaseClass{}); - s.value1b(z); - } + MultipleInheritanceVirtualBase(uint8_t x_, + uint8_t y1_, + uint8_t y2_, + uint8_t z_) + { + x = x_; + y1 = y1_; + y2 = y2_; + z = z_; + } + template + void serialize(S& s) + { + s.ext(*this, BaseClass{}); + s.ext(*this, BaseClass{}); + s.value1b(z); + } }; -bool operator == (const MultipleInheritanceVirtualBase& lhs, const MultipleInheritanceVirtualBase& rhs) { - return std::tie(lhs.x, lhs.y1, lhs.y2, lhs.z) == std::tie(rhs.x, rhs.y1, rhs.y2, rhs.z); +bool +operator==(const MultipleInheritanceVirtualBase& lhs, + const MultipleInheritanceVirtualBase& rhs) +{ + return std::tie(lhs.x, lhs.y1, lhs.y2, lhs.z) == + std::tie(rhs.x, rhs.y1, rhs.y2, rhs.z); } -TEST(SerializeExtensionInheritance, BaseClass) { +TEST(SerializeExtensionInheritance, BaseClass) +{ - Derive1NonVirtually d1{}; - d1.x = 187; - d1.y1 = 74; - Derive1NonVirtually rd1{}; + Derive1NonVirtually d1{}; + d1.x = 187; + d1.y1 = 74; + Derive1NonVirtually rd1{}; - SerContext ctx{}; - bitsery::ext::InheritanceContext inherCtxSer{}; - bitsery::ext::InheritanceContext inherCtxDes{}; - ctx.createSerializer(inherCtxSer).object(d1); - ctx.createDeserializer(inherCtxDes).object(rd1); + SerContext ctx{}; + bitsery::ext::InheritanceContext inherCtxSer{}; + bitsery::ext::InheritanceContext inherCtxDes{}; + ctx.createSerializer(inherCtxSer).object(d1); + ctx.createDeserializer(inherCtxDes).object(rd1); - EXPECT_THAT(rd1.x, Eq(d1.x)); - EXPECT_THAT(rd1.y1, Eq(d1.y1)); - EXPECT_THAT(ctx.getBufferSize(), Eq(2)); + EXPECT_THAT(rd1.x, Eq(d1.x)); + EXPECT_THAT(rd1.y1, Eq(d1.y1)); + EXPECT_THAT(ctx.getBufferSize(), Eq(2)); } -TEST(SerializeExtensionInheritance, VirtualBaseClass) { - Derive1Virtually d1{}; - d1.x = 15; - d1.y1 = 87; - Derive1Virtually rd1{}; +TEST(SerializeExtensionInheritance, VirtualBaseClass) +{ + Derive1Virtually d1{}; + d1.x = 15; + d1.y1 = 87; + Derive1Virtually rd1{}; - SerContext ctx{}; - bitsery::ext::InheritanceContext inherCtxSer{}; - bitsery::ext::InheritanceContext inherCtxDes{}; - ctx.createSerializer(inherCtxSer).object(d1); - ctx.createDeserializer(inherCtxDes).object(rd1); + SerContext ctx{}; + bitsery::ext::InheritanceContext inherCtxSer{}; + bitsery::ext::InheritanceContext inherCtxDes{}; + ctx.createSerializer(inherCtxSer).object(d1); + ctx.createDeserializer(inherCtxDes).object(rd1); - EXPECT_THAT(rd1.x, Eq(d1.x)); - EXPECT_THAT(rd1.y1, Eq(d1.y1)); - EXPECT_THAT(ctx.getBufferSize(), Eq(2)); + EXPECT_THAT(rd1.x, Eq(d1.x)); + EXPECT_THAT(rd1.y1, Eq(d1.y1)); + EXPECT_THAT(ctx.getBufferSize(), Eq(2)); } -TEST(SerializeExtensionInheritance, MultipleBasesWithoutVirtualInheritance) { - MultipleInheritanceNonVirtualBase md{}; - //x is ambiguous because we don't derive virtually - static_cast(md).x = 1; - static_cast(md).x = 2; - md.y1 = 4; - md.z = 5; - md.y2 = 6; - MultipleInheritanceNonVirtualBase res{}; +TEST(SerializeExtensionInheritance, MultipleBasesWithoutVirtualInheritance) +{ + MultipleInheritanceNonVirtualBase md{}; + // x is ambiguous because we don't derive virtually + static_cast(md).x = 1; + static_cast(md).x = 2; + md.y1 = 4; + md.z = 5; + md.y2 = 6; + MultipleInheritanceNonVirtualBase res{}; - SerContext ctx{}; - bitsery::ext::InheritanceContext inherCtxSer{}; - bitsery::ext::InheritanceContext inherCtxDes{}; - ctx.createSerializer(inherCtxSer).object(md); - ctx.createDeserializer(inherCtxDes).object(res); - - EXPECT_THAT(static_cast(res).x, Eq(static_cast(md).x)); - EXPECT_THAT(static_cast(res).x, Eq(static_cast(md).x)); - EXPECT_THAT(res.y1, Eq(md.y1)); - EXPECT_THAT(res.y2, Eq(md.y2)); - EXPECT_THAT(res.z, Eq(md.z)); - EXPECT_THAT(ctx.getBufferSize(), Eq(5)); //5 because two bases + SerContext ctx{}; + bitsery::ext::InheritanceContext inherCtxSer{}; + bitsery::ext::InheritanceContext inherCtxDes{}; + ctx.createSerializer(inherCtxSer).object(md); + ctx.createDeserializer(inherCtxDes).object(res); + EXPECT_THAT(static_cast(res).x, + Eq(static_cast(md).x)); + EXPECT_THAT(static_cast(res).x, + Eq(static_cast(md).x)); + EXPECT_THAT(res.y1, Eq(md.y1)); + EXPECT_THAT(res.y2, Eq(md.y2)); + EXPECT_THAT(res.z, Eq(md.z)); + EXPECT_THAT(ctx.getBufferSize(), Eq(5)); // 5 because two bases } -TEST(SerializeExtensionInheritance, WhenNoVirtualInheritanceExistsThenInheritanceContextIsNotRequired) { - MultipleInheritanceNonVirtualBase md{}; - //x is ambiguous because we don't derive virtually - static_cast(md).x = 1; - static_cast(md).x = 2; - md.y1 = 4; - md.z = 5; - md.y2 = 6; - MultipleInheritanceNonVirtualBase res{}; +TEST(SerializeExtensionInheritance, + WhenNoVirtualInheritanceExistsThenInheritanceContextIsNotRequired) +{ + MultipleInheritanceNonVirtualBase md{}; + // x is ambiguous because we don't derive virtually + static_cast(md).x = 1; + static_cast(md).x = 2; + md.y1 = 4; + md.z = 5; + md.y2 = 6; + MultipleInheritanceNonVirtualBase res{}; - //without InheritanceContext - SerializationContext ctx{}; - ctx.createSerializer().object(md); - ctx.createDeserializer().object(res); - - EXPECT_THAT(static_cast(res).x, Eq(static_cast(md).x)); - EXPECT_THAT(static_cast(res).x, Eq(static_cast(md).x)); - EXPECT_THAT(res.y1, Eq(md.y1)); - EXPECT_THAT(res.y2, Eq(md.y2)); - EXPECT_THAT(res.z, Eq(md.z)); - EXPECT_THAT(ctx.getBufferSize(), Eq(5)); //5 because two bases + // without InheritanceContext + SerializationContext ctx{}; + ctx.createSerializer().object(md); + ctx.createDeserializer().object(res); + EXPECT_THAT(static_cast(res).x, + Eq(static_cast(md).x)); + EXPECT_THAT(static_cast(res).x, + Eq(static_cast(md).x)); + EXPECT_THAT(res.y1, Eq(md.y1)); + EXPECT_THAT(res.y2, Eq(md.y2)); + EXPECT_THAT(res.z, Eq(md.z)); + EXPECT_THAT(ctx.getBufferSize(), Eq(5)); // 5 because two bases } +TEST(SerializeExtensionInheritance, MultipleBasesWithVirtualInheritance) +{ + MultipleInheritanceVirtualBase md{ 3, 7, 5, 15 }; + MultipleInheritanceVirtualBase res{}; - -TEST(SerializeExtensionInheritance, MultipleBasesWithVirtualInheritance) { - MultipleInheritanceVirtualBase md{3,7,5,15}; - MultipleInheritanceVirtualBase res{}; - - SerContext ctx{}; - bitsery::ext::InheritanceContext inherCtxSer{}; - bitsery::ext::InheritanceContext inherCtxDes{}; - ctx.createSerializer(inherCtxSer).object(md); - ctx.createDeserializer(inherCtxDes).object(res); - EXPECT_THAT(res, Eq(md)); - EXPECT_THAT(ctx.getBufferSize(), Eq(4)); //4 because virtual base + SerContext ctx{}; + bitsery::ext::InheritanceContext inherCtxSer{}; + bitsery::ext::InheritanceContext inherCtxDes{}; + ctx.createSerializer(inherCtxSer).object(md); + ctx.createDeserializer(inherCtxDes).object(res); + EXPECT_THAT(res, Eq(md)); + EXPECT_THAT(ctx.getBufferSize(), Eq(4)); // 4 because virtual base } -TEST(SerializeExtensionInheritance, MultipleBasesWithVirtualInheritanceMultipleObjects) { - std::vector data; - data.emplace_back(4,8,7,9); - data.emplace_back(1,2,3,4); - data.emplace_back(8,7,15,97); - data.emplace_back(54,132,45,84); - data.emplace_back(27,85,41,2); - std::vector res{}; +TEST(SerializeExtensionInheritance, + MultipleBasesWithVirtualInheritanceMultipleObjects) +{ + std::vector data; + data.emplace_back(4, 8, 7, 9); + data.emplace_back(1, 2, 3, 4); + data.emplace_back(8, 7, 15, 97); + data.emplace_back(54, 132, 45, 84); + data.emplace_back(27, 85, 41, 2); + std::vector res{}; - SerContext ctx{}; - bitsery::ext::InheritanceContext inherCtxSer{}; - bitsery::ext::InheritanceContext inherCtxDes{}; - ctx.createSerializer(inherCtxSer).container(data, 10); - ctx.createDeserializer(inherCtxDes).container(res, 10); - EXPECT_THAT(res, ::testing::ContainerEq(data)); - EXPECT_THAT(ctx.getBufferSize(), Eq(1 + 4 * data.size())); //1 container size + 4 because virtual base * elements + SerContext ctx{}; + bitsery::ext::InheritanceContext inherCtxSer{}; + bitsery::ext::InheritanceContext inherCtxDes{}; + ctx.createSerializer(inherCtxSer).container(data, 10); + ctx.createDeserializer(inherCtxDes).container(res, 10); + EXPECT_THAT(res, ::testing::ContainerEq(data)); + EXPECT_THAT( + ctx.getBufferSize(), + Eq(1 + + 4 * + data.size())); // 1 container size + 4 because virtual base * elements } // -class BasePrivateSerialize { +class BasePrivateSerialize +{ public: - explicit BasePrivateSerialize(uint8_t v):_v{v} {} - uint8_t getX() const { return _v; } + explicit BasePrivateSerialize(uint8_t v) + : _v{ v } + { + } + uint8_t getX() const { return _v; } + private: - uint8_t _v; - - friend bitsery::Access; - template - void serialize(S& s) { - s.value1b(_v); - } + uint8_t _v; + friend bitsery::Access; + template + void serialize(S& s) + { + s.value1b(_v); + } }; -class DerivedPrivateBase: public BasePrivateSerialize { +class DerivedPrivateBase : public BasePrivateSerialize +{ public: - explicit DerivedPrivateBase(uint8_t v) : BasePrivateSerialize(v) {} - uint8_t z{}; + explicit DerivedPrivateBase(uint8_t v) + : BasePrivateSerialize(v) + { + } + uint8_t z{}; }; -template -void serialize(S& s, DerivedPrivateBase& o) { - //use lambda for base serialization - s.ext(o, BaseClass{}, [](S& s, BasePrivateSerialize& b) { - s.object(b); - }); - s.value1b(o.z); +template +void +serialize(S& s, DerivedPrivateBase& o) +{ + // use lambda for base serialization + s.ext(o, + BaseClass{}, + [](S& s, BasePrivateSerialize& b) { s.object(b); }); + s.value1b(o.z); } -struct BaseNonMemberSerialize { - uint8_t x{}; +struct BaseNonMemberSerialize +{ + uint8_t x{}; }; -template -void serialize(S& s, BaseNonMemberSerialize& o) { - s.value1b(o.x); +template +void +serialize(S& s, BaseNonMemberSerialize& o) +{ + s.value1b(o.x); } - -struct DerivedMemberSerialize: public BaseNonMemberSerialize { - uint8_t z{}; - template - void serialize(S& s) { - s.ext(*this, BaseClass{}); - s.value1b(z); - } +struct DerivedMemberSerialize : public BaseNonMemberSerialize +{ + uint8_t z{}; + template + void serialize(S& s) + { + s.ext(*this, BaseClass{}); + s.value1b(z); + } }; -//explicitly select serialize functions, for types that has ambiguous serialize functions +// explicitly select serialize functions, for types that has ambiguous serialize +// functions namespace bitsery { - template <> - struct SelectSerializeFnc:UseNonMemberFnc {}; - - template <> - struct SelectSerializeFnc:UseMemberFnc {}; -} - - -TEST(SerializeExtensionInheritance, WhenDerivedClassHasAmbiguousSerializeFunctionThenExplicitlySelectSpecialization) { - DerivedPrivateBase data1{43}; - data1.z = 87; - DerivedMemberSerialize data2{}; - data2.x = 71; - data2.z = 22; - DerivedPrivateBase res1{0}; - DerivedMemberSerialize res2{}; - - SerContext ctx{}; - bitsery::ext::InheritanceContext inherCtxSer{}; - bitsery::ext::InheritanceContext inherCtxDes{}; - ctx.createSerializer(inherCtxSer).object(data1); - ctx.createSerializer(inherCtxSer).object(data2); - ctx.createDeserializer(inherCtxDes).object(res1); - ctx.createDeserializer(inherCtxDes).object(res2); - EXPECT_THAT(res1.getX(), Eq(data1.getX())); - EXPECT_THAT(res1.z, Eq(data1.z)); - EXPECT_THAT(res2.x, Eq(data2.x)); - EXPECT_THAT(res2.z, Eq(data2.z)); -} - -struct AbstractBase { - uint8_t x{}; - virtual void exec() = 0; - virtual ~AbstractBase() = default; - - template - void serialize(S& s) { - s.value1b(x); - } +template<> +struct SelectSerializeFnc : UseNonMemberFnc +{ }; -struct ImplementedBase:AbstractBase { - uint8_t y{}; - void exec() override {} +template<> +struct SelectSerializeFnc : UseMemberFnc +{ +}; +} - template - void serialize(S& s) { - s.ext(*this, BaseClass{}); - s.value1b(y); - } +TEST( + SerializeExtensionInheritance, + WhenDerivedClassHasAmbiguousSerializeFunctionThenExplicitlySelectSpecialization) +{ + DerivedPrivateBase data1{ 43 }; + data1.z = 87; + DerivedMemberSerialize data2{}; + data2.x = 71; + data2.z = 22; + DerivedPrivateBase res1{ 0 }; + DerivedMemberSerialize res2{}; + + SerContext ctx{}; + bitsery::ext::InheritanceContext inherCtxSer{}; + bitsery::ext::InheritanceContext inherCtxDes{}; + ctx.createSerializer(inherCtxSer).object(data1); + ctx.createSerializer(inherCtxSer).object(data2); + ctx.createDeserializer(inherCtxDes).object(res1); + ctx.createDeserializer(inherCtxDes).object(res2); + EXPECT_THAT(res1.getX(), Eq(data1.getX())); + EXPECT_THAT(res1.z, Eq(data1.z)); + EXPECT_THAT(res2.x, Eq(data2.x)); + EXPECT_THAT(res2.z, Eq(data2.z)); +} + +struct AbstractBase +{ + uint8_t x{}; + virtual void exec() = 0; + virtual ~AbstractBase() = default; + + template + void serialize(S& s) + { + s.value1b(x); + } }; -TEST(SerializeExtensionInheritance, CanSerializeAbstractClass) { - ImplementedBase data{}; - data.x = 4; - data.y = 2; - data.exec(); - ImplementedBase res{}; - SerContext ctx{}; - bitsery::ext::InheritanceContext inherCtxSer{}; - bitsery::ext::InheritanceContext inherCtxDes{}; - ctx.createSerializer(inherCtxSer).object(data); - ctx.createDeserializer(inherCtxDes).object(res); - EXPECT_THAT(res.x, Eq(data.x)); - EXPECT_THAT(res.y, Eq(data.y)); +struct ImplementedBase : AbstractBase +{ + uint8_t y{}; + void exec() override {} + + template + void serialize(S& s) + { + s.ext(*this, BaseClass{}); + s.value1b(y); + } +}; + +TEST(SerializeExtensionInheritance, CanSerializeAbstractClass) +{ + ImplementedBase data{}; + data.x = 4; + data.y = 2; + data.exec(); + ImplementedBase res{}; + SerContext ctx{}; + bitsery::ext::InheritanceContext inherCtxSer{}; + bitsery::ext::InheritanceContext inherCtxDes{}; + ctx.createSerializer(inherCtxSer).object(data); + ctx.createDeserializer(inherCtxDes).object(res); + EXPECT_THAT(res.x, Eq(data.x)); + EXPECT_THAT(res.y, Eq(data.y)); } \ No newline at end of file diff --git a/tests/serialization_ext_pointer.cpp b/tests/serialization_ext_pointer.cpp index eee5861..72dace1 100644 --- a/tests/serialization_ext_pointer.cpp +++ b/tests/serialization_ext_pointer.cpp @@ -1,532 +1,618 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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 "serialization_test_utils.h" #include #include -#include "serialization_test_utils.h" -using bitsery::ext::PointerOwner; -using bitsery::ext::PointerObserver; -using bitsery::ext::ReferencedByPointer; using bitsery::ext::PointerLinkingContext; +using bitsery::ext::PointerObserver; +using bitsery::ext::PointerOwner; using bitsery::ext::PointerType; +using bitsery::ext::ReferencedByPointer; using testing::Eq; using SerContext = BasicSerializationContext; -class SerializeExtensionPointerSerialization : public testing::Test { +class SerializeExtensionPointerSerialization : public testing::Test +{ public: - //data used for serialization - int16_t d1{1597}; - int16_t *pd1 = &d1; - MyEnumClass d2{MyEnumClass::E2}; - MyEnumClass *pd2 = &d2; - MyStruct1 d3{184, 897}; - MyStruct1 *pd3 = &d3; + // data used for serialization + int16_t d1{ 1597 }; + int16_t* pd1 = &d1; + MyEnumClass d2{ MyEnumClass::E2 }; + MyEnumClass* pd2 = &d2; + MyStruct1 d3{ 184, 897 }; + MyStruct1* pd3 = &d3; - //data used for deserialization - int16_t r1{-84}; - int16_t *pr1 = &r1; - MyEnumClass r2{MyEnumClass::E4}; - MyEnumClass *pr2 = &r2; - MyStruct1 r3{-4984, -14597}; - MyStruct1 *pr3 = &r3; + // data used for deserialization + int16_t r1{ -84 }; + int16_t* pr1 = &r1; + MyEnumClass r2{ MyEnumClass::E4 }; + MyEnumClass* pr2 = &r2; + MyStruct1 r3{ -4984, -14597 }; + MyStruct1* pr3 = &r3; - //null pointers - int16_t *p1null = nullptr; - MyEnumClass *p2null = nullptr; - MyStruct1 *p3null = nullptr; + // null pointers + int16_t* p1null = nullptr; + MyEnumClass* p2null = nullptr; + MyStruct1* p3null = nullptr; - PointerLinkingContext plctx1{}; - SerContext sctx1{}; + PointerLinkingContext plctx1{}; + SerContext sctx1{}; + typename SerContext::TSerializer& createSerializer() + { + return sctx1.createSerializer(plctx1); + } - typename SerContext::TSerializer& createSerializer() { - return sctx1.createSerializer(plctx1); - } - - typename SerContext::TDeserializer& createDeserializer() { - return sctx1.createDeserializer(plctx1); - } - - bool isPointerContextValid() { - return plctx1.isValid(); - } + typename SerContext::TDeserializer& createDeserializer() + { + return sctx1.createDeserializer(plctx1); + } + bool isPointerContextValid() { return plctx1.isValid(); } }; -TEST(SerializeExtensionPointer, RequiresPointerLinkingContext) { - MyStruct1 *data = nullptr; - //linking context - PointerLinkingContext plctx1{}; - SerContext sctx1; - sctx1.createSerializer(plctx1).ext(data, PointerOwner{}); - sctx1.createDeserializer(plctx1).ext(data, PointerOwner{}); +TEST(SerializeExtensionPointer, RequiresPointerLinkingContext) +{ + MyStruct1* data = nullptr; + // linking context + PointerLinkingContext plctx1{}; + SerContext sctx1; + sctx1.createSerializer(plctx1).ext(data, PointerOwner{}); + sctx1.createDeserializer(plctx1).ext(data, PointerOwner{}); - //linking context in tuple - using ContextInTuple = std::tuple; - ContextInTuple plctx2(0, PointerLinkingContext{}, 0.0f, 'a'); - BasicSerializationContext sctx2; - sctx2.createSerializer(plctx2).ext(data, PointerObserver{}); - sctx2.createDeserializer(plctx2).ext(data, PointerObserver{}); + // linking context in tuple + using ContextInTuple = std::tuple; + ContextInTuple plctx2(0, PointerLinkingContext{}, 0.0f, 'a'); + BasicSerializationContext sctx2; + sctx2.createSerializer(plctx2).ext(data, PointerObserver{}); + sctx2.createDeserializer(plctx2).ext(data, PointerObserver{}); } -TEST(SerializeExtensionPointer, PointerLinkingContextAcceptsMultipleSharedOwnersAndReturnSameId) { - MyStruct1 data{}; - //pretend that this is shared ptr - MyStruct1 *sharedPtr = &data; - //linking context - PointerLinkingContext plctx1{}; - EXPECT_THAT(plctx1.getInfoByPtr(sharedPtr, bitsery::ext::PointerOwnershipType::SharedOwner).id, Eq(1)); - EXPECT_THAT(plctx1.getInfoByPtr(sharedPtr, bitsery::ext::PointerOwnershipType::SharedObserver).id, Eq(1)); - EXPECT_THAT(plctx1.getInfoByPtr(sharedPtr, bitsery::ext::PointerOwnershipType::SharedOwner).id, Eq(1)); +TEST(SerializeExtensionPointer, + PointerLinkingContextAcceptsMultipleSharedOwnersAndReturnSameId) +{ + MyStruct1 data{}; + // pretend that this is shared ptr + MyStruct1* sharedPtr = &data; + // linking context + PointerLinkingContext plctx1{}; + EXPECT_THAT( + plctx1 + .getInfoByPtr(sharedPtr, bitsery::ext::PointerOwnershipType::SharedOwner) + .id, + Eq(1)); + EXPECT_THAT(plctx1 + .getInfoByPtr( + sharedPtr, bitsery::ext::PointerOwnershipType::SharedObserver) + .id, + Eq(1)); + EXPECT_THAT( + plctx1 + .getInfoByPtr(sharedPtr, bitsery::ext::PointerOwnershipType::SharedOwner) + .id, + Eq(1)); } -TEST(SerializeExtensionPointer, WhenOnlySharedObserverThenPointerLinkingContextIsInvalid) { - MyStruct1 data1{}; - MyStruct1 data2{}; - //pretend that this is shared ptr - MyStruct1 *sharedPtr1 = &data1; - MyStruct1 *sharedPtr2 = &data2; - //linking context - PointerLinkingContext plctx1{}; - EXPECT_THAT(plctx1.getInfoByPtr(sharedPtr1, bitsery::ext::PointerOwnershipType::SharedObserver).id, Eq(1)); - EXPECT_THAT(plctx1.getInfoByPtr(sharedPtr2, bitsery::ext::PointerOwnershipType::SharedObserver).id, Eq(2)); - EXPECT_THAT(plctx1.getInfoByPtr(sharedPtr1, bitsery::ext::PointerOwnershipType::SharedObserver).id, Eq(1)); - EXPECT_FALSE(plctx1.isValid()); - EXPECT_THAT(plctx1.getInfoByPtr(sharedPtr1, bitsery::ext::PointerOwnershipType::SharedOwner).id, Eq(1)); - EXPECT_THAT(plctx1.getInfoByPtr(sharedPtr2, bitsery::ext::PointerOwnershipType::SharedOwner).id, Eq(2)); - EXPECT_TRUE(plctx1.isValid()); +TEST(SerializeExtensionPointer, + WhenOnlySharedObserverThenPointerLinkingContextIsInvalid) +{ + MyStruct1 data1{}; + MyStruct1 data2{}; + // pretend that this is shared ptr + MyStruct1* sharedPtr1 = &data1; + MyStruct1* sharedPtr2 = &data2; + // linking context + PointerLinkingContext plctx1{}; + EXPECT_THAT( + plctx1 + .getInfoByPtr(sharedPtr1, + bitsery::ext::PointerOwnershipType::SharedObserver) + .id, + Eq(1)); + EXPECT_THAT( + plctx1 + .getInfoByPtr(sharedPtr2, + bitsery::ext::PointerOwnershipType::SharedObserver) + .id, + Eq(2)); + EXPECT_THAT( + plctx1 + .getInfoByPtr(sharedPtr1, + bitsery::ext::PointerOwnershipType::SharedObserver) + .id, + Eq(1)); + EXPECT_FALSE(plctx1.isValid()); + EXPECT_THAT( + plctx1 + .getInfoByPtr(sharedPtr1, bitsery::ext::PointerOwnershipType::SharedOwner) + .id, + Eq(1)); + EXPECT_THAT( + plctx1 + .getInfoByPtr(sharedPtr2, bitsery::ext::PointerOwnershipType::SharedOwner) + .id, + Eq(2)); + EXPECT_TRUE(plctx1.isValid()); } -TEST_F(SerializeExtensionPointerSerialization, WhenPointersAreNullThenIsValid) { +TEST_F(SerializeExtensionPointerSerialization, WhenPointersAreNullThenIsValid) +{ - auto& ser = createSerializer(); - ser.ext2b(p1null, PointerOwner{}); - ser.ext2b(p1null, PointerObserver{}); - ser.ext(p3null, PointerOwner{}); - ser.ext(p3null, PointerObserver{}); - createDeserializer(); - EXPECT_THAT(sctx1.ser->adapter().writtenBytesCount(), Eq(4)); + auto& ser = createSerializer(); + ser.ext2b(p1null, PointerOwner{}); + ser.ext2b(p1null, PointerObserver{}); + ser.ext(p3null, PointerOwner{}); + ser.ext(p3null, PointerObserver{}); + createDeserializer(); + EXPECT_THAT(sctx1.ser->adapter().writtenBytesCount(), Eq(4)); - EXPECT_THAT(plctx1.isValid(), Eq(true)); + EXPECT_THAT(plctx1.isValid(), Eq(true)); } #ifndef NDEBUG -TEST_F(SerializeExtensionPointerSerialization, WhenPointerOwnerIsNotUniqueThenAssert) { +TEST_F(SerializeExtensionPointerSerialization, + WhenPointerOwnerIsNotUniqueThenAssert) +{ - auto& ser = createSerializer(); - ser.ext2b(p1null, PointerOwner{}); - ser.ext2b(pd1, PointerOwner{}); - ser.ext4b(pd2, PointerOwner{}); - ser.ext2b(p1null, PointerOwner{}); - //dublicating pointer - EXPECT_DEATH(ser.ext2b(pd1, PointerOwner{}), ""); + auto& ser = createSerializer(); + ser.ext2b(p1null, PointerOwner{}); + ser.ext2b(pd1, PointerOwner{}); + ser.ext4b(pd2, PointerOwner{}); + ser.ext2b(p1null, PointerOwner{}); + // dublicating pointer + EXPECT_DEATH(ser.ext2b(pd1, PointerOwner{}), ""); } -TEST_F(SerializeExtensionPointerSerialization, WhenRererencedByPointerIsSameAsPointerOwnerThenAssert1) { - auto& ser1 = createSerializer(); - ser1.ext4b(pd2, PointerOwner{}); - ser1.ext(d3, ReferencedByPointer{}); +TEST_F(SerializeExtensionPointerSerialization, + WhenRererencedByPointerIsSameAsPointerOwnerThenAssert1) +{ + auto& ser1 = createSerializer(); + ser1.ext4b(pd2, PointerOwner{}); + ser1.ext(d3, ReferencedByPointer{}); - EXPECT_DEATH(ser1.ext(pd3, PointerOwner{}), ""); + EXPECT_DEATH(ser1.ext(pd3, PointerOwner{}), ""); } -TEST_F(SerializeExtensionPointerSerialization, WhenRererencedByPointerIsSameAsPointerOwnerThenAssert2) { - auto& ser1 = createSerializer(); - ser1.ext2b(pd1, PointerOwner{}); - ser1.ext4b(d2, ReferencedByPointer{}); - EXPECT_DEATH(ser1.ext2b(d1, ReferencedByPointer{}), ""); +TEST_F(SerializeExtensionPointerSerialization, + WhenRererencedByPointerIsSameAsPointerOwnerThenAssert2) +{ + auto& ser1 = createSerializer(); + ser1.ext2b(pd1, PointerOwner{}); + ser1.ext4b(d2, ReferencedByPointer{}); + EXPECT_DEATH(ser1.ext2b(d1, ReferencedByPointer{}), ""); } -TEST_F(SerializeExtensionPointerSerialization, WhenNonNullPointerIsNullThenAssert) { - auto& ser1 = createSerializer(); - EXPECT_DEATH(ser1.ext2b(p1null, PointerOwner{PointerType::NotNull}), ""); - EXPECT_DEATH(ser1.ext2b(p1null, PointerObserver{PointerType::NotNull}), ""); +TEST_F(SerializeExtensionPointerSerialization, + WhenNonNullPointerIsNullThenAssert) +{ + auto& ser1 = createSerializer(); + EXPECT_DEATH(ser1.ext2b(p1null, PointerOwner{ PointerType::NotNull }), ""); + EXPECT_DEATH(ser1.ext2b(p1null, PointerObserver{ PointerType::NotNull }), ""); } #endif -TEST_F(SerializeExtensionPointerSerialization, WhenPointerObserverPointsToOwnerThenIsValid) { - auto& ser1 = createSerializer(); - ser1.ext2b(pd1, PointerOwner{}); - ser1.ext2b(p1null, PointerObserver{}); - EXPECT_THAT(plctx1.isValid(), Eq(true)); - ser1.ext4b(pd2, PointerObserver{});//points to d2, and d2 is not still marked as owner - EXPECT_THAT(plctx1.isValid(), Eq(false)); - ser1.ext4b(pd2, PointerOwner{});//now d2 is owning pointer - ser1.ext4b(pd2, PointerObserver{});//points to d2, but this time d2 has owner - ser1.ext2b(p1null, PointerObserver{}); - EXPECT_THAT(plctx1.isValid(), Eq(true)); +TEST_F(SerializeExtensionPointerSerialization, + WhenPointerObserverPointsToOwnerThenIsValid) +{ + auto& ser1 = createSerializer(); + ser1.ext2b(pd1, PointerOwner{}); + ser1.ext2b(p1null, PointerObserver{}); + EXPECT_THAT(plctx1.isValid(), Eq(true)); + ser1.ext4b( + pd2, + PointerObserver{}); // points to d2, and d2 is not still marked as owner + EXPECT_THAT(plctx1.isValid(), Eq(false)); + ser1.ext4b(pd2, PointerOwner{}); // now d2 is owning pointer + ser1.ext4b(pd2, PointerObserver{}); // points to d2, but this time d2 has + // owner + ser1.ext2b(p1null, PointerObserver{}); + EXPECT_THAT(plctx1.isValid(), Eq(true)); } -TEST_F(SerializeExtensionPointerSerialization, ReferenceTypeCanAlsoBeReferencedByPointerObservers) { - auto& ser1 = createSerializer(); - ser1.ext2b(p1null, PointerObserver{}); - EXPECT_THAT(plctx1.isValid(), Eq(true)); - ser1.ext4b(pd2, PointerObserver{});//points to d2, and d2 is not still marked as owner - EXPECT_THAT(plctx1.isValid(), Eq(false)); - ser1.ext4b(d2, ReferencedByPointer{});//now d2 is marked by marked as owning pointer - ser1.ext4b(pd2, PointerObserver{});//points to d2, but this time d2 has owner - ser1.ext(p3null, PointerObserver{}); - EXPECT_THAT(plctx1.isValid(), Eq(true)); +TEST_F(SerializeExtensionPointerSerialization, + ReferenceTypeCanAlsoBeReferencedByPointerObservers) +{ + auto& ser1 = createSerializer(); + ser1.ext2b(p1null, PointerObserver{}); + EXPECT_THAT(plctx1.isValid(), Eq(true)); + ser1.ext4b( + pd2, + PointerObserver{}); // points to d2, and d2 is not still marked as owner + EXPECT_THAT(plctx1.isValid(), Eq(false)); + ser1.ext4b( + d2, ReferencedByPointer{}); // now d2 is marked by marked as owning pointer + ser1.ext4b(pd2, PointerObserver{}); // points to d2, but this time d2 has + // owner + ser1.ext(p3null, PointerObserver{}); + EXPECT_THAT(plctx1.isValid(), Eq(true)); } -TEST_F(SerializeExtensionPointerSerialization, WhenPointerIsNullThenPointerIdIsZero) { - auto& ser1 = createSerializer(); - ser1.ext(p3null, PointerOwner{}); - ser1.ext2b(p1null, PointerObserver{}); - createDeserializer(); - EXPECT_THAT(sctx1.ser->adapter().writtenBytesCount(), Eq(2)); - size_t res; - bitsery::details::readSize(sctx1.des->adapter(), res, 0, std::false_type{}); - EXPECT_THAT(res, Eq(0)); - bitsery::details::readSize(sctx1.des->adapter(), res, 0, std::false_type{}); - EXPECT_THAT(res, Eq(0)); +TEST_F(SerializeExtensionPointerSerialization, + WhenPointerIsNullThenPointerIdIsZero) +{ + auto& ser1 = createSerializer(); + ser1.ext(p3null, PointerOwner{}); + ser1.ext2b(p1null, PointerObserver{}); + createDeserializer(); + EXPECT_THAT(sctx1.ser->adapter().writtenBytesCount(), Eq(2)); + size_t res; + bitsery::details::readSize(sctx1.des->adapter(), res, 0, std::false_type{}); + EXPECT_THAT(res, Eq(0)); + bitsery::details::readSize(sctx1.des->adapter(), res, 0, std::false_type{}); + EXPECT_THAT(res, Eq(0)); } -TEST_F(SerializeExtensionPointerSerialization, PointerIdsStartsFromOne) { - auto& ser1 = createSerializer(); - ser1.ext2b(pd1, PointerObserver{}); - ser1.ext4b(pd2, PointerObserver{}); - ser1.ext4b(pd2, PointerObserver{}); - ser1.ext2b(p1null, PointerObserver{}); - createDeserializer(); - EXPECT_THAT(sctx1.ser->adapter().writtenBytesCount(), Eq(4)); - size_t res; - bitsery::details::readSize(sctx1.des->adapter(), res, 0, std::false_type{}); - EXPECT_THAT(res, Eq(1)); - bitsery::details::readSize(sctx1.des->adapter(), res, 0, std::false_type{}); - EXPECT_THAT(res, Eq(2)); - bitsery::details::readSize(sctx1.des->adapter(), res, 0, std::false_type{}); - EXPECT_THAT(res, Eq(2)); - bitsery::details::readSize(sctx1.des->adapter(), res, 0, std::false_type{}); - EXPECT_THAT(res, Eq(0)); +TEST_F(SerializeExtensionPointerSerialization, PointerIdsStartsFromOne) +{ + auto& ser1 = createSerializer(); + ser1.ext2b(pd1, PointerObserver{}); + ser1.ext4b(pd2, PointerObserver{}); + ser1.ext4b(pd2, PointerObserver{}); + ser1.ext2b(p1null, PointerObserver{}); + createDeserializer(); + EXPECT_THAT(sctx1.ser->adapter().writtenBytesCount(), Eq(4)); + size_t res; + bitsery::details::readSize(sctx1.des->adapter(), res, 0, std::false_type{}); + EXPECT_THAT(res, Eq(1)); + bitsery::details::readSize(sctx1.des->adapter(), res, 0, std::false_type{}); + EXPECT_THAT(res, Eq(2)); + bitsery::details::readSize(sctx1.des->adapter(), res, 0, std::false_type{}); + EXPECT_THAT(res, Eq(2)); + bitsery::details::readSize(sctx1.des->adapter(), res, 0, std::false_type{}); + EXPECT_THAT(res, Eq(0)); } -TEST_F(SerializeExtensionPointerSerialization, PointerObserversDoesntSerializeObject) { - auto& ser1 = createSerializer(); - ser1.ext2b(pd1, PointerObserver{}); - ser1.ext4b(pd2, PointerObserver{}); - ser1.ext4b(pd2, PointerObserver{}); - createDeserializer(); - EXPECT_THAT(sctx1.ser->adapter().writtenBytesCount(), Eq(3)); +TEST_F(SerializeExtensionPointerSerialization, + PointerObserversDoesntSerializeObject) +{ + auto& ser1 = createSerializer(); + ser1.ext2b(pd1, PointerObserver{}); + ser1.ext4b(pd2, PointerObserver{}); + ser1.ext4b(pd2, PointerObserver{}); + createDeserializer(); + EXPECT_THAT(sctx1.ser->adapter().writtenBytesCount(), Eq(3)); } -TEST_F(SerializeExtensionPointerSerialization, ReferencedByPointerSerializesIdAndObject) { - auto& ser1 = createSerializer(); - ser1.ext2b(d1, ReferencedByPointer{}); - ser1.ext4b(d2, ReferencedByPointer{}); - ser1.ext4b(pd2, PointerObserver{}); - auto& des = createDeserializer(); - EXPECT_THAT(sctx1.ser->adapter().writtenBytesCount(), Eq(3 + 6)); - size_t id{}; - bitsery::details::readSize(sctx1.des->adapter(), id, 0, std::false_type{}); - EXPECT_THAT(id, Eq(1)); - des.value2b(r1); - EXPECT_THAT(r1, Eq(d1)); - bitsery::details::readSize(sctx1.des->adapter(), id, 0, std::false_type{}); - EXPECT_THAT(id, Eq(2)); - des.value4b(r2); - EXPECT_THAT(r2, Eq(d2)); - bitsery::details::readSize(sctx1.des->adapter(), id, 0, std::false_type{}); - EXPECT_THAT(id, Eq(2)); +TEST_F(SerializeExtensionPointerSerialization, + ReferencedByPointerSerializesIdAndObject) +{ + auto& ser1 = createSerializer(); + ser1.ext2b(d1, ReferencedByPointer{}); + ser1.ext4b(d2, ReferencedByPointer{}); + ser1.ext4b(pd2, PointerObserver{}); + auto& des = createDeserializer(); + EXPECT_THAT(sctx1.ser->adapter().writtenBytesCount(), Eq(3 + 6)); + size_t id{}; + bitsery::details::readSize(sctx1.des->adapter(), id, 0, std::false_type{}); + EXPECT_THAT(id, Eq(1)); + des.value2b(r1); + EXPECT_THAT(r1, Eq(d1)); + bitsery::details::readSize(sctx1.des->adapter(), id, 0, std::false_type{}); + EXPECT_THAT(id, Eq(2)); + des.value4b(r2); + EXPECT_THAT(r2, Eq(d2)); + bitsery::details::readSize(sctx1.des->adapter(), id, 0, std::false_type{}); + EXPECT_THAT(id, Eq(2)); } -TEST_F(SerializeExtensionPointerSerialization, PointerOwnerSerializesIdAndObject) { - auto& ser1 = createSerializer(); - ser1.ext4b(pd2, PointerOwner{}); - ser1.ext(pd3, PointerOwner{}); - auto& des1 = createDeserializer(); - //2x ids + int32_t + MyStruct1 - EXPECT_THAT(sctx1.ser->adapter().writtenBytesCount(), Eq(2 + 4 + MyStruct1::SIZE)); - size_t id; - bitsery::details::readSize(sctx1.des->adapter(), id, 0, std::false_type{}); - des1.value4b(r2); - EXPECT_THAT(r2, Eq(*pd2)); - bitsery::details::readSize(sctx1.des->adapter(), id, 0, std::false_type{}); - des1.object(r3); - EXPECT_THAT(r3, Eq(*pd3)); +TEST_F(SerializeExtensionPointerSerialization, + PointerOwnerSerializesIdAndObject) +{ + auto& ser1 = createSerializer(); + ser1.ext4b(pd2, PointerOwner{}); + ser1.ext(pd3, PointerOwner{}); + auto& des1 = createDeserializer(); + // 2x ids + int32_t + MyStruct1 + EXPECT_THAT(sctx1.ser->adapter().writtenBytesCount(), + Eq(2 + 4 + MyStruct1::SIZE)); + size_t id; + bitsery::details::readSize(sctx1.des->adapter(), id, 0, std::false_type{}); + des1.value4b(r2); + EXPECT_THAT(r2, Eq(*pd2)); + bitsery::details::readSize(sctx1.des->adapter(), id, 0, std::false_type{}); + des1.object(r3); + EXPECT_THAT(r3, Eq(*pd3)); } -class SerializeExtensionPointerDeserialization : public SerializeExtensionPointerSerialization { +class SerializeExtensionPointerDeserialization + : public SerializeExtensionPointerSerialization +{ public: - }; -TEST_F(SerializeExtensionPointerDeserialization, ReferencedByPointer) { - auto& ser = createSerializer(); - ser.ext2b(d1, ReferencedByPointer{}); - ser.ext4b(d2, ReferencedByPointer{}); - ser.ext(d3, ReferencedByPointer{}); - auto& des = createDeserializer(); - des.ext2b(r1, ReferencedByPointer{}); - des.ext4b(r2, ReferencedByPointer{}); - des.ext(r3, ReferencedByPointer{}); +TEST_F(SerializeExtensionPointerDeserialization, ReferencedByPointer) +{ + auto& ser = createSerializer(); + ser.ext2b(d1, ReferencedByPointer{}); + ser.ext4b(d2, ReferencedByPointer{}); + ser.ext(d3, ReferencedByPointer{}); + auto& des = createDeserializer(); + des.ext2b(r1, ReferencedByPointer{}); + des.ext4b(r2, ReferencedByPointer{}); + des.ext(r3, ReferencedByPointer{}); - EXPECT_THAT(r1, Eq(d1)); - EXPECT_THAT(r2, Eq(d2)); - EXPECT_THAT(r3, Eq(d3)); + EXPECT_THAT(r1, Eq(d1)); + EXPECT_THAT(r2, Eq(d2)); + EXPECT_THAT(r3, Eq(d3)); } -TEST_F(SerializeExtensionPointerDeserialization, WhenReferencedByPointerReadsNullPointerThenInvalidPointerError) { - auto& ser = createSerializer(); - bitsery::details::writeSize(sctx1.ser->adapter(), 0u); - ser.ext2b(d1, ReferencedByPointer{}); - auto& des = createDeserializer(); - des.ext2b(r1, ReferencedByPointer{}); - EXPECT_THAT(sctx1.des->adapter().error(), Eq(bitsery::ReaderError::InvalidPointer)); +TEST_F(SerializeExtensionPointerDeserialization, + WhenReferencedByPointerReadsNullPointerThenInvalidPointerError) +{ + auto& ser = createSerializer(); + bitsery::details::writeSize(sctx1.ser->adapter(), 0u); + ser.ext2b(d1, ReferencedByPointer{}); + auto& des = createDeserializer(); + des.ext2b(r1, ReferencedByPointer{}); + EXPECT_THAT(sctx1.des->adapter().error(), + Eq(bitsery::ReaderError::InvalidPointer)); } -TEST_F(SerializeExtensionPointerDeserialization, WhenNonNullPointerIsNullThenInvalidPointerError) { - createSerializer(); - bitsery::details::writeSize(sctx1.ser->adapter(), 0u); - auto& des1 = createDeserializer(); - des1.ext2b(p1null, PointerOwner{PointerType::NotNull}); - EXPECT_THAT(sctx1.des->adapter().error(), Eq(bitsery::ReaderError::InvalidPointer)); +TEST_F(SerializeExtensionPointerDeserialization, + WhenNonNullPointerIsNullThenInvalidPointerError) +{ + createSerializer(); + bitsery::details::writeSize(sctx1.ser->adapter(), 0u); + auto& des1 = createDeserializer(); + des1.ext2b(p1null, PointerOwner{ PointerType::NotNull }); + EXPECT_THAT(sctx1.des->adapter().error(), + Eq(bitsery::ReaderError::InvalidPointer)); - auto& des2 = createDeserializer(); - des2.ext2b(p1null, PointerObserver{PointerType::NotNull}); - EXPECT_THAT(sctx1.des->adapter().error(), Eq(bitsery::ReaderError::InvalidPointer)); + auto& des2 = createDeserializer(); + des2.ext2b(p1null, PointerObserver{ PointerType::NotNull }); + EXPECT_THAT(sctx1.des->adapter().error(), + Eq(bitsery::ReaderError::InvalidPointer)); } -TEST_F(SerializeExtensionPointerDeserialization, PointerOwnerCreatesObjects) { - auto& ser = createSerializer(); - ser.ext2b(pd1, PointerOwner{}); - ser.ext4b(pd2, PointerOwner{}); - ser.ext(pd3, PointerOwner{}); - auto& des = createDeserializer(); - des.ext2b(p1null, PointerOwner{}); - des.ext4b(p2null, PointerOwner{}); - des.ext(p3null, PointerOwner{}); +TEST_F(SerializeExtensionPointerDeserialization, PointerOwnerCreatesObjects) +{ + auto& ser = createSerializer(); + ser.ext2b(pd1, PointerOwner{}); + ser.ext4b(pd2, PointerOwner{}); + ser.ext(pd3, PointerOwner{}); + auto& des = createDeserializer(); + des.ext2b(p1null, PointerOwner{}); + des.ext4b(p2null, PointerOwner{}); + des.ext(p3null, PointerOwner{}); - EXPECT_THAT(isPointerContextValid(), Eq(true)); - EXPECT_THAT(p1null, ::testing::NotNull()); - EXPECT_THAT(p2null, ::testing::NotNull()); - EXPECT_THAT(p3null, ::testing::NotNull()); - EXPECT_THAT(*p1null, Eq(*pd1)); - EXPECT_THAT(*p2null, Eq(*pd2)); - EXPECT_THAT(*p3null, Eq(*pd3)); + EXPECT_THAT(isPointerContextValid(), Eq(true)); + EXPECT_THAT(p1null, ::testing::NotNull()); + EXPECT_THAT(p2null, ::testing::NotNull()); + EXPECT_THAT(p3null, ::testing::NotNull()); + EXPECT_THAT(*p1null, Eq(*pd1)); + EXPECT_THAT(*p2null, Eq(*pd2)); + EXPECT_THAT(*p3null, Eq(*pd3)); } -TEST_F(SerializeExtensionPointerDeserialization, PointerOwnerDestroysObjects) { - auto& ser = createSerializer(); - ser.ext2b(p1null, PointerOwner{}); - ser.ext4b(p2null, PointerOwner{}); - ser.ext(p3null, PointerOwner{}); - auto& des = createDeserializer(); - //pr cannot link to local variables, need to allocate them separately - pr1 = new int16_t{}; - pr2 = new MyEnumClass{}; - pr3 = new MyStruct1{3, 4}; - des.ext2b(pr1, PointerOwner{}); - des.ext4b(pr2, PointerOwner{}); - des.ext(pr3, PointerOwner{}); +TEST_F(SerializeExtensionPointerDeserialization, PointerOwnerDestroysObjects) +{ + auto& ser = createSerializer(); + ser.ext2b(p1null, PointerOwner{}); + ser.ext4b(p2null, PointerOwner{}); + ser.ext(p3null, PointerOwner{}); + auto& des = createDeserializer(); + // pr cannot link to local variables, need to allocate them separately + pr1 = new int16_t{}; + pr2 = new MyEnumClass{}; + pr3 = new MyStruct1{ 3, 4 }; + des.ext2b(pr1, PointerOwner{}); + des.ext4b(pr2, PointerOwner{}); + des.ext(pr3, PointerOwner{}); - EXPECT_THAT(isPointerContextValid(), Eq(true)); - EXPECT_THAT(pr1, ::testing::IsNull()); - EXPECT_THAT(pr2, ::testing::IsNull()); - EXPECT_THAT(pr3, ::testing::IsNull()); + EXPECT_THAT(isPointerContextValid(), Eq(true)); + EXPECT_THAT(pr1, ::testing::IsNull()); + EXPECT_THAT(pr2, ::testing::IsNull()); + EXPECT_THAT(pr3, ::testing::IsNull()); } -TEST_F(SerializeExtensionPointerDeserialization, PointerObserver) { - auto& ser = createSerializer(); - //first owner, than observer - ser.ext4b(d2, ReferencedByPointer{}); - ser.ext2b(p1null, PointerObserver{}); - ser.ext4b(pd2, PointerObserver{}); - //first observer, than owner - ser.ext(pd3, PointerObserver{}); - ser.ext(pd3, PointerOwner{}); - auto& des = createDeserializer(); - des.ext4b(r2, ReferencedByPointer{}); - des.ext2b(pr1, PointerObserver{}); - des.ext4b(p2null, PointerObserver{}); - des.ext(pr3, PointerObserver{}); - des.ext(pr3, PointerOwner{}); +TEST_F(SerializeExtensionPointerDeserialization, PointerObserver) +{ + auto& ser = createSerializer(); + // first owner, than observer + ser.ext4b(d2, ReferencedByPointer{}); + ser.ext2b(p1null, PointerObserver{}); + ser.ext4b(pd2, PointerObserver{}); + // first observer, than owner + ser.ext(pd3, PointerObserver{}); + ser.ext(pd3, PointerOwner{}); + auto& des = createDeserializer(); + des.ext4b(r2, ReferencedByPointer{}); + des.ext2b(pr1, PointerObserver{}); + des.ext4b(p2null, PointerObserver{}); + des.ext(pr3, PointerObserver{}); + des.ext(pr3, PointerOwner{}); - EXPECT_THAT(isPointerContextValid(), Eq(true)); - //serialize null, override non-null - EXPECT_THAT(pr1, Eq(p1null)); - //serialize non-null, override null - EXPECT_THAT(*p2null, Eq(*pd2)); - EXPECT_THAT(p2null, Eq(&r2)); - //serialize non-null override non-null - EXPECT_THAT(*pr3, Eq(*pd3)); - EXPECT_THAT(pr3, Eq(&r3)); + EXPECT_THAT(isPointerContextValid(), Eq(true)); + // serialize null, override non-null + EXPECT_THAT(pr1, Eq(p1null)); + // serialize non-null, override null + EXPECT_THAT(*p2null, Eq(*pd2)); + EXPECT_THAT(p2null, Eq(&r2)); + // serialize non-null override non-null + EXPECT_THAT(*pr3, Eq(*pd3)); + EXPECT_THAT(pr3, Eq(&r3)); } -struct Test1Data { - std::vector vdata; - std::vector vptr; - MyStruct1 o1; - MyStruct1 *po1; - int32_t i1; - int32_t *pi1; +struct Test1Data +{ + std::vector vdata; + std::vector vptr; + MyStruct1 o1; + MyStruct1* po1; + int32_t i1; + int32_t* pi1; - template - void serialize(S &s) { - //set container elements to be candidates for non-owning pointers - s.container(vdata, 100, [](S& s, MyStruct1 &d) { - s.ext(d, ReferencedByPointer{}); - }); - //contains non owning pointers - // - //IMPORTANT !!! - // ALWAYS ACCEPT BY REFERENCE like this: T* (&obj) - // - s.container(vptr, 100, [](S& s, MyStruct1 *(&d)) { - s.ext(d, PointerObserver{}); - }); - //just a regular fields - s.object(o1); - s.value4b(i1); - //observer - s.ext(po1, PointerObserver{}); - //owner - s.ext4b(pi1, PointerOwner{}); - - } + template + void serialize(S& s) + { + // set container elements to be candidates for non-owning pointers + s.container( + vdata, 100, [](S& s, MyStruct1& d) { s.ext(d, ReferencedByPointer{}); }); + // contains non owning pointers + // + // IMPORTANT !!! + // ALWAYS ACCEPT BY REFERENCE like this: T* (&obj) + // + s.container( + vptr, 100, [](S& s, MyStruct1*(&d)) { s.ext(d, PointerObserver{}); }); + // just a regular fields + s.object(o1); + s.value4b(i1); + // observer + s.ext(po1, PointerObserver{}); + // owner + s.ext4b(pi1, PointerOwner{}); + } }; -TEST(SerializeExtensionPointer, IntegrationTest) { +TEST(SerializeExtensionPointer, IntegrationTest) +{ - Test1Data data{}; - data.vdata.push_back({165, -45}); - data.vdata.push_back({7895, -1576}); - data.vdata.push_back({5987, -798}); - //container of non owning pointers (observers) - data.vptr.push_back(nullptr); - data.vptr.push_back(std::addressof(data.vdata[0])); - data.vptr.push_back(std::addressof(data.vdata[2])); - //regular fields - data.o1 = MyStruct1{145, 948}; - data.i1 = 945415; - //observer - data.po1 = std::addressof(data.vdata[1]); - //owning pointer - data.pi1 = new int32_t{}; + Test1Data data{}; + data.vdata.push_back({ 165, -45 }); + data.vdata.push_back({ 7895, -1576 }); + data.vdata.push_back({ 5987, -798 }); + // container of non owning pointers (observers) + data.vptr.push_back(nullptr); + data.vptr.push_back(std::addressof(data.vdata[0])); + data.vptr.push_back(std::addressof(data.vdata[2])); + // regular fields + data.o1 = MyStruct1{ 145, 948 }; + data.i1 = 945415; + // observer + data.po1 = std::addressof(data.vdata[1]); + // owning pointer + data.pi1 = new int32_t{}; - Test1Data res{}; + Test1Data res{}; - PointerLinkingContext plctx1{}; - SerContext sctx1; - sctx1.createSerializer(plctx1).object(data); - sctx1.createDeserializer(plctx1).object(res); + PointerLinkingContext plctx1{}; + SerContext sctx1; + sctx1.createSerializer(plctx1).object(data); + sctx1.createDeserializer(plctx1).object(res); - EXPECT_THAT(plctx1.isValid(), Eq(true)); - //check regular fields - EXPECT_THAT(res.i1, Eq(data.i1)); - EXPECT_THAT(res.o1, Eq(data.o1)); - //check data container - EXPECT_THAT(res.vdata, ::testing::ContainerEq(data.vdata)); - //check owning pointers - EXPECT_THAT(*res.pi1, Eq(*data.pi1)); - EXPECT_THAT(res.pi1, ::testing::Ne(data.pi1)); - //check if observers points to correct data - EXPECT_THAT(res.po1, Eq(std::addressof(res.vdata[1]))); - EXPECT_THAT(res.vptr[0], ::testing::IsNull()); - EXPECT_THAT(res.vptr[1], Eq(std::addressof(res.vdata[0]))); - EXPECT_THAT(res.vptr[2], Eq(std::addressof(res.vdata[2]))); + EXPECT_THAT(plctx1.isValid(), Eq(true)); + // check regular fields + EXPECT_THAT(res.i1, Eq(data.i1)); + EXPECT_THAT(res.o1, Eq(data.o1)); + // check data container + EXPECT_THAT(res.vdata, ::testing::ContainerEq(data.vdata)); + // check owning pointers + EXPECT_THAT(*res.pi1, Eq(*data.pi1)); + EXPECT_THAT(res.pi1, ::testing::Ne(data.pi1)); + // check if observers points to correct data + EXPECT_THAT(res.po1, Eq(std::addressof(res.vdata[1]))); + EXPECT_THAT(res.vptr[0], ::testing::IsNull()); + EXPECT_THAT(res.vptr[1], Eq(std::addressof(res.vdata[0]))); + EXPECT_THAT(res.vptr[2], Eq(std::addressof(res.vdata[2]))); - //free owning raw pointers - delete data.pi1; - delete res.pi1; + // free owning raw pointers + delete data.pi1; + delete res.pi1; } -TEST(SerializeExtensionPointer, PointerOwnerWithNonPolymorphicTypeCanUseLambdaOverload) { - const int32_t NEW_VALUE = 2; - const int32_t OLD_VALUE = 1; - MyStruct1 *data = new MyStruct1{NEW_VALUE, NEW_VALUE}; - MyStruct1 *res = new MyStruct1{OLD_VALUE, OLD_VALUE}; - //linking context - PointerLinkingContext plctx1{}; - SerContext sctx1; - auto& ser = sctx1.createSerializer(plctx1); - ser.ext(data, PointerOwner{}, [](decltype(ser)& ser, MyStruct1 &o) { - //serialize only one field - ser.value4b(o.i1); - }); - auto& des = sctx1.createDeserializer(plctx1); - des.ext(res, PointerOwner{}, [](decltype(des)& des,MyStruct1 &o) { - //deserialize only one field - des.value4b(o.i1); - }); +TEST(SerializeExtensionPointer, + PointerOwnerWithNonPolymorphicTypeCanUseLambdaOverload) +{ + const int32_t NEW_VALUE = 2; + const int32_t OLD_VALUE = 1; + MyStruct1* data = new MyStruct1{ NEW_VALUE, NEW_VALUE }; + MyStruct1* res = new MyStruct1{ OLD_VALUE, OLD_VALUE }; + // linking context + PointerLinkingContext plctx1{}; + SerContext sctx1; + auto& ser = sctx1.createSerializer(plctx1); + ser.ext(data, PointerOwner{}, [](decltype(ser)& ser, MyStruct1& o) { + // serialize only one field + ser.value4b(o.i1); + }); + auto& des = sctx1.createDeserializer(plctx1); + des.ext(res, PointerOwner{}, [](decltype(des)& des, MyStruct1& o) { + // deserialize only one field + des.value4b(o.i1); + }); - EXPECT_THAT(res->i1, Eq(NEW_VALUE)); - EXPECT_THAT(res->i2, Eq(OLD_VALUE));//we didn't serialized that + EXPECT_THAT(res->i1, Eq(NEW_VALUE)); + EXPECT_THAT(res->i2, Eq(OLD_VALUE)); // we didn't serialized that - delete data; - delete res; + delete data; + delete res; } -TEST(SerializeExtensionPointer, ReferencedByPointerCanUseLambdaOverload) { - const int32_t NEW_VALUE = 2; - const int32_t OLD_VALUE = 1; - MyStruct1 data = MyStruct1{NEW_VALUE, NEW_VALUE}; - MyStruct1 res = MyStruct1{OLD_VALUE, OLD_VALUE}; - //linking context - PointerLinkingContext plctx1{}; - SerContext sctx1; - auto& ser = sctx1.createSerializer(plctx1); - ser.ext(data, ReferencedByPointer{}, [](decltype(ser)& ser,MyStruct1 &o) { - //serialize only one field - ser.value4b(o.i1); - }); - auto& des = sctx1.createDeserializer(plctx1); - des.ext(res, ReferencedByPointer{}, [](decltype(des)& des,MyStruct1 &o) { - //deserialize only one field - des.value4b(o.i1); - }); +TEST(SerializeExtensionPointer, ReferencedByPointerCanUseLambdaOverload) +{ + const int32_t NEW_VALUE = 2; + const int32_t OLD_VALUE = 1; + MyStruct1 data = MyStruct1{ NEW_VALUE, NEW_VALUE }; + MyStruct1 res = MyStruct1{ OLD_VALUE, OLD_VALUE }; + // linking context + PointerLinkingContext plctx1{}; + SerContext sctx1; + auto& ser = sctx1.createSerializer(plctx1); + ser.ext(data, ReferencedByPointer{}, [](decltype(ser)& ser, MyStruct1& o) { + // serialize only one field + ser.value4b(o.i1); + }); + auto& des = sctx1.createDeserializer(plctx1); + des.ext(res, ReferencedByPointer{}, [](decltype(des)& des, MyStruct1& o) { + // deserialize only one field + des.value4b(o.i1); + }); - EXPECT_THAT(res.i1, Eq(NEW_VALUE)); - EXPECT_THAT(res.i2, Eq(OLD_VALUE));//we didn't serialized that + EXPECT_THAT(res.i1, Eq(NEW_VALUE)); + EXPECT_THAT(res.i2, Eq(OLD_VALUE)); // we didn't serialized that } -TEST(SerializeExtensionPointer, PointerOwnerCanUseValueOverload) { - auto *data = new int64_t{49845894}; - auto *res = new int64_t{-78548415}; +TEST(SerializeExtensionPointer, PointerOwnerCanUseValueOverload) +{ + auto* data = new int64_t{ 49845894 }; + auto* res = new int64_t{ -78548415 }; - PointerLinkingContext plctx1{}; - SerContext sctx1; - sctx1.createSerializer(plctx1).ext8b(data, PointerOwner{}); - sctx1.createDeserializer(plctx1).ext8b(res, PointerOwner{}); + PointerLinkingContext plctx1{}; + SerContext sctx1; + sctx1.createSerializer(plctx1).ext8b(data, PointerOwner{}); + sctx1.createDeserializer(plctx1).ext8b(res, PointerOwner{}); - EXPECT_THAT(*res, Eq(*data)); + EXPECT_THAT(*res, Eq(*data)); - delete data; - delete res; + delete data; + delete res; } -TEST(SerializeExtensionPointer, ReferencedByPointerCanUseValueOverload) { - int64_t data{49845894}; - int64_t res{-78548415}; +TEST(SerializeExtensionPointer, ReferencedByPointerCanUseValueOverload) +{ + int64_t data{ 49845894 }; + int64_t res{ -78548415 }; - PointerLinkingContext plctx1{}; - SerContext sctx1; - sctx1.createSerializer(plctx1).ext8b(data, ReferencedByPointer{}); - sctx1.createDeserializer(plctx1).ext8b(res, ReferencedByPointer{}); + PointerLinkingContext plctx1{}; + SerContext sctx1; + sctx1.createSerializer(plctx1).ext8b(data, ReferencedByPointer{}); + sctx1.createDeserializer(plctx1).ext8b(res, ReferencedByPointer{}); - EXPECT_THAT(res, Eq(data)); + EXPECT_THAT(res, Eq(data)); } diff --git a/tests/serialization_ext_pointer_polymorphic_types.cpp b/tests/serialization_ext_pointer_polymorphic_types.cpp index fab730b..b240642 100644 --- a/tests/serialization_ext_pointer_polymorphic_types.cpp +++ b/tests/serialization_ext_pointer_polymorphic_types.cpp @@ -1,31 +1,30 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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 -#include #include "serialization_test_utils.h" +#include using bitsery::ext::BaseClass; using bitsery::ext::VirtualBaseClass; @@ -35,294 +34,342 @@ using bitsery::ext::PointerLinkingContext; using bitsery::ext::PolymorphicContext; using bitsery::ext::StandardRTTI; -using bitsery::ext::PointerOwner; using bitsery::ext::PointerObserver; +using bitsery::ext::PointerOwner; using bitsery::ext::ReferencedByPointer; using testing::Eq; -using TContext = std::tuple>; +using TContext = std::tuple>; using SerContext = BasicSerializationContext; -//this is useful for PolymorphicContext to bind classes to serializer/deserializer +// this is useful for PolymorphicContext to bind classes to +// serializer/deserializer using TSerializer = typename SerContext::TSerializer; using TDeserializer = typename SerContext::TDeserializer; /* * base class */ -struct Base { - uint8_t x{}; +struct Base +{ + uint8_t x{}; - virtual ~Base() = default; + virtual ~Base() = default; }; template -void serialize(S &s, Base &o) { - s.value1b(o.x); +void +serialize(S& s, Base& o) +{ + s.value1b(o.x); } -struct Derived1 : virtual Base { - uint8_t y1{}; +struct Derived1 : virtual Base +{ + uint8_t y1{}; }; template -void serialize(S &s, Derived1 &o) { - s.ext(o, VirtualBaseClass{}); - s.value1b(o.y1); +void +serialize(S& s, Derived1& o) +{ + s.ext(o, VirtualBaseClass{}); + s.value1b(o.y1); } -struct Derived2 : virtual Base { - uint8_t y2{}; +struct Derived2 : virtual Base +{ + uint8_t y2{}; }; template -void serialize(S &s, Derived2 &o) { - s.ext(o, VirtualBaseClass{}); - s.value1b(o.y2); +void +serialize(S& s, Derived2& o) +{ + s.ext(o, VirtualBaseClass{}); + s.value1b(o.y2); } -struct MultipleVirtualInheritance : Derived1, Derived2 { - int8_t z{}; +struct MultipleVirtualInheritance + : Derived1 + , Derived2 +{ + int8_t z{}; - MultipleVirtualInheritance() = default; + MultipleVirtualInheritance() = default; - MultipleVirtualInheritance(uint8_t x_, uint8_t y1_, uint8_t y2_, int8_t z_) { - x = x_; - y1 = y1_; - y2 = y2_; - z = z_; - } - - template - void serialize(S &s) { - s.ext(*this, BaseClass{}); - s.ext(*this, BaseClass{}); - s.value1b(z); - } + MultipleVirtualInheritance(uint8_t x_, uint8_t y1_, uint8_t y2_, int8_t z_) + { + x = x_; + y1 = y1_; + y2 = y2_; + z = z_; + } + template + void serialize(S& s) + { + s.ext(*this, BaseClass{}); + s.ext(*this, BaseClass{}); + s.value1b(z); + } }; -//this class has no relationships specified via PolymorphicBaseClass -struct NoRelationshipSpecifiedDerived : Base { -}; +// this class has no relationships specified via PolymorphicBaseClass +struct NoRelationshipSpecifiedDerived : Base +{}; -//these classes will be used to "cheat" a little bit when testing deserialization flows -struct BaseClone { - uint8_t x{}; +// these classes will be used to "cheat" a little bit when testing +// deserialization flows +struct BaseClone +{ + uint8_t x{}; - virtual ~BaseClone() = default; + virtual ~BaseClone() = default; }; template -void serialize(S &s, BaseClone &o) { - s.value1b(o.x); +void +serialize(S& s, BaseClone& o) +{ + s.value1b(o.x); } -//define relationships between base class and derived classes for runtime polymorphism +// define relationships between base class and derived classes for runtime +// polymorphism namespace bitsery { - namespace ext { +namespace ext { - template<> - struct PolymorphicBaseClass : PolymorphicDerivedClasses { - }; - - // this is commented on purpose, to test scenario when base class is registered (Base) - // but using instance of Derived1 which is not registered as base -// template<> -// struct PolymorphicBaseClass : PolymorphicDerivedClasses { -// }; - - template<> - struct PolymorphicBaseClass : PolymorphicDerivedClasses { - }; - - } -} - - -class SerializeExtensionPointerPolymorphicTypes : public testing::Test { -public: - - TContext plctx{}; - SerContext sctx{}; - - typename SerContext::TSerializer& createSerializer() { - auto& res = sctx.createSerializer(plctx); - std::get<2>(plctx).clear(); - //bind serializer with classes - std::get<2>(plctx).registerBasesList(bitsery::ext::PolymorphicClassesList{}); - return res; - } - - typename SerContext::TDeserializer& createDeserializer() { - auto& res = sctx.createDeserializer(plctx); - std::get<2>(plctx).clear(); - //bind deserializer with classes - std::get<2>(plctx).registerBasesList(bitsery::ext::PolymorphicClassesList{}); - return res; - } - - bool isPointerContextValid() { - return std::get<0>(plctx).isValid(); - } - - virtual void TearDown() override { - EXPECT_TRUE(isPointerContextValid()); - } +template<> +struct PolymorphicBaseClass + : PolymorphicDerivedClasses +{ }; -TEST_F(SerializeExtensionPointerPolymorphicTypes, Data0Result0) { - Base *baseData = nullptr; - createSerializer().ext(baseData, PointerOwner{}); - Base *baseRes = nullptr; - createDeserializer().ext(baseRes, PointerOwner{}); +// this is commented on purpose, to test scenario when base class is registered +// (Base) but using instance of Derived1 which is not registered as base +// template<> +// struct PolymorphicBaseClass : +// PolymorphicDerivedClasses { +// }; - EXPECT_THAT(baseRes, ::testing::IsNull()); - EXPECT_THAT(baseData, ::testing::IsNull()); +template<> +struct PolymorphicBaseClass + : PolymorphicDerivedClasses +{ +}; + +} } -TEST_F(SerializeExtensionPointerPolymorphicTypes, Data0Result1) { - Base *baseData = nullptr; - createSerializer().ext(baseData, PointerOwner{}); +class SerializeExtensionPointerPolymorphicTypes : public testing::Test +{ +public: + TContext plctx{}; + SerContext sctx{}; - Base *baseRes = new Derived1{}; - createDeserializer().ext(baseRes, PointerOwner{}); + typename SerContext::TSerializer& createSerializer() + { + auto& res = sctx.createSerializer(plctx); + std::get<2>(plctx).clear(); + // bind serializer with classes + std::get<2>(plctx).registerBasesList( + bitsery::ext::PolymorphicClassesList{}); + return res; + } - EXPECT_THAT(baseRes, ::testing::IsNull()); - EXPECT_THAT(baseData, ::testing::IsNull()); + typename SerContext::TDeserializer& createDeserializer() + { + auto& res = sctx.createDeserializer(plctx); + std::get<2>(plctx).clear(); + // bind deserializer with classes + std::get<2>(plctx).registerBasesList( + bitsery::ext::PolymorphicClassesList{}); + return res; + } + + bool isPointerContextValid() { return std::get<0>(plctx).isValid(); } + + virtual void TearDown() override { EXPECT_TRUE(isPointerContextValid()); } +}; + +TEST_F(SerializeExtensionPointerPolymorphicTypes, Data0Result0) +{ + Base* baseData = nullptr; + createSerializer().ext(baseData, PointerOwner{}); + Base* baseRes = nullptr; + createDeserializer().ext(baseRes, PointerOwner{}); + + EXPECT_THAT(baseRes, ::testing::IsNull()); + EXPECT_THAT(baseData, ::testing::IsNull()); } -TEST_F(SerializeExtensionPointerPolymorphicTypes, Data1Result0) { - Derived1 d1{}; - d1.x = 3; - d1.y1 = 78; - Base *baseData = &d1; - createSerializer().ext(baseData, PointerOwner{}); - Base *baseRes = nullptr; - createDeserializer().ext(baseRes, PointerOwner{}); +TEST_F(SerializeExtensionPointerPolymorphicTypes, Data0Result1) +{ + Base* baseData = nullptr; + createSerializer().ext(baseData, PointerOwner{}); - auto *data = dynamic_cast(baseData); - auto *res = dynamic_cast(baseRes); + Base* baseRes = new Derived1{}; + createDeserializer().ext(baseRes, PointerOwner{}); - EXPECT_THAT(baseRes, ::testing::NotNull()); - EXPECT_THAT(data, ::testing::NotNull()); - EXPECT_THAT(res, ::testing::NotNull()); - EXPECT_THAT(res->x, Eq(data->x)); - EXPECT_THAT(res->y1, Eq(data->y1)); - delete baseRes; + EXPECT_THAT(baseRes, ::testing::IsNull()); + EXPECT_THAT(baseData, ::testing::IsNull()); } -TEST_F(SerializeExtensionPointerPolymorphicTypes, Data1Result1) { - Derived1 d1{}; - d1.x = 3; - d1.y1 = 78; - Base *baseData = &d1; - createSerializer().ext(baseData, PointerOwner{}); - Base *baseRes = &d1; - createDeserializer().ext(baseRes, PointerOwner{}); +TEST_F(SerializeExtensionPointerPolymorphicTypes, Data1Result0) +{ + Derived1 d1{}; + d1.x = 3; + d1.y1 = 78; + Base* baseData = &d1; + createSerializer().ext(baseData, PointerOwner{}); + Base* baseRes = nullptr; + createDeserializer().ext(baseRes, PointerOwner{}); - auto *data = dynamic_cast(baseData); - auto *res = dynamic_cast(baseRes); + auto* data = dynamic_cast(baseData); + auto* res = dynamic_cast(baseRes); - EXPECT_THAT(baseRes, ::testing::NotNull()); - EXPECT_THAT(data, ::testing::NotNull()); - EXPECT_THAT(res, ::testing::NotNull()); - EXPECT_THAT(res->x, Eq(data->x)); - EXPECT_THAT(res->y1, Eq(data->y1)); + EXPECT_THAT(baseRes, ::testing::NotNull()); + EXPECT_THAT(data, ::testing::NotNull()); + EXPECT_THAT(res, ::testing::NotNull()); + EXPECT_THAT(res->x, Eq(data->x)); + EXPECT_THAT(res->y1, Eq(data->y1)); + delete baseRes; } -TEST_F(SerializeExtensionPointerPolymorphicTypes, ComplexTypeWithVirtualInheritanceData1Result0) { - MultipleVirtualInheritance md1{}; - md1.x = 3; - md1.y1 = 78; - md1.y2 = 14; - md1.z = -33; - Base *baseData = &md1; - createSerializer().ext(baseData, PointerOwner{}); - Base *baseRes = nullptr; - createDeserializer().ext(baseRes, PointerOwner{}); +TEST_F(SerializeExtensionPointerPolymorphicTypes, Data1Result1) +{ + Derived1 d1{}; + d1.x = 3; + d1.y1 = 78; + Base* baseData = &d1; + createSerializer().ext(baseData, PointerOwner{}); + Base* baseRes = &d1; + createDeserializer().ext(baseRes, PointerOwner{}); - auto *data = dynamic_cast(baseData); - auto *res = dynamic_cast(baseRes); + auto* data = dynamic_cast(baseData); + auto* res = dynamic_cast(baseRes); - EXPECT_THAT(baseRes, ::testing::NotNull()); - EXPECT_THAT(data, ::testing::NotNull()); - EXPECT_THAT(res, ::testing::NotNull()); - EXPECT_THAT(res->x, Eq(data->x)); - EXPECT_THAT(res->y1, Eq(data->y1)); - EXPECT_THAT(res->y2, Eq(data->y2)); - EXPECT_THAT(res->z, Eq(data->z)); - delete baseRes; + EXPECT_THAT(baseRes, ::testing::NotNull()); + EXPECT_THAT(data, ::testing::NotNull()); + EXPECT_THAT(res, ::testing::NotNull()); + EXPECT_THAT(res->x, Eq(data->x)); + EXPECT_THAT(res->y1, Eq(data->y1)); } -TEST_F(SerializeExtensionPointerPolymorphicTypes, WhenResultIsDifferentTypeThenRecreate) { - MultipleVirtualInheritance md1{}; - md1.x = 3; - md1.y1 = 78; - md1.y2 = 14; - md1.z = -33; - Base *baseData = &md1; - createSerializer().ext(baseData, PointerOwner{}); - Base *baseRes = new Derived1{}; - EXPECT_THAT(dynamic_cast(baseRes), ::testing::IsNull()); - createDeserializer().ext(baseRes, PointerOwner{}); - EXPECT_THAT(dynamic_cast(baseRes), ::testing::NotNull()); - delete baseRes; +TEST_F(SerializeExtensionPointerPolymorphicTypes, + ComplexTypeWithVirtualInheritanceData1Result0) +{ + MultipleVirtualInheritance md1{}; + md1.x = 3; + md1.y1 = 78; + md1.y2 = 14; + md1.z = -33; + Base* baseData = &md1; + createSerializer().ext(baseData, PointerOwner{}); + Base* baseRes = nullptr; + createDeserializer().ext(baseRes, PointerOwner{}); + + auto* data = dynamic_cast(baseData); + auto* res = dynamic_cast(baseRes); + + EXPECT_THAT(baseRes, ::testing::NotNull()); + EXPECT_THAT(data, ::testing::NotNull()); + EXPECT_THAT(res, ::testing::NotNull()); + EXPECT_THAT(res->x, Eq(data->x)); + EXPECT_THAT(res->y1, Eq(data->y1)); + EXPECT_THAT(res->y2, Eq(data->y2)); + EXPECT_THAT(res->z, Eq(data->z)); + delete baseRes; +} + +TEST_F(SerializeExtensionPointerPolymorphicTypes, + WhenResultIsDifferentTypeThenRecreate) +{ + MultipleVirtualInheritance md1{}; + md1.x = 3; + md1.y1 = 78; + md1.y2 = 14; + md1.z = -33; + Base* baseData = &md1; + createSerializer().ext(baseData, PointerOwner{}); + Base* baseRes = new Derived1{}; + EXPECT_THAT(dynamic_cast(baseRes), + ::testing::IsNull()); + createDeserializer().ext(baseRes, PointerOwner{}); + EXPECT_THAT(dynamic_cast(baseRes), + ::testing::NotNull()); + delete baseRes; } #ifndef NDEBUG -TEST_F(SerializeExtensionPointerPolymorphicTypes, - WhenSerializingDerivedTypeWithoutSpecifiedRelationshipsWithBaseThenAssert) { +TEST_F( + SerializeExtensionPointerPolymorphicTypes, + WhenSerializingDerivedTypeWithoutSpecifiedRelationshipsWithBaseThenAssert) +{ - NoRelationshipSpecifiedDerived md1;//this class has no relationships specified via PolymorphicBaseClass - Base *baseData = &md1; - EXPECT_DEATH(createSerializer().ext(baseData, PointerOwner{}), ""); + NoRelationshipSpecifiedDerived + md1; // this class has no relationships specified via PolymorphicBaseClass + Base* baseData = &md1; + EXPECT_DEATH(createSerializer().ext(baseData, PointerOwner{}), ""); } -TEST_F(SerializeExtensionPointerPolymorphicTypes, - WhenDeserializingDerivedTypeNotRegisteredWithPolymorphicContextThenAssert) { +TEST_F( + SerializeExtensionPointerPolymorphicTypes, + WhenDeserializingDerivedTypeNotRegisteredWithPolymorphicContextThenAssert) +{ - Derived1 d1{}; - Base *baseData = &d1; - createSerializer().ext(baseData, PointerOwner{}); + Derived1 d1{}; + Base* baseData = &d1; + createSerializer().ext(baseData, PointerOwner{}); - BaseClone *baseRes = nullptr; //this class is not registered - EXPECT_DEATH(createDeserializer().ext(baseRes, PointerOwner{}), ""); + BaseClone* baseRes = nullptr; // this class is not registered + EXPECT_DEATH(createDeserializer().ext(baseRes, PointerOwner{}), ""); } #endif -TEST_F(SerializeExtensionPointerPolymorphicTypes, - CompileTimeTypeIsDerivedAndReachableFromBaseRegisteredWithPolymorphicContext) { +TEST_F( + SerializeExtensionPointerPolymorphicTypes, + CompileTimeTypeIsDerivedAndReachableFromBaseRegisteredWithPolymorphicContext) +{ - MultipleVirtualInheritance md; - Derived2 *derivedData = &md;//this class is not registered via PolymorphicContext - - createSerializer().ext(derivedData, PointerOwner{}); - Derived2 *derivedRes = new Derived2{}; - EXPECT_THAT(dynamic_cast(derivedRes), ::testing::IsNull()); - createDeserializer().ext(derivedRes, PointerOwner{}); - EXPECT_THAT(dynamic_cast(derivedRes), ::testing::NotNull()); - delete derivedRes; + MultipleVirtualInheritance md; + Derived2* derivedData = + &md; // this class is not registered via PolymorphicContext + createSerializer().ext(derivedData, PointerOwner{}); + Derived2* derivedRes = new Derived2{}; + EXPECT_THAT(dynamic_cast(derivedRes), + ::testing::IsNull()); + createDeserializer().ext(derivedRes, PointerOwner{}); + EXPECT_THAT(dynamic_cast(derivedRes), + ::testing::NotNull()); + delete derivedRes; } - TEST_F(SerializeExtensionPointerPolymorphicTypes, - WhenPolymorphicTypeNotFoundDuringDeserializionThenInvalidPointerError) { + WhenPolymorphicTypeNotFoundDuringDeserializionThenInvalidPointerError) +{ - Derived1 d1{}; - Base *baseData = &d1; - createSerializer().ext(baseData, PointerOwner{}); + Derived1 d1{}; + Base* baseData = &d1; + createSerializer().ext(baseData, PointerOwner{}); - BaseClone *baseRes = nullptr; //this class will be registered, but it doesn't have relationships specified via PolymorphicBaseClass - auto& des = sctx.createDeserializer(plctx); - auto &pc = std::get<2>(plctx); - pc.clear(); - pc.registerBasesList(bitsery::ext::PolymorphicClassesList{}); - des.ext(baseRes, PointerOwner{}); - EXPECT_THAT(sctx.des->adapter().error(), Eq(bitsery::ReaderError::InvalidPointer)); + BaseClone* baseRes = + nullptr; // this class will be registered, but it doesn't have relationships + // specified via PolymorphicBaseClass + auto& des = sctx.createDeserializer(plctx); + auto& pc = std::get<2>(plctx); + pc.clear(); + pc.registerBasesList( + bitsery::ext::PolymorphicClassesList{}); + des.ext(baseRes, PointerOwner{}); + EXPECT_THAT(sctx.des->adapter().error(), + Eq(bitsery::ReaderError::InvalidPointer)); } diff --git a/tests/serialization_ext_pointer_with_allocator.cpp b/tests/serialization_ext_pointer_with_allocator.cpp index 8e36fc7..929cd4c 100644 --- a/tests/serialization_ext_pointer_with_allocator.cpp +++ b/tests/serialization_ext_pointer_with_allocator.cpp @@ -1,32 +1,31 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. - +// 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 #include -#include #include "serialization_test_utils.h" +#include using bitsery::ext::BaseClass; using bitsery::ext::VirtualBaseClass; @@ -36,332 +35,396 @@ using bitsery::ext::PointerLinkingContext; using bitsery::ext::PolymorphicContext; using bitsery::ext::StandardRTTI; -using bitsery::ext::PointerOwner; using bitsery::ext::PointerObserver; +using bitsery::ext::PointerOwner; using bitsery::ext::ReferencedByPointer; using bitsery::ext::StdSmartPtr; using testing::Eq; -using TContext = std::tuple>; +using TContext = std::tuple>; using SerContext = BasicSerializationContext; -//this is useful for PolymorphicContext to bind classes to serializer/deserializer +// this is useful for PolymorphicContext to bind classes to +// serializer/deserializer using TSerializer = typename SerContext::TSerializer; using TDeserializer = typename SerContext::TDeserializer; /* * base class */ -struct Base { - Base() = default; +struct Base +{ + Base() = default; - explicit Base(uint64_t v) : x{v} {} + explicit Base(uint64_t v) + : x{ v } + { + } - uint64_t x{}; + uint64_t x{}; - virtual ~Base() = default; + virtual ~Base() = default; }; template -void serialize(S& s, Base& o) { - s.value8b(o.x); +void +serialize(S& s, Base& o) +{ + s.value8b(o.x); } -struct Derived1 : Base { - Derived1() = default; +struct Derived1 : Base +{ + Derived1() = default; - Derived1(uint64_t x_, uint64_t y_) : Base{x_}, y1{y_} {} + Derived1(uint64_t x_, uint64_t y_) + : Base{ x_ } + , y1{ y_ } + { + } - friend bool operator==(const Derived1& lhs, const Derived1& rhs) { - return lhs.x == rhs.x && lhs.y1 == rhs.y1; - } + friend bool operator==(const Derived1& lhs, const Derived1& rhs) + { + return lhs.x == rhs.x && lhs.y1 == rhs.y1; + } - uint64_t y1{}; + uint64_t y1{}; }; template -void serialize(S& s, Derived1& o) { - s.ext(o, BaseClass{}); - s.value8b(o.y1); +void +serialize(S& s, Derived1& o) +{ + s.ext(o, BaseClass{}); + s.value8b(o.y1); } -struct Derived2 : Base { - uint64_t y1{}; - uint64_t y2{}; +struct Derived2 : Base +{ + uint64_t y1{}; + uint64_t y2{}; }; template -void serialize(S& s, Derived2& o) { - s.ext(o, BaseClass{}); - s.value8b(o.y1); - s.value8b(o.y2); +void +serialize(S& s, Derived2& o) +{ + s.ext(o, BaseClass{}); + s.value8b(o.y1); + s.value8b(o.y2); } -// polymorphic structure that contains polymorphic pointer, to test memory resource propagation -struct PolyPtrWithPolyPtrBase { - std::unique_ptr ptr{}; +// polymorphic structure that contains polymorphic pointer, to test memory +// resource propagation +struct PolyPtrWithPolyPtrBase +{ + std::unique_ptr ptr{}; - virtual ~PolyPtrWithPolyPtrBase() = default; + virtual ~PolyPtrWithPolyPtrBase() = default; }; template -void serialize(S& s, PolyPtrWithPolyPtrBase& o) { - s.ext(o.ptr, StdSmartPtr{}); +void +serialize(S& s, PolyPtrWithPolyPtrBase& o) +{ + s.ext(o.ptr, StdSmartPtr{}); } -struct DerivedPolyPtrWithPolyPtr : PolyPtrWithPolyPtrBase { - -}; +struct DerivedPolyPtrWithPolyPtr : PolyPtrWithPolyPtrBase +{}; template -void serialize(S& s, DerivedPolyPtrWithPolyPtr& o) { - s.ext(o.ptr, StdSmartPtr{}); +void +serialize(S& s, DerivedPolyPtrWithPolyPtr& o) +{ + s.ext(o.ptr, StdSmartPtr{}); } - -//define relationships between base class and derived classes for runtime polymorphism +// define relationships between base class and derived classes for runtime +// polymorphism namespace bitsery { - namespace ext { +namespace ext { - template<> - struct PolymorphicBaseClass : PolymorphicDerivedClasses { - }; +template<> +struct PolymorphicBaseClass + : PolymorphicDerivedClasses +{ +}; - template<> - struct PolymorphicBaseClass : PolymorphicDerivedClasses { - }; +template<> +struct PolymorphicBaseClass + : PolymorphicDerivedClasses +{ +}; - } +} } // this class is for testing -struct TestAllocInfo { - void* ptr; - size_t bytes; - size_t alignment; - size_t typeId; +struct TestAllocInfo +{ + void* ptr; + size_t bytes; + size_t alignment; + size_t typeId; - friend bool operator==(const TestAllocInfo& lhs, const TestAllocInfo& rhs) { - return std::tie(lhs.ptr, lhs.bytes, lhs.alignment, lhs.typeId) == - std::tie(rhs.ptr, rhs.bytes, rhs.alignment, rhs.typeId); - } + friend bool operator==(const TestAllocInfo& lhs, const TestAllocInfo& rhs) + { + return std::tie(lhs.ptr, lhs.bytes, lhs.alignment, lhs.typeId) == + std::tie(rhs.ptr, rhs.bytes, rhs.alignment, rhs.typeId); + } }; -struct MemResourceForTest : public bitsery::ext::MemResourceBase { +struct MemResourceForTest : public bitsery::ext::MemResourceBase +{ - void* allocate(size_t bytes, size_t alignment, size_t typeId) override { - const auto res = bitsery::ext::MemResourceNewDelete{}.allocate(bytes, alignment, typeId); - allocs.push_back({res, bytes, alignment, typeId}); - return res; - } + void* allocate(size_t bytes, size_t alignment, size_t typeId) override + { + const auto res = + bitsery::ext::MemResourceNewDelete{}.allocate(bytes, alignment, typeId); + allocs.push_back({ res, bytes, alignment, typeId }); + return res; + } - void deallocate(void* ptr, size_t bytes, size_t alignment, size_t typeId) noexcept override { - deallocs.push_back({ptr, bytes, alignment, typeId}); - bitsery::ext::MemResourceNewDelete{}.deallocate(ptr, bytes, alignment, typeId); - } + void deallocate(void* ptr, + size_t bytes, + size_t alignment, + size_t typeId) noexcept override + { + deallocs.push_back({ ptr, bytes, alignment, typeId }); + bitsery::ext::MemResourceNewDelete{}.deallocate( + ptr, bytes, alignment, typeId); + } - std::vector allocs{}; - std::vector deallocs{}; + std::vector allocs{}; + std::vector deallocs{}; }; -class SerializeExtensionPointerWithAllocator : public testing::Test { +class SerializeExtensionPointerWithAllocator : public testing::Test +{ public: + TContext plctx{}; + SerContext sctx{}; - TContext plctx{}; - SerContext sctx{}; + typename SerContext::TSerializer& createSerializer() + { + auto& res = sctx.createSerializer(plctx); + std::get<2>(plctx).clear(); + // bind serializer with classes + std::get<2>(plctx).registerBasesList( + bitsery::ext::PolymorphicClassesList{}); + return res; + } - typename SerContext::TSerializer& createSerializer() { - auto& res = sctx.createSerializer(plctx); - std::get<2>(plctx).clear(); - //bind serializer with classes - std::get<2>(plctx).registerBasesList( - bitsery::ext::PolymorphicClassesList{}); - return res; - } + typename SerContext::TDeserializer& createDeserializer() + { + auto& res = sctx.createDeserializer(plctx); + std::get<2>(plctx).clear(); + // bind deserializer with classes + std::get<2>(plctx).registerBasesList( + bitsery::ext::PolymorphicClassesList{}); + return res; + } - typename SerContext::TDeserializer& createDeserializer() { - auto& res = sctx.createDeserializer(plctx); - std::get<2>(plctx).clear(); - //bind deserializer with classes - std::get<2>(plctx).registerBasesList( - bitsery::ext::PolymorphicClassesList{}); - return res; - } + bool isPointerContextValid() { return std::get<0>(plctx).isValid(); } - bool isPointerContextValid() { - return std::get<0>(plctx).isValid(); - } - - virtual void TearDown() override { - EXPECT_TRUE(isPointerContextValid()); - } + virtual void TearDown() override { EXPECT_TRUE(isPointerContextValid()); } }; -TEST_F(SerializeExtensionPointerWithAllocator, CanSetDefaultMemoryResourceInPointerLinkingContext) { +TEST_F(SerializeExtensionPointerWithAllocator, + CanSetDefaultMemoryResourceInPointerLinkingContext) +{ - MemResourceForTest memRes{}; - std::get<0>(plctx).setMemResource(&memRes); + MemResourceForTest memRes{}; + std::get<0>(plctx).setMemResource(&memRes); - Base* baseData = new Derived1{2, 1}; - createSerializer().ext(baseData, PointerOwner{}); - Base* baseRes = nullptr; - createDeserializer().ext(baseRes, PointerOwner{}); + Base* baseData = new Derived1{ 2, 1 }; + createSerializer().ext(baseData, PointerOwner{}); + Base* baseRes = nullptr; + createDeserializer().ext(baseRes, PointerOwner{}); - auto dData = dynamic_cast(baseData); - auto dRes = dynamic_cast(baseRes); + auto dData = dynamic_cast(baseData); + auto dRes = dynamic_cast(baseRes); - EXPECT_THAT(dRes, ::testing::NotNull()); - EXPECT_THAT(*dData, *dRes); - EXPECT_THAT(memRes.allocs.size(), Eq(1u)); - EXPECT_THAT(memRes.allocs[0].bytes, Eq(sizeof(Derived1))); - EXPECT_THAT(memRes.allocs[0].alignment, Eq(alignof(Derived1))); - EXPECT_THAT(memRes.allocs[0].typeId, Eq(bitsery::ext::StandardRTTI::get())); - EXPECT_THAT(memRes.deallocs.size(), Eq(0u)); - delete dData; - delete dRes; + EXPECT_THAT(dRes, ::testing::NotNull()); + EXPECT_THAT(*dData, *dRes); + EXPECT_THAT(memRes.allocs.size(), Eq(1u)); + EXPECT_THAT(memRes.allocs[0].bytes, Eq(sizeof(Derived1))); + EXPECT_THAT(memRes.allocs[0].alignment, Eq(alignof(Derived1))); + EXPECT_THAT(memRes.allocs[0].typeId, + Eq(bitsery::ext::StandardRTTI::get())); + EXPECT_THAT(memRes.deallocs.size(), Eq(0u)); + delete dData; + delete dRes; } -TEST_F(SerializeExtensionPointerWithAllocator, CorrectlyDeallocatesPreviousInstance) { - MemResourceForTest memRes{}; - std::get<0>(plctx).setMemResource(&memRes); +TEST_F(SerializeExtensionPointerWithAllocator, + CorrectlyDeallocatesPreviousInstance) +{ + MemResourceForTest memRes{}; + std::get<0>(plctx).setMemResource(&memRes); - Base* baseData = new Derived1{2, 1}; - createSerializer().ext(baseData, PointerOwner{}); - Base* baseRes = new Derived2; - createDeserializer().ext(baseRes, PointerOwner{}); + Base* baseData = new Derived1{ 2, 1 }; + createSerializer().ext(baseData, PointerOwner{}); + Base* baseRes = new Derived2; + createDeserializer().ext(baseRes, PointerOwner{}); - auto dData = dynamic_cast(baseData); - auto dRes = dynamic_cast(baseRes); + auto dData = dynamic_cast(baseData); + auto dRes = dynamic_cast(baseRes); - EXPECT_THAT(dRes, ::testing::NotNull()); - EXPECT_THAT(*dData, *dRes); - EXPECT_THAT(memRes.allocs.size(), Eq(1u)); - EXPECT_THAT(memRes.allocs[0].bytes, Eq(sizeof(Derived1))); - EXPECT_THAT(memRes.allocs[0].alignment, Eq(alignof(Derived1))); - EXPECT_THAT(memRes.allocs[0].typeId, Eq(bitsery::ext::StandardRTTI::get())); - EXPECT_THAT(memRes.deallocs.size(), Eq(1u)); - EXPECT_THAT(memRes.deallocs[0].bytes, Eq(sizeof(Derived2))); - EXPECT_THAT(memRes.deallocs[0].alignment, Eq(alignof(Derived2))); - EXPECT_THAT(memRes.deallocs[0].typeId, Eq(bitsery::ext::StandardRTTI::get())); + EXPECT_THAT(dRes, ::testing::NotNull()); + EXPECT_THAT(*dData, *dRes); + EXPECT_THAT(memRes.allocs.size(), Eq(1u)); + EXPECT_THAT(memRes.allocs[0].bytes, Eq(sizeof(Derived1))); + EXPECT_THAT(memRes.allocs[0].alignment, Eq(alignof(Derived1))); + EXPECT_THAT(memRes.allocs[0].typeId, + Eq(bitsery::ext::StandardRTTI::get())); + EXPECT_THAT(memRes.deallocs.size(), Eq(1u)); + EXPECT_THAT(memRes.deallocs[0].bytes, Eq(sizeof(Derived2))); + EXPECT_THAT(memRes.deallocs[0].alignment, Eq(alignof(Derived2))); + EXPECT_THAT(memRes.deallocs[0].typeId, + Eq(bitsery::ext::StandardRTTI::get())); - delete dData; - delete dRes; + delete dData; + delete dRes; } -TEST_F(SerializeExtensionPointerWithAllocator, DefaultDeleterIsNotUsedForStdUniquePtr) { - MemResourceForTest memRes{}; - std::get<0>(plctx).setMemResource(&memRes); +TEST_F(SerializeExtensionPointerWithAllocator, + DefaultDeleterIsNotUsedForStdUniquePtr) +{ + MemResourceForTest memRes{}; + std::get<0>(plctx).setMemResource(&memRes); - std::unique_ptr baseData{}; - createSerializer().ext(baseData, StdSmartPtr{}); - auto baseRes = std::unique_ptr(new Derived1{45, 64}); - createDeserializer().ext(baseRes, StdSmartPtr{}); + std::unique_ptr baseData{}; + createSerializer().ext(baseData, StdSmartPtr{}); + auto baseRes = std::unique_ptr(new Derived1{ 45, 64 }); + createDeserializer().ext(baseRes, StdSmartPtr{}); - EXPECT_THAT(memRes.allocs.size(), Eq(0u)); - EXPECT_THAT(memRes.deallocs.size(), Eq(1u)); - EXPECT_THAT(memRes.deallocs[0].bytes, Eq(sizeof(Derived1))); - EXPECT_THAT(memRes.deallocs[0].alignment, Eq(alignof(Derived1))); - EXPECT_THAT(memRes.deallocs[0].typeId, Eq(bitsery::ext::StandardRTTI::get())); + EXPECT_THAT(memRes.allocs.size(), Eq(0u)); + EXPECT_THAT(memRes.deallocs.size(), Eq(1u)); + EXPECT_THAT(memRes.deallocs[0].bytes, Eq(sizeof(Derived1))); + EXPECT_THAT(memRes.deallocs[0].alignment, Eq(alignof(Derived1))); + EXPECT_THAT(memRes.deallocs[0].typeId, + Eq(bitsery::ext::StandardRTTI::get())); } -struct CustomBaseDeleter { - void operator()(Base* obj) { - delete obj; - } +struct CustomBaseDeleter +{ + void operator()(Base* obj) { delete obj; } }; -TEST_F(SerializeExtensionPointerWithAllocator, CustomDeleterIsNotUsedForStdUniquePtr) { - MemResourceForTest memRes{}; - std::get<0>(plctx).setMemResource(&memRes); +TEST_F(SerializeExtensionPointerWithAllocator, + CustomDeleterIsNotUsedForStdUniquePtr) +{ + MemResourceForTest memRes{}; + std::get<0>(plctx).setMemResource(&memRes); - std::unique_ptr baseData{}; - createSerializer().ext(baseData, StdSmartPtr{}); - auto baseRes = std::unique_ptr(new Derived1{45, 64}); - createDeserializer().ext(baseRes, StdSmartPtr{}); + std::unique_ptr baseData{}; + createSerializer().ext(baseData, StdSmartPtr{}); + auto baseRes = + std::unique_ptr(new Derived1{ 45, 64 }); + createDeserializer().ext(baseRes, StdSmartPtr{}); - EXPECT_THAT(memRes.allocs.size(), Eq(0u)); - EXPECT_THAT(memRes.deallocs.size(), Eq(1u)); - EXPECT_THAT(memRes.deallocs[0].bytes, Eq(sizeof(Derived1))); - EXPECT_THAT(memRes.deallocs[0].alignment, Eq(alignof(Derived1))); - EXPECT_THAT(memRes.deallocs[0].typeId, Eq(bitsery::ext::StandardRTTI::get())); + EXPECT_THAT(memRes.allocs.size(), Eq(0u)); + EXPECT_THAT(memRes.deallocs.size(), Eq(1u)); + EXPECT_THAT(memRes.deallocs[0].bytes, Eq(sizeof(Derived1))); + EXPECT_THAT(memRes.deallocs[0].alignment, Eq(alignof(Derived1))); + EXPECT_THAT(memRes.deallocs[0].typeId, + Eq(bitsery::ext::StandardRTTI::get())); } +TEST_F(SerializeExtensionPointerWithAllocator, CanSetMemResourcePerPointer) +{ + MemResourceForTest memRes1{}; + MemResourceForTest memRes2{}; + std::get<0>(plctx).setMemResource(&memRes1); -TEST_F(SerializeExtensionPointerWithAllocator, CanSetMemResourcePerPointer) { - MemResourceForTest memRes1{}; - MemResourceForTest memRes2{}; - std::get<0>(plctx).setMemResource(&memRes1); + Base* baseData = new Derived1{ 2, 1 }; + createSerializer().ext( + baseData, PointerOwner{ bitsery::ext::PointerType::Nullable, &memRes2 }); + Base* baseRes = new Derived2; + createDeserializer().ext( + baseRes, PointerOwner{ bitsery::ext::PointerType::Nullable, &memRes2 }); - Base* baseData = new Derived1{2, 1}; - createSerializer().ext(baseData, PointerOwner{bitsery::ext::PointerType::Nullable, &memRes2}); - Base* baseRes = new Derived2; - createDeserializer().ext(baseRes, PointerOwner{bitsery::ext::PointerType::Nullable, &memRes2}); + auto dData = dynamic_cast(baseData); + auto dRes = dynamic_cast(baseRes); - auto dData = dynamic_cast(baseData); - auto dRes = dynamic_cast(baseRes); + EXPECT_THAT(dRes, ::testing::NotNull()); + EXPECT_THAT(*dData, *dRes); + EXPECT_THAT(memRes1.allocs.size(), Eq(0u)); + EXPECT_THAT(memRes1.deallocs.size(), Eq(0u)); + EXPECT_THAT(memRes2.allocs.size(), Eq(1u)); + EXPECT_THAT(memRes2.allocs[0].bytes, Eq(sizeof(Derived1))); + EXPECT_THAT(memRes2.allocs[0].alignment, Eq(alignof(Derived1))); + EXPECT_THAT(memRes2.allocs[0].typeId, + Eq(bitsery::ext::StandardRTTI::get())); + EXPECT_THAT(memRes2.deallocs.size(), Eq(1u)); + EXPECT_THAT(memRes2.deallocs[0].bytes, Eq(sizeof(Derived2))); + EXPECT_THAT(memRes2.deallocs[0].alignment, Eq(alignof(Derived2))); + EXPECT_THAT(memRes2.deallocs[0].typeId, + Eq(bitsery::ext::StandardRTTI::get())); - EXPECT_THAT(dRes, ::testing::NotNull()); - EXPECT_THAT(*dData, *dRes); - EXPECT_THAT(memRes1.allocs.size(), Eq(0u)); - EXPECT_THAT(memRes1.deallocs.size(), Eq(0u)); - EXPECT_THAT(memRes2.allocs.size(), Eq(1u)); - EXPECT_THAT(memRes2.allocs[0].bytes, Eq(sizeof(Derived1))); - EXPECT_THAT(memRes2.allocs[0].alignment, Eq(alignof(Derived1))); - EXPECT_THAT(memRes2.allocs[0].typeId, Eq(bitsery::ext::StandardRTTI::get())); - EXPECT_THAT(memRes2.deallocs.size(), Eq(1u)); - EXPECT_THAT(memRes2.deallocs[0].bytes, Eq(sizeof(Derived2))); - EXPECT_THAT(memRes2.deallocs[0].alignment, Eq(alignof(Derived2))); - EXPECT_THAT(memRes2.deallocs[0].typeId, Eq(bitsery::ext::StandardRTTI::get())); - - delete dData; - delete dRes; + delete dData; + delete dRes; } +TEST_F(SerializeExtensionPointerWithAllocator, + MemResourceSetPerPointerByDefaultDoNotPropagate) +{ + MemResourceForTest memRes1{}; + MemResourceForTest memRes2{}; + std::get<0>(plctx).setMemResource(&memRes1); -TEST_F(SerializeExtensionPointerWithAllocator, MemResourceSetPerPointerByDefaultDoNotPropagate) { - MemResourceForTest memRes1{}; - MemResourceForTest memRes2{}; - std::get<0>(plctx).setMemResource(&memRes1); + auto data = + std::unique_ptr(new PolyPtrWithPolyPtrBase{}); + data->ptr = std::unique_ptr(new Derived1{ 5, 6 }); + createSerializer().ext( + data, StdSmartPtr{ bitsery::ext::PointerType::Nullable, &memRes2 }); - auto data = std::unique_ptr(new PolyPtrWithPolyPtrBase{}); - data->ptr = std::unique_ptr(new Derived1{5, 6}); - createSerializer().ext(data, StdSmartPtr{bitsery::ext::PointerType::Nullable, &memRes2}); + auto res = + std::unique_ptr(new DerivedPolyPtrWithPolyPtr{}); + res->ptr = std::unique_ptr(new Derived2{}); + createDeserializer().ext( + res, StdSmartPtr{ bitsery::ext::PointerType::Nullable, &memRes2 }); - auto res = std::unique_ptr(new DerivedPolyPtrWithPolyPtr{}); - res->ptr = std::unique_ptr(new Derived2{}); - createDeserializer().ext(res, StdSmartPtr{bitsery::ext::PointerType::Nullable, &memRes2}); - - - EXPECT_THAT(memRes1.allocs.size(), Eq(1u)); - // Base* was destroyed by unique_ptr on PolyPtrWithPolyPtrBase destructor, hence == 0 - EXPECT_THAT(memRes1.deallocs.size(), Eq(0u)); - - EXPECT_THAT(memRes2.allocs.size(), Eq(1u)); - EXPECT_THAT(memRes2.deallocs.size(), Eq(1u)); + EXPECT_THAT(memRes1.allocs.size(), Eq(1u)); + // Base* was destroyed by unique_ptr on PolyPtrWithPolyPtrBase destructor, + // hence == 0 + EXPECT_THAT(memRes1.deallocs.size(), Eq(0u)); + EXPECT_THAT(memRes2.allocs.size(), Eq(1u)); + EXPECT_THAT(memRes2.deallocs.size(), Eq(1u)); } -TEST_F(SerializeExtensionPointerWithAllocator, MemResourceSetPerPointerCanPropagate) { - MemResourceForTest memRes1{}; - MemResourceForTest memRes2{}; - std::get<0>(plctx).setMemResource(&memRes1); +TEST_F(SerializeExtensionPointerWithAllocator, + MemResourceSetPerPointerCanPropagate) +{ + MemResourceForTest memRes1{}; + MemResourceForTest memRes2{}; + std::get<0>(plctx).setMemResource(&memRes1); - auto data = std::unique_ptr(new PolyPtrWithPolyPtrBase{}); - data->ptr = std::unique_ptr(new Derived1{5, 6}); - createSerializer().ext(data, StdSmartPtr{bitsery::ext::PointerType::Nullable, &memRes2, true}); + auto data = + std::unique_ptr(new PolyPtrWithPolyPtrBase{}); + data->ptr = std::unique_ptr(new Derived1{ 5, 6 }); + createSerializer().ext( + data, StdSmartPtr{ bitsery::ext::PointerType::Nullable, &memRes2, true }); - auto res = std::unique_ptr(new DerivedPolyPtrWithPolyPtr{}); - res->ptr = std::unique_ptr(new Derived2{}); - createDeserializer().ext(res, StdSmartPtr{bitsery::ext::PointerType::Nullable, &memRes2, true}); - - EXPECT_THAT(memRes1.allocs.size(), Eq(0u)); - EXPECT_THAT(memRes1.deallocs.size(), Eq(0u)); - EXPECT_THAT(memRes2.allocs.size(), Eq(2u)); - // deallocates are actually == 1, because when we destroy PolyPtrWithPolyPtrBase - // it also destroys Base because it is managed by unique_ptr. - // in order to do it correctly we should always use custom deleter for structures with nested pointers - EXPECT_THAT(memRes2.deallocs.size(), Eq(1u)); + auto res = + std::unique_ptr(new DerivedPolyPtrWithPolyPtr{}); + res->ptr = std::unique_ptr(new Derived2{}); + createDeserializer().ext( + res, StdSmartPtr{ bitsery::ext::PointerType::Nullable, &memRes2, true }); + EXPECT_THAT(memRes1.allocs.size(), Eq(0u)); + EXPECT_THAT(memRes1.deallocs.size(), Eq(0u)); + EXPECT_THAT(memRes2.allocs.size(), Eq(2u)); + // deallocates are actually == 1, because when we destroy + // PolyPtrWithPolyPtrBase it also destroys Base because it is managed by + // unique_ptr. in order to do it correctly we should always use custom deleter + // for structures with nested pointers + EXPECT_THAT(memRes2.deallocs.size(), Eq(1u)); } diff --git a/tests/serialization_ext_std_bitset.cpp b/tests/serialization_ext_std_bitset.cpp index 9d687a1..85c9e24 100644 --- a/tests/serialization_ext_std_bitset.cpp +++ b/tests/serialization_ext_std_bitset.cpp @@ -1,124 +1,132 @@ -//MIT License +// MIT License // -//Copyright (c) 2020 Mindaugas Vinkelis +// Copyright (c) 2020 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: +// 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 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. +// 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 -#include #include "serialization_test_utils.h" +#include using StdBitset = bitsery::ext::StdBitset; using ValueRange = bitsery::ext::ValueRange; using testing::Eq; -TEST(SerializeExtensionStdBitset, BitsetSmallerThanULongLong) { - SerializationContext ctx; +TEST(SerializeExtensionStdBitset, BitsetSmallerThanULongLong) +{ + SerializationContext ctx; - std::bitset<31> data; - data[2] = true; - data[8] = true; - data[15] = true; - data[25] = true; - data[30] = true; - std::bitset<31> res; + std::bitset<31> data; + data[2] = true; + data[8] = true; + data[15] = true; + data[25] = true; + data[30] = true; + std::bitset<31> res; - ctx.createSerializer().ext(data, StdBitset{}); - ctx.createDeserializer().ext(res, StdBitset{}); - EXPECT_THAT(res, Eq(data)); + ctx.createSerializer().ext(data, StdBitset{}); + ctx.createDeserializer().ext(res, StdBitset{}); + EXPECT_THAT(res, Eq(data)); } -TEST(SerializeExtensionStdBitset, BitsetSmallerThanULongLong2) { - SerializationContext ctx; +TEST(SerializeExtensionStdBitset, BitsetSmallerThanULongLong2) +{ + SerializationContext ctx; - std::bitset<9> data; - data.set(); - std::bitset<9> res; + std::bitset<9> data; + data.set(); + std::bitset<9> res; - ctx.createSerializer().ext(data, StdBitset{}); - ctx.createDeserializer().ext(res, StdBitset{}); - EXPECT_THAT(res, Eq(data)); + ctx.createSerializer().ext(data, StdBitset{}); + ctx.createDeserializer().ext(res, StdBitset{}); + EXPECT_THAT(res, Eq(data)); } +TEST(SerializeExtensionStdBitset, BitsetLargerThanULongLong) +{ + SerializationContext ctx; -TEST(SerializeExtensionStdBitset, BitsetLargerThanULongLong) { - SerializationContext ctx; + std::bitset<200> data; + data[1] = true; + data[31] = true; + data[63] = true; + data[100] = true; + data[191] = true; + std::bitset<200> res; - std::bitset<200> data; - data[1] = true; - data[31] = true; - data[63] = true; - data[100] = true; - data[191] = true; - std::bitset<200> res; - - ctx.createSerializer().ext(data, StdBitset{}); - ctx.createDeserializer().ext(res, StdBitset{}); - EXPECT_THAT(res, Eq(data)); + ctx.createSerializer().ext(data, StdBitset{}); + ctx.createDeserializer().ext(res, StdBitset{}); + EXPECT_THAT(res, Eq(data)); } -TEST(SerializeExtensionStdBitset, BitsetSmallerThanULongLongBitPackingEnabled) { - SerializationContext ctx; +TEST(SerializeExtensionStdBitset, BitsetSmallerThanULongLongBitPackingEnabled) +{ + SerializationContext ctx; - std::bitset<12> data; - int other_data = 1001; - data[2] = true; - data[9] = true; - std::bitset<12> res{}; - int other_res{}; + std::bitset<12> data; + int other_data = 1001; + data[2] = true; + data[9] = true; + std::bitset<12> res{}; + int other_res{}; - ctx.createSerializer().enableBitPacking([&data, &other_data](SerializationContext::TSerializerBPEnabled& sbp) { - sbp.ext(data, StdBitset{}); - sbp.ext(other_data, ValueRange{1000,1015}); + ctx.createSerializer().enableBitPacking( + [&data, &other_data](SerializationContext::TSerializerBPEnabled& sbp) { + sbp.ext(data, StdBitset{}); + sbp.ext(other_data, ValueRange{ 1000, 1015 }); }); - ctx.createDeserializer().enableBitPacking([&res, &other_res](SerializationContext::TDeserializerBPEnabled& dbp) { - dbp.ext(res, StdBitset{}); - dbp.ext(other_res, ValueRange{1000,1015}); + ctx.createDeserializer().enableBitPacking( + [&res, &other_res](SerializationContext::TDeserializerBPEnabled& dbp) { + dbp.ext(res, StdBitset{}); + dbp.ext(other_res, ValueRange{ 1000, 1015 }); }); - EXPECT_THAT(res, Eq(data)); - EXPECT_THAT(other_res, Eq(other_data)); - EXPECT_THAT(ctx.getBufferSize(), Eq(2)); + EXPECT_THAT(res, Eq(data)); + EXPECT_THAT(other_res, Eq(other_data)); + EXPECT_THAT(ctx.getBufferSize(), Eq(2)); } -TEST(SerializeExtensionStdBitset, BitsetLargerThanULongLongBitPackingEnabled) { - SerializationContext ctx; +TEST(SerializeExtensionStdBitset, BitsetLargerThanULongLongBitPackingEnabled) +{ + SerializationContext ctx; - std::bitset<204> data; - int other_data = 1001; - data[1] = true; - data[100] = true; - data[191] = true; - std::bitset<204> res{}; - int other_res{}; + std::bitset<204> data; + int other_data = 1001; + data[1] = true; + data[100] = true; + data[191] = true; + std::bitset<204> res{}; + int other_res{}; - ctx.createSerializer().enableBitPacking([&data, &other_data](SerializationContext::TSerializerBPEnabled& sbp) { - sbp.ext(data, StdBitset{}); - sbp.ext(other_data, ValueRange{1000,1015}); + ctx.createSerializer().enableBitPacking( + [&data, &other_data](SerializationContext::TSerializerBPEnabled& sbp) { + sbp.ext(data, StdBitset{}); + sbp.ext(other_data, ValueRange{ 1000, 1015 }); }); - ctx.createDeserializer().enableBitPacking([&res, &other_res](SerializationContext::TDeserializerBPEnabled& dbp) { - dbp.ext(res, StdBitset{}); - dbp.ext(other_res, ValueRange{1000,1015}); + ctx.createDeserializer().enableBitPacking( + [&res, &other_res](SerializationContext::TDeserializerBPEnabled& dbp) { + dbp.ext(res, StdBitset{}); + dbp.ext(other_res, ValueRange{ 1000, 1015 }); }); - EXPECT_THAT(res, Eq(data)); - EXPECT_THAT(other_res, Eq(other_data)); - EXPECT_THAT(ctx.getBufferSize(), Eq(26)); + EXPECT_THAT(res, Eq(data)); + EXPECT_THAT(other_res, Eq(other_data)); + EXPECT_THAT(ctx.getBufferSize(), Eq(26)); } diff --git a/tests/serialization_ext_std_chrono.cpp b/tests/serialization_ext_std_chrono.cpp index 1220881..b293dc5 100644 --- a/tests/serialization_ext_std_chrono.cpp +++ b/tests/serialization_ext_std_chrono.cpp @@ -1,81 +1,85 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. +// 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 #include "serialization_test_utils.h" +#include using StdDuration = bitsery::ext::StdDuration; using StdTimePoint = bitsery::ext::StdTimePoint; using testing::Eq; -TEST(SerializeExtensionStdChrono, IntegralDuration) { - SerializationContext ctx1; - using Hours = std::chrono::duration>; +TEST(SerializeExtensionStdChrono, IntegralDuration) +{ + SerializationContext ctx1; + using Hours = std::chrono::duration>; - Hours data{43}; - Hours res{}; + Hours data{ 43 }; + Hours res{}; - ctx1.createSerializer().ext4b(data, StdDuration{}); - ctx1.createDeserializer().ext4b(res, StdDuration{}); - EXPECT_THAT(res, Eq(data)); + ctx1.createSerializer().ext4b(data, StdDuration{}); + ctx1.createDeserializer().ext4b(res, StdDuration{}); + EXPECT_THAT(res, Eq(data)); } -TEST(SerializeExtensionStdChrono, IntegralTimePoint) { - SerializationContext ctx1; - using Duration = std::chrono::duration; - using TP = std::chrono::time_point; +TEST(SerializeExtensionStdChrono, IntegralTimePoint) +{ + SerializationContext ctx1; + using Duration = std::chrono::duration; + using TP = std::chrono::time_point; - TP data{Duration{243}}; - TP res{}; + TP data{ Duration{ 243 } }; + TP res{}; - ctx1.createSerializer().ext8b(data, StdTimePoint{}); - ctx1.createDeserializer().ext8b(res, StdTimePoint{}); - EXPECT_THAT(res, Eq(data)); + ctx1.createSerializer().ext8b(data, StdTimePoint{}); + ctx1.createDeserializer().ext8b(res, StdTimePoint{}); + EXPECT_THAT(res, Eq(data)); } -TEST(SerializeExtensionStdChrono, FloatDuration) { - SerializationContext ctx1; - using Hours = std::chrono::duration>; +TEST(SerializeExtensionStdChrono, FloatDuration) +{ + SerializationContext ctx1; + using Hours = std::chrono::duration>; - Hours data{43.5f}; - Hours res{}; + Hours data{ 43.5f }; + Hours res{}; - ctx1.createSerializer().ext4b(data, StdDuration{}); - ctx1.createDeserializer().ext4b(res, StdDuration{}); - EXPECT_THAT(res, Eq(data)); + ctx1.createSerializer().ext4b(data, StdDuration{}); + ctx1.createDeserializer().ext4b(res, StdDuration{}); + EXPECT_THAT(res, Eq(data)); } -TEST(SerializeExtensionStdChrono, FloatTimePoint) { - SerializationContext ctx1; - using Duration = std::chrono::duration; - using TP = std::chrono::time_point; +TEST(SerializeExtensionStdChrono, FloatTimePoint) +{ + SerializationContext ctx1; + using Duration = std::chrono::duration; + using TP = std::chrono::time_point; - TP data{Duration{243457.4}}; - TP res{}; + TP data{ Duration{ 243457.4 } }; + TP res{}; - ctx1.createSerializer().ext8b(data, StdTimePoint{}); - ctx1.createDeserializer().ext8b(res, StdTimePoint{}); - EXPECT_THAT(res, Eq(data)); + ctx1.createSerializer().ext8b(data, StdTimePoint{}); + ctx1.createDeserializer().ext8b(res, StdTimePoint{}); + EXPECT_THAT(res, Eq(data)); } diff --git a/tests/serialization_ext_std_map.cpp b/tests/serialization_ext_std_map.cpp index e73a96c..e1b1a48 100644 --- a/tests/serialization_ext_std_map.cpp +++ b/tests/serialization_ext_std_map.cpp @@ -1,139 +1,151 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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 -#include +#include #include +#include -#include #include "serialization_test_utils.h" +#include using StdMap = bitsery::ext::StdMap; using testing::Eq; template -Container createData() { - return {}; +Container +createData() +{ + return {}; } template<> -std::unordered_map createData>() { - return { - std::make_pair("some key", MyStruct1{874,456}), - std::make_pair("other key", MyStruct1{-34,8645}), - std::make_pair("secret key", MyStruct1{-4878,3468975}) - }; +std::unordered_map +createData>() +{ + return { std::make_pair("some key", MyStruct1{ 874, 456 }), + std::make_pair("other key", MyStruct1{ -34, 8645 }), + std::make_pair("secret key", MyStruct1{ -4878, 3468975 }) }; } template<> -std::unordered_multimap createData>() { - return { - std::pair(545, 45.485f), - std::pair(6748, -7891.5f), - std::pair(845, -457.0f) - }; +std::unordered_multimap +createData>() +{ + return { std::pair(545, 45.485f), + std::pair(6748, -7891.5f), + std::pair(845, -457.0f) }; } template<> -std::map createData>() { - return { - std::make_pair(MyEnumClass::E3, MyStruct1{874,456}), - std::make_pair(MyEnumClass::E6, MyStruct1{-34,8645}), - std::make_pair(MyEnumClass::E2, MyStruct1{-4878,3468975}) - }; +std::map +createData>() +{ + return { std::make_pair(MyEnumClass::E3, MyStruct1{ 874, 456 }), + std::make_pair(MyEnumClass::E6, MyStruct1{ -34, 8645 }), + std::make_pair(MyEnumClass::E2, MyStruct1{ -4878, 3468975 }) }; } template<> -std::multimap createData>() { - return {//these are optimized with range and entropy - std::pair(-45, -984196845ll), - std::pair(54, 1ll), - std::pair(98, 3ll) - }; +std::multimap +createData>() +{ + return { // these are optimized with range and entropy + std::pair(-45, -984196845ll), + std::pair(54, 1ll), + std::pair(98, 3ll) + }; } template -class SerializeExtensionStdMap : public testing::Test { +class SerializeExtensionStdMap : public testing::Test +{ public: - using TContainer = T; + using TContainer = T; - const TContainer src = createData(); - TContainer res{}; + const TContainer src = createData(); + TContainer res{}; }; -using SerializeExtensionStdMapTypes = ::testing::Types< - std::unordered_map, - std::unordered_multimap, - std::map, - std::multimap ->; +using SerializeExtensionStdMapTypes = + ::testing::Types, + std::unordered_multimap, + std::map, + std::multimap>; -TYPED_TEST_SUITE(SerializeExtensionStdMap, SerializeExtensionStdMapTypes,); +TYPED_TEST_SUITE(SerializeExtensionStdMap, SerializeExtensionStdMapTypes, ); namespace bitsery { - template - void serialize(S& s, std::unordered_map& o) { - s.ext(o, StdMap{10}, [](S& s, std::string& key, MyStruct1& value) { - s.text1b(key, 100); - s.object(value); - }); - } +template +void +serialize(S& s, std::unordered_map& o) +{ + s.ext(o, StdMap{ 10 }, [](S& s, std::string& key, MyStruct1& value) { + s.text1b(key, 100); + s.object(value); + }); +} - template - void serialize(S& s, std::unordered_multimap& o) { - s.ext(o, StdMap{10}, [](S& s, int32_t& key, float& value) { - s.value4b(key); - s.value4b(value); - }); - } +template +void +serialize(S& s, std::unordered_multimap& o) +{ + s.ext(o, StdMap{ 10 }, [](S& s, int32_t& key, float& value) { + s.value4b(key); + s.value4b(value); + }); +} - template - void serialize(S& s, std::map& o) { - s.ext(o, StdMap{10}, [](S& s, MyEnumClass& key, MyStruct1& value) { - s.value4b(key); - s.object(value); - }); - } - - template - void serialize(S& s, std::multimap& o) { - s.ext(o, StdMap{10}, [](S& s, int32_t& key, int64_t& value) { - s.enableBitPacking([&key, &value](typename S::BPEnabledType& sbp) { - int64_t values[3]{1ll, 2ll, 3ll}; - sbp.ext(key, bitsery::ext::ValueRange{-100,100}); - sbp.ext8b(value, bitsery::ext::Entropy{values}); - }); - }); - } +template +void +serialize(S& s, std::map& o) +{ + s.ext(o, StdMap{ 10 }, [](S& s, MyEnumClass& key, MyStruct1& value) { + s.value4b(key); + s.object(value); + }); +} +template +void +serialize(S& s, std::multimap& o) +{ + s.ext(o, StdMap{ 10 }, [](S& s, int32_t& key, int64_t& value) { + s.enableBitPacking([&key, &value](typename S::BPEnabledType& sbp) { + int64_t values[3]{ 1ll, 2ll, 3ll }; + sbp.ext(key, bitsery::ext::ValueRange{ -100, 100 }); + sbp.ext8b(value, bitsery::ext::Entropy{ values }); + }); + }); +} } -TYPED_TEST(SerializeExtensionStdMap, SerializeAndDeserializeEquals) { - SerializationContext ctx1; - ctx1.createSerializer().object(this->src); - ctx1.createDeserializer().object(this->res); - EXPECT_THAT(this->res, Eq(this->src)); +TYPED_TEST(SerializeExtensionStdMap, SerializeAndDeserializeEquals) +{ + SerializationContext ctx1; + ctx1.createSerializer().object(this->src); + ctx1.createDeserializer().object(this->res); + EXPECT_THAT(this->res, Eq(this->src)); } diff --git a/tests/serialization_ext_std_optional.cpp b/tests/serialization_ext_std_optional.cpp index b07dc60..b279116 100644 --- a/tests/serialization_ext_std_optional.cpp +++ b/tests/serialization_ext_std_optional.cpp @@ -1,28 +1,27 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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 #if __cplusplus > 201402L @@ -36,92 +35,96 @@ using BPDes = SerializationContext::TDeserializer::BPEnabledType; using testing::Eq; -template -void test(SerializationContext& ctx, const T& v, T& r) { - ctx.createSerializer().ext4b(v, StdOptional{}); - ctx.createDeserializer().ext4b(r, StdOptional{}); +template +void +test(SerializationContext& ctx, const T& v, T& r) +{ + ctx.createSerializer().ext4b(v, StdOptional{}); + ctx.createDeserializer().ext4b(r, StdOptional{}); } -TEST(SerializeExtensionStdOptional, EmptyOptional) { - std::optional t1{}; - std::optional r1{}; +TEST(SerializeExtensionStdOptional, EmptyOptional) +{ + std::optional t1{}; + std::optional r1{}; - SerializationContext ctx1; - test(ctx1,t1, r1); - EXPECT_THAT(ctx1.getBufferSize(), Eq(1)); - EXPECT_THAT(t1, Eq(r1)); + SerializationContext ctx1; + test(ctx1, t1, r1); + EXPECT_THAT(ctx1.getBufferSize(), Eq(1)); + EXPECT_THAT(t1, Eq(r1)); - - r1 = 3; - SerializationContext ctx2; - test(ctx2,t1, r1); - EXPECT_THAT(ctx2.getBufferSize(), Eq(1)); - EXPECT_THAT(t1, Eq(r1)); + r1 = 3; + SerializationContext ctx2; + test(ctx2, t1, r1); + EXPECT_THAT(ctx2.getBufferSize(), Eq(1)); + EXPECT_THAT(t1, Eq(r1)); } -TEST(SerializeExtensionStdOptional, OptionalHasValue) { - std::optional t1{43}; - std::optional r1{52}; +TEST(SerializeExtensionStdOptional, OptionalHasValue) +{ + std::optional t1{ 43 }; + std::optional r1{ 52 }; - SerializationContext ctx1; - test(ctx1,t1, r1); - EXPECT_THAT(ctx1.getBufferSize(), Eq(1 + sizeof(int))); - EXPECT_THAT(t1.value(), Eq(r1.value())); - - r1 = std::optional{}; - SerializationContext ctx2; - test(ctx2,t1, r1); - EXPECT_THAT(ctx2.getBufferSize(), Eq(1 + sizeof(int))); - EXPECT_THAT(t1.value(), Eq(r1.value())); + SerializationContext ctx1; + test(ctx1, t1, r1); + EXPECT_THAT(ctx1.getBufferSize(), Eq(1 + sizeof(int))); + EXPECT_THAT(t1.value(), Eq(r1.value())); + r1 = std::optional{}; + SerializationContext ctx2; + test(ctx2, t1, r1); + EXPECT_THAT(ctx2.getBufferSize(), Eq(1 + sizeof(int))); + EXPECT_THAT(t1.value(), Eq(r1.value())); } -TEST(SerializeExtensionStdOptional, AlignAfterStateWriteRead) { - std::optional t1{43}; - std::optional r1{52}; - auto range = bitsery::ext::ValueRange{40,60}; +TEST(SerializeExtensionStdOptional, AlignAfterStateWriteRead) +{ + std::optional t1{ 43 }; + std::optional r1{ 52 }; + auto range = bitsery::ext::ValueRange{ 40, 60 }; - SerializationContext ctx; - ctx.createSerializer().enableBitPacking([&t1, &range](BPSer& ser) { - - ser.ext(t1, StdOptional(true), [&range](BPSer& ser, int32_t& v) { - ser.ext(v, range); - }); + SerializationContext ctx; + ctx.createSerializer().enableBitPacking([&t1, &range](BPSer& ser) { + ser.ext(t1, StdOptional(true), [&range](BPSer& ser, int32_t& v) { + ser.ext(v, range); }); - ctx.createDeserializer().enableBitPacking([&r1, &range](BPDes& des) { - des.ext(r1, StdOptional(true), [&range](BPDes& des, int32_t& v) { - des.ext(v, range); - }); + }); + ctx.createDeserializer().enableBitPacking([&r1, &range](BPDes& des) { + des.ext(r1, StdOptional(true), [&range](BPDes& des, int32_t& v) { + des.ext(v, range); }); + }); - EXPECT_THAT(ctx.getBufferSize(), Eq(2));//1byte for index + 1byte for value - EXPECT_THAT(t1.value(), Eq(r1.value())); + EXPECT_THAT(ctx.getBufferSize(), Eq(2)); // 1byte for index + 1byte for value + EXPECT_THAT(t1.value(), Eq(r1.value())); } -TEST(SerializeExtensionStdOptional, NoAlignAfterStateWriteRead) { - std::optional t1{43}; - std::optional r1{52}; - auto range = bitsery::ext::ValueRange{40,60}; +TEST(SerializeExtensionStdOptional, NoAlignAfterStateWriteRead) +{ + std::optional t1{ 43 }; + std::optional r1{ 52 }; + auto range = bitsery::ext::ValueRange{ 40, 60 }; - SerializationContext ctx; - ctx.createSerializer().enableBitPacking([&t1, &range](BPSer& ser) { - ser.ext(t1, StdOptional(false), [&range](BPSer& ser, int32_t& v) { - ser.ext(v, range); - }); + SerializationContext ctx; + ctx.createSerializer().enableBitPacking([&t1, &range](BPSer& ser) { + ser.ext(t1, StdOptional(false), [&range](BPSer& ser, int32_t& v) { + ser.ext(v, range); }); - ctx.createDeserializer().enableBitPacking([&r1, &range](BPDes& des) { - des.ext(r1, StdOptional(false), [&range](BPDes& des, int32_t& v) { - des.ext(v, range); - }); + }); + ctx.createDeserializer().enableBitPacking([&r1, &range](BPDes& des) { + des.ext(r1, StdOptional(false), [&range](BPDes& des, int32_t& v) { + des.ext(v, range); }); + }); - EXPECT_THAT(range.getRequiredBits() + 1, ::testing::Lt(8)); - EXPECT_THAT(ctx.getBufferSize(), Eq(1)); - EXPECT_THAT(t1.value(), Eq(r1.value())); + EXPECT_THAT(range.getRequiredBits() + 1, ::testing::Lt(8)); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); + EXPECT_THAT(t1.value(), Eq(r1.value())); } #elif defined(_MSC_VER) -#pragma message("C++17 and /Zc:__cplusplus option is required to enable std::optional tests") +#pragma message( \ + "C++17 and /Zc:__cplusplus option is required to enable std::optional tests") #else #pragma message("C++17 is required to enable std::optional tests") #endif diff --git a/tests/serialization_ext_std_queue.cpp b/tests/serialization_ext_std_queue.cpp index f8d126b..864e844 100644 --- a/tests/serialization_ext_std_queue.cpp +++ b/tests/serialization_ext_std_queue.cpp @@ -1,100 +1,107 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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 #include "serialization_test_utils.h" +#include using StdQueue = bitsery::ext::StdQueue; using testing::Eq; -//inherit from queue so we could take underlying container, because priority queue doesn't have equal operator defined -template +// inherit from queue so we could take underlying container, because priority +// queue doesn't have equal operator defined +template struct PriorityQueueCnt : public std::priority_queue { - static const C& getContainer(const std::priority_queue& s ) - { - //get address of underlying container - return s.*(&PriorityQueueCnt::c); - } - static C& getContainer(std::priority_queue& s ) - { - //get address of underlying container - return s.*(&PriorityQueueCnt::c); - } + static const C& getContainer(const std::priority_queue& s) + { + // get address of underlying container + return s.*(&PriorityQueueCnt::c); + } + static C& getContainer(std::priority_queue& s) + { + // get address of underlying container + return s.*(&PriorityQueueCnt::c); + } }; -template -void test(SerializationContext& ctx, const T& v, T& r) { - ctx.createSerializer().ext4b(v, StdQueue{10}); - ctx.createDeserializer().ext4b(r, StdQueue{10}); +template +void +test(SerializationContext& ctx, const T& v, T& r) +{ + ctx.createSerializer().ext4b(v, StdQueue{ 10 }); + ctx.createDeserializer().ext4b(r, StdQueue{ 10 }); } -TEST(SerializeExtensionStdQueue, QueueDefaultContainer) { - std::queue t1{}; - t1.push(3); - t1.push(-4854); - std::queue r1{}; +TEST(SerializeExtensionStdQueue, QueueDefaultContainer) +{ + std::queue t1{}; + t1.push(3); + t1.push(-4854); + std::queue r1{}; - SerializationContext ctx1{}; - test(ctx1,t1, r1); - EXPECT_THAT(t1, Eq(r1)); + SerializationContext ctx1{}; + test(ctx1, t1, r1); + EXPECT_THAT(t1, Eq(r1)); } -TEST(SerializeExtensionStdQueue, QueueVectorContainer) { - std::queue> t1{}; - t1.push(3); - t1.push(-4854); - std::queue> r1{}; +TEST(SerializeExtensionStdQueue, QueueVectorContainer) +{ + std::queue> t1{}; + t1.push(3); + t1.push(-4854); + std::queue> r1{}; - SerializationContext ctx1{}; - test(ctx1,t1, r1); - EXPECT_THAT(t1, Eq(r1)); + SerializationContext ctx1{}; + test(ctx1, t1, r1); + EXPECT_THAT(t1, Eq(r1)); } -TEST(SerializeExtensionStdQueue, PriorityQueueDefaultContainer) { - std::priority_queue t1{}; - t1.push(3); - t1.push(-4854); - std::priority_queue r1{}; +TEST(SerializeExtensionStdQueue, PriorityQueueDefaultContainer) +{ + std::priority_queue t1{}; + t1.push(3); + t1.push(-4854); + std::priority_queue r1{}; - SerializationContext ctx1{}; - test(ctx1,t1, r1); - auto & ct1 = PriorityQueueCnt>::getContainer(t1); - auto & cr1 = PriorityQueueCnt>::getContainer(r1); - EXPECT_THAT(ct1, Eq(cr1)); + SerializationContext ctx1{}; + test(ctx1, t1, r1); + auto& ct1 = PriorityQueueCnt>::getContainer(t1); + auto& cr1 = PriorityQueueCnt>::getContainer(r1); + EXPECT_THAT(ct1, Eq(cr1)); } -TEST(SerializeExtensionStdQueue, PriorityQueueDequeContainer) { - std::priority_queue> t1{}; - t1.push(678); - t1.push(-44); - std::priority_queue> r1{}; +TEST(SerializeExtensionStdQueue, PriorityQueueDequeContainer) +{ + std::priority_queue> t1{}; + t1.push(678); + t1.push(-44); + std::priority_queue> r1{}; - SerializationContext ctx1{}; - test(ctx1,t1, r1); - auto & ct1 = PriorityQueueCnt>::getContainer(t1); - auto & cr1 = PriorityQueueCnt>::getContainer(r1); - EXPECT_THAT(ct1, Eq(cr1)); + SerializationContext ctx1{}; + test(ctx1, t1, r1); + auto& ct1 = PriorityQueueCnt>::getContainer(t1); + auto& cr1 = PriorityQueueCnt>::getContainer(r1); + EXPECT_THAT(ct1, Eq(cr1)); } diff --git a/tests/serialization_ext_std_set.cpp b/tests/serialization_ext_std_set.cpp index be4fa4b..1341816 100644 --- a/tests/serialization_ext_std_set.cpp +++ b/tests/serialization_ext_std_set.cpp @@ -1,78 +1,82 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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 -#include #include "serialization_test_utils.h" +#include using StdSet = bitsery::ext::StdSet; using testing::Eq; template -class SerializeExtensionStdSet : public testing::Test { +class SerializeExtensionStdSet : public testing::Test +{ public: - using TContainer = T; - const TContainer src = {4, 8, 48, 4, 9845, 64, 8}; - TContainer res{78,74,154,8}; + using TContainer = T; + const TContainer src = { 4, 8, 48, 4, 9845, 64, 8 }; + TContainer res{ 78, 74, 154, 8 }; }; -using SerializeExtensionStdSetTypes = ::testing::Types< - std::unordered_set, - std::unordered_multiset, - std::set, - std::multiset>; +using SerializeExtensionStdSetTypes = + ::testing::Types, + std::unordered_multiset, + std::set, + std::multiset>; -TYPED_TEST_SUITE(SerializeExtensionStdSet, SerializeExtensionStdSetTypes,); +TYPED_TEST_SUITE(SerializeExtensionStdSet, SerializeExtensionStdSetTypes, ); -TYPED_TEST(SerializeExtensionStdSet, ValuesSyntaxDifferentSetTypes) { - SerializationContext ctx1; - ctx1.createSerializer().ext4b(this->src, StdSet{10}); - ctx1.createDeserializer().ext4b(this->res, StdSet{10}); - EXPECT_THAT(this->res, Eq(this->src)); +TYPED_TEST(SerializeExtensionStdSet, ValuesSyntaxDifferentSetTypes) +{ + SerializationContext ctx1; + ctx1.createSerializer().ext4b(this->src, StdSet{ 10 }); + ctx1.createDeserializer().ext4b(this->res, StdSet{ 10 }); + EXPECT_THAT(this->res, Eq(this->src)); } -TEST(SerializeExtensionStdSet, ObjectSyntax) { - SerializationContext ctx1; - std::set t1{MyStruct1{874 ,456}, MyStruct1{-874, -456}, MyStruct1{4894,0}}; - std::set r1{}; - ctx1.createSerializer().ext(t1, StdSet{10}); - ctx1.createDeserializer().ext(r1, StdSet{10}); - EXPECT_THAT(r1, Eq(t1)); +TEST(SerializeExtensionStdSet, ObjectSyntax) +{ + SerializationContext ctx1; + std::set t1{ MyStruct1{ 874, 456 }, + MyStruct1{ -874, -456 }, + MyStruct1{ 4894, 0 } }; + std::set r1{}; + ctx1.createSerializer().ext(t1, StdSet{ 10 }); + ctx1.createDeserializer().ext(r1, StdSet{ 10 }); + EXPECT_THAT(r1, Eq(t1)); } -TEST(SerializeExtensionStdSet, FunctionSyntax) { - SerializationContext ctx1; - std::unordered_multiset t1{54,-484,841,79}; - std::unordered_multiset r1{74,878,15,16,-7,5,-4,8,7}; - auto& ser = ctx1.createSerializer(); - ser.ext(t1, StdSet{10}, [](decltype(ser)& ser, int32_t& v) { - ser.value4b(v); - }); - auto& des = ctx1.createDeserializer(); - des.ext(r1, StdSet{10}, [](decltype(des)& des, int32_t& v) { - des.value4b(v); - }); - EXPECT_THAT(r1, Eq(t1)); +TEST(SerializeExtensionStdSet, FunctionSyntax) +{ + SerializationContext ctx1; + std::unordered_multiset t1{ 54, -484, 841, 79 }; + std::unordered_multiset r1{ 74, 878, 15, 16, -7, 5, -4, 8, 7 }; + auto& ser = ctx1.createSerializer(); + ser.ext( + t1, StdSet{ 10 }, [](decltype(ser)& ser, int32_t& v) { ser.value4b(v); }); + auto& des = ctx1.createDeserializer(); + des.ext( + r1, StdSet{ 10 }, [](decltype(des)& des, int32_t& v) { des.value4b(v); }); + EXPECT_THAT(r1, Eq(t1)); } diff --git a/tests/serialization_ext_std_smart_ptr.cpp b/tests/serialization_ext_std_smart_ptr.cpp index d012d8f..1f9e1cf 100644 --- a/tests/serialization_ext_std_smart_ptr.cpp +++ b/tests/serialization_ext_std_smart_ptr.cpp @@ -1,739 +1,793 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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 #include -#include #include "serialization_test_utils.h" +#include using bitsery::ext::BaseClass; using bitsery::ext::VirtualBaseClass; using bitsery::ext::InheritanceContext; using bitsery::ext::PointerLinkingContext; +using bitsery::ext::PointerType; using bitsery::ext::PolymorphicContext; using bitsery::ext::StandardRTTI; -using bitsery::ext::PointerType; -using bitsery::ext::StdSmartPtr; using bitsery::ext::PointerObserver; +using bitsery::ext::StdSmartPtr; using testing::Eq; using testing::Ne; -struct Base { - uint8_t x{}; +struct Base +{ + uint8_t x{}; - virtual ~Base() = default; + virtual ~Base() = default; }; template -void serialize(S& s, Base& o) { - s.value1b(o.x); +void +serialize(S& s, Base& o) +{ + s.value1b(o.x); } -struct Derived : virtual Base { - uint8_t y{}; +struct Derived : virtual Base +{ + uint8_t y{}; - Derived() = default; + Derived() = default; - Derived(uint8_t x_, uint8_t y_) { - x = x_; - y = y_; - } + Derived(uint8_t x_, uint8_t y_) + { + x = x_; + y = y_; + } }; template -void serialize(S& s, Derived& o) { - s.ext(o, VirtualBaseClass{}); - s.value1b(o.y); +void +serialize(S& s, Derived& o) +{ + s.ext(o, VirtualBaseClass{}); + s.value1b(o.y); } -struct MoreDerived : Derived { - uint8_t z{}; +struct MoreDerived : Derived +{ + uint8_t z{}; - MoreDerived() = default; - - MoreDerived(uint8_t x_, uint8_t y_, uint8_t z_) : Derived(x_, y_) { - z = z_; - } + MoreDerived() = default; + MoreDerived(uint8_t x_, uint8_t y_, uint8_t z_) + : Derived(x_, y_) + { + z = z_; + } }; template -void serialize(S& s, MoreDerived& o) { - s.ext(o, BaseClass{}); - s.value1b(o.z); +void +serialize(S& s, MoreDerived& o) +{ + s.ext(o, BaseClass{}); + s.value1b(o.z); } -//define relationships between base class and derived classes for runtime polymorphism +// define relationships between base class and derived classes for runtime +// polymorphism namespace bitsery { - namespace ext { +namespace ext { - template<> - struct PolymorphicBaseClass : PolymorphicDerivedClasses { - }; +template<> +struct PolymorphicBaseClass : PolymorphicDerivedClasses +{ +}; - template<> - struct PolymorphicBaseClass : PolymorphicDerivedClasses { - }; +template<> +struct PolymorphicBaseClass : PolymorphicDerivedClasses +{ +}; - } +} } template -class SerializeExtensionStdSmartPtrNonPolymorphicType : public testing::Test { +class SerializeExtensionStdSmartPtrNonPolymorphicType : public testing::Test +{ public: - template - using TPtr = typename T::template TData; - using TExt = typename T::TExt; + template + using TPtr = typename T::template TData; + using TExt = typename T::TExt; - using TContext = std::tuple; - using SerContext = BasicSerializationContext; + using TContext = std::tuple; + using SerContext = BasicSerializationContext; -//this is useful for PolymorphicContext to bind classes to serializer/deserializer - using TSerializer = typename SerContext::TSerializer; - using TDeserializer = typename SerContext::TDeserializer; + // this is useful for PolymorphicContext to bind classes to + // serializer/deserializer + using TSerializer = typename SerContext::TSerializer; + using TDeserializer = typename SerContext::TDeserializer; - TContext plctx{}; - SerContext sctx{}; + TContext plctx{}; + SerContext sctx{}; - typename SerContext::TSerializer& createSerializer() { - return sctx.createSerializer(plctx); - } + typename SerContext::TSerializer& createSerializer() + { + return sctx.createSerializer(plctx); + } - typename SerContext::TDeserializer& createDeserializer() { - return sctx.createDeserializer(plctx); - } + typename SerContext::TDeserializer& createDeserializer() + { + return sctx.createDeserializer(plctx); + } - bool isPointerContextValid() { - return std::get<0>(plctx).isValid(); - } + bool isPointerContextValid() { return std::get<0>(plctx).isValid(); } - virtual void TearDown() override { - EXPECT_TRUE(isPointerContextValid()); - } + virtual void TearDown() override { EXPECT_TRUE(isPointerContextValid()); } }; template -class SerializeExtensionStdSmartPtrPolymorphicType : public testing::Test { +class SerializeExtensionStdSmartPtrPolymorphicType : public testing::Test +{ public: - template - using TPtr = typename T::template TData; - using TExt = typename T::TExt; + template + using TPtr = typename T::template TData; + using TExt = typename T::TExt; - using TContext = std::tuple>; - using SerContext = BasicSerializationContext; + using TContext = std::tuple>; + using SerContext = BasicSerializationContext; -//this is useful for PolymorphicContext to bind classes to serializer/deserializer - using TSerializer = typename SerContext::TSerializer; - using TDeserializer = typename SerContext::TDeserializer; + // this is useful for PolymorphicContext to bind classes to + // serializer/deserializer + using TSerializer = typename SerContext::TSerializer; + using TDeserializer = typename SerContext::TDeserializer; - TContext plctx{}; - SerContext sctx{}; + TContext plctx{}; + SerContext sctx{}; - typename SerContext::TSerializer& createSerializer() { - auto& res = sctx.createSerializer(plctx); - std::get<2>(plctx).clear(); - //bind serializer with classes - std::get<2>(plctx).template registerBasesList( - bitsery::ext::PolymorphicClassesList{}); - return res; - } + typename SerContext::TSerializer& createSerializer() + { + auto& res = sctx.createSerializer(plctx); + std::get<2>(plctx).clear(); + // bind serializer with classes + std::get<2>(plctx).template registerBasesList( + bitsery::ext::PolymorphicClassesList{}); + return res; + } - typename SerContext::TDeserializer& createDeserializer() { - auto& res = sctx.createDeserializer(plctx); - std::get<2>(plctx).clear(); - //bind deserializer with classes - std::get<2>(plctx).template registerBasesList( - bitsery::ext::PolymorphicClassesList{}); - return res; - } + typename SerContext::TDeserializer& createDeserializer() + { + auto& res = sctx.createDeserializer(plctx); + std::get<2>(plctx).clear(); + // bind deserializer with classes + std::get<2>(plctx).template registerBasesList( + bitsery::ext::PolymorphicClassesList{}); + return res; + } - bool isPointerContextValid() { - return std::get<0>(plctx).isValid(); - } + bool isPointerContextValid() { return std::get<0>(plctx).isValid(); } - virtual void TearDown() override { - EXPECT_TRUE(isPointerContextValid()); - } + virtual void TearDown() override { EXPECT_TRUE(isPointerContextValid()); } }; -struct UniquePtrTest { - template - using TData = std::unique_ptr; - using TExt = StdSmartPtr; +struct UniquePtrTest +{ + template + using TData = std::unique_ptr; + using TExt = StdSmartPtr; }; -struct SharedPtrTest { - template - using TData = std::shared_ptr; - using TExt = StdSmartPtr; +struct SharedPtrTest +{ + template + using TData = std::shared_ptr; + using TExt = StdSmartPtr; }; -using TestingWithNonPolymorphicTypes = ::testing::Types< - UniquePtrTest, - SharedPtrTest>; +using TestingWithNonPolymorphicTypes = + ::testing::Types; -TYPED_TEST_SUITE(SerializeExtensionStdSmartPtrNonPolymorphicType, TestingWithNonPolymorphicTypes,); +TYPED_TEST_SUITE(SerializeExtensionStdSmartPtrNonPolymorphicType, + TestingWithNonPolymorphicTypes, ); -using TestingWithPolymorphicTypes = ::testing::Types< - UniquePtrTest, - SharedPtrTest>; +using TestingWithPolymorphicTypes = + ::testing::Types; -TYPED_TEST_SUITE(SerializeExtensionStdSmartPtrPolymorphicType, TestingWithPolymorphicTypes,); +TYPED_TEST_SUITE(SerializeExtensionStdSmartPtrPolymorphicType, + TestingWithPolymorphicTypes, ); -TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, Data0Result0) { - using Ptr = typename TestFixture::template TPtr; - using Ext = typename TestFixture::TExt; +TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, Data0Result0) +{ + using Ptr = typename TestFixture::template TPtr; + using Ext = typename TestFixture::TExt; - Ptr data{}; - this->createSerializer().ext(data, Ext{}); - Ptr res{}; - this->createDeserializer().ext(res, Ext{}); + Ptr data{}; + this->createSerializer().ext(data, Ext{}); + Ptr res{}; + this->createDeserializer().ext(res, Ext{}); - EXPECT_THAT(data.get(), ::testing::IsNull()); - EXPECT_THAT(res.get(), ::testing::IsNull()); + EXPECT_THAT(data.get(), ::testing::IsNull()); + EXPECT_THAT(res.get(), ::testing::IsNull()); } -TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, Data0Result1) { - using Ptr = typename TestFixture::template TPtr; - using Ext = typename TestFixture::TExt; +TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, Data0Result1) +{ + using Ptr = typename TestFixture::template TPtr; + using Ext = typename TestFixture::TExt; - Ptr data{}; - this->createSerializer().ext(data, Ext{}); - Ptr res{new MyStruct1{}}; - this->createDeserializer().ext(res, Ext{}); + Ptr data{}; + this->createSerializer().ext(data, Ext{}); + Ptr res{ new MyStruct1{} }; + this->createDeserializer().ext(res, Ext{}); - EXPECT_THAT(data.get(), ::testing::IsNull()); - EXPECT_THAT(res.get(), ::testing::IsNull()); + EXPECT_THAT(data.get(), ::testing::IsNull()); + EXPECT_THAT(res.get(), ::testing::IsNull()); } -TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, Data1Result0) { - using Ptr = typename TestFixture::template TPtr; - using Ext = typename TestFixture::TExt; +TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, Data1Result0) +{ + using Ptr = typename TestFixture::template TPtr; + using Ext = typename TestFixture::TExt; - Ptr data{new MyStruct1{3, 78}}; - this->createSerializer().ext(data, Ext{}); - Ptr res{}; - this->createDeserializer().ext(res, Ext{}); + Ptr data{ new MyStruct1{ 3, 78 } }; + this->createSerializer().ext(data, Ext{}); + Ptr res{}; + this->createDeserializer().ext(res, Ext{}); - EXPECT_THAT(data.get(), ::testing::NotNull()); - EXPECT_THAT(res.get(), ::testing::NotNull()); - EXPECT_THAT(res->i1, Eq(data->i1)); - EXPECT_THAT(res->i2, Eq(data->i2)); + EXPECT_THAT(data.get(), ::testing::NotNull()); + EXPECT_THAT(res.get(), ::testing::NotNull()); + EXPECT_THAT(res->i1, Eq(data->i1)); + EXPECT_THAT(res->i2, Eq(data->i2)); } -TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, Data1Result1) { - using Ptr = typename TestFixture::template TPtr; - using Ext = typename TestFixture::TExt; +TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, Data1Result1) +{ + using Ptr = typename TestFixture::template TPtr; + using Ext = typename TestFixture::TExt; - Ptr data{new MyStruct1{3, 78}}; - this->createSerializer().ext(data, Ext{}); - Ptr res{new MyStruct1{}}; - this->createDeserializer().ext(res, Ext{}); + Ptr data{ new MyStruct1{ 3, 78 } }; + this->createSerializer().ext(data, Ext{}); + Ptr res{ new MyStruct1{} }; + this->createDeserializer().ext(res, Ext{}); - EXPECT_THAT(data.get(), ::testing::NotNull()); - EXPECT_THAT(res.get(), ::testing::NotNull()); - EXPECT_THAT(res->i1, Eq(data->i1)); - EXPECT_THAT(res->i2, Eq(data->i2)); + EXPECT_THAT(data.get(), ::testing::NotNull()); + EXPECT_THAT(res.get(), ::testing::NotNull()); + EXPECT_THAT(res->i1, Eq(data->i1)); + EXPECT_THAT(res->i2, Eq(data->i2)); } -TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, CanUseLambdaOverload) { - using Ptr = typename TestFixture::template TPtr; - using Ext = typename TestFixture::TExt; +TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, + CanUseLambdaOverload) +{ + using Ptr = typename TestFixture::template TPtr; + using Ext = typename TestFixture::TExt; - Ptr data{new MyStruct1{3, 78}}; - auto& ser = this->createSerializer(); - ser.ext(data, Ext{}, [](decltype(ser)& ser, MyStruct1& o) { - //serialize only one field - ser.value4b(o.i1); - }); - Ptr res{new MyStruct1{97, 12}}; - auto& des = this->createDeserializer(); - des.ext(res, Ext{}, [](decltype(des)& des, MyStruct1& o) { - des.value4b(o.i1); - }); + Ptr data{ new MyStruct1{ 3, 78 } }; + auto& ser = this->createSerializer(); + ser.ext(data, Ext{}, [](decltype(ser)& ser, MyStruct1& o) { + // serialize only one field + ser.value4b(o.i1); + }); + Ptr res{ new MyStruct1{ 97, 12 } }; + auto& des = this->createDeserializer(); + des.ext( + res, Ext{}, [](decltype(des)& des, MyStruct1& o) { des.value4b(o.i1); }); - EXPECT_THAT(res->i1, Eq(data->i1)); - EXPECT_THAT(res->i2, Ne(data->i2)); + EXPECT_THAT(res->i1, Eq(data->i1)); + EXPECT_THAT(res->i2, Ne(data->i2)); } -TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, CanUseValueOverload) { - using Ptr = typename TestFixture::template TPtr; - using Ext = typename TestFixture::TExt; +TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, CanUseValueOverload) +{ + using Ptr = typename TestFixture::template TPtr; + using Ext = typename TestFixture::TExt; - Ptr data{new uint16_t{3}}; - this->createSerializer().ext2b(data, Ext{}); - Ptr res{}; - this->createDeserializer().ext2b(res, Ext{}); - EXPECT_THAT(*res, Eq(*data)); + Ptr data{ new uint16_t{ 3 } }; + this->createSerializer().ext2b(data, Ext{}); + Ptr res{}; + this->createDeserializer().ext2b(res, Ext{}); + EXPECT_THAT(*res, Eq(*data)); } -TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, FirstPtrThenPointerObserver) { - using Ptr = typename TestFixture::template TPtr; - using Ext = typename TestFixture::TExt; +TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, + FirstPtrThenPointerObserver) +{ + using Ptr = typename TestFixture::template TPtr; + using Ext = typename TestFixture::TExt; - Ptr data{new uint16_t{3}}; - uint16_t* dataObs = data.get(); - auto& ser = this->createSerializer(); - ser.ext2b(data, Ext{}); - ser.ext2b(dataObs, PointerObserver{}); - Ptr res{}; - uint16_t* resObs = nullptr; - auto& des = this->createDeserializer(); - des.ext2b(res, Ext{}); - des.ext2b(resObs, PointerObserver{}); + Ptr data{ new uint16_t{ 3 } }; + uint16_t* dataObs = data.get(); + auto& ser = this->createSerializer(); + ser.ext2b(data, Ext{}); + ser.ext2b(dataObs, PointerObserver{}); + Ptr res{}; + uint16_t* resObs = nullptr; + auto& des = this->createDeserializer(); + des.ext2b(res, Ext{}); + des.ext2b(resObs, PointerObserver{}); - EXPECT_THAT(resObs, Eq(res.get())); + EXPECT_THAT(resObs, Eq(res.get())); } -TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, FirstPointerObserverThenPtr) { - using Ptr = typename TestFixture::template TPtr; - using Ext = typename TestFixture::TExt; +TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, + FirstPointerObserverThenPtr) +{ + using Ptr = typename TestFixture::template TPtr; + using Ext = typename TestFixture::TExt; - Ptr data{new uint16_t{3}}; - uint16_t* dataObs = data.get(); - auto& ser = this->createSerializer(); - ser.ext2b(dataObs, PointerObserver{}); - ser.ext2b(data, Ext{}); - Ptr res{}; - uint16_t* resObs = nullptr; - auto& des = this->createDeserializer(); - des.ext2b(resObs, PointerObserver{}); - des.ext2b(res, Ext{}); - EXPECT_THAT(resObs, Eq(res.get())); + Ptr data{ new uint16_t{ 3 } }; + uint16_t* dataObs = data.get(); + auto& ser = this->createSerializer(); + ser.ext2b(dataObs, PointerObserver{}); + ser.ext2b(data, Ext{}); + Ptr res{}; + uint16_t* resObs = nullptr; + auto& des = this->createDeserializer(); + des.ext2b(resObs, PointerObserver{}); + des.ext2b(res, Ext{}); + EXPECT_THAT(resObs, Eq(res.get())); } -TYPED_TEST(SerializeExtensionStdSmartPtrPolymorphicType, Data0Result0) { - using Ptr = typename TestFixture::template TPtr; - using Ext = typename TestFixture::TExt; +TYPED_TEST(SerializeExtensionStdSmartPtrPolymorphicType, Data0Result0) +{ + using Ptr = typename TestFixture::template TPtr; + using Ext = typename TestFixture::TExt; - Ptr baseData{}; - this->createSerializer().ext(baseData, Ext{}); - Ptr baseRes{}; - this->createDeserializer().ext(baseRes, Ext{}); + Ptr baseData{}; + this->createSerializer().ext(baseData, Ext{}); + Ptr baseRes{}; + this->createDeserializer().ext(baseRes, Ext{}); - EXPECT_THAT(baseRes.get(), ::testing::IsNull()); - EXPECT_THAT(baseData.get(), ::testing::IsNull()); + EXPECT_THAT(baseRes.get(), ::testing::IsNull()); + EXPECT_THAT(baseData.get(), ::testing::IsNull()); } -TYPED_TEST(SerializeExtensionStdSmartPtrPolymorphicType, Data0Result1) { - using Ptr = typename TestFixture::template TPtr; - using Ext = typename TestFixture::TExt; +TYPED_TEST(SerializeExtensionStdSmartPtrPolymorphicType, Data0Result1) +{ + using Ptr = typename TestFixture::template TPtr; + using Ext = typename TestFixture::TExt; - Ptr baseData{}; - this->createSerializer().ext(baseData, Ext{}); + Ptr baseData{}; + this->createSerializer().ext(baseData, Ext{}); - Ptr baseRes{new Derived{}}; - this->createDeserializer().ext(baseRes, Ext{}); + Ptr baseRes{ new Derived{} }; + this->createDeserializer().ext(baseRes, Ext{}); - EXPECT_THAT(baseRes.get(), ::testing::IsNull()); - EXPECT_THAT(baseData.get(), ::testing::IsNull()); + EXPECT_THAT(baseRes.get(), ::testing::IsNull()); + EXPECT_THAT(baseData.get(), ::testing::IsNull()); } -TYPED_TEST(SerializeExtensionStdSmartPtrPolymorphicType, Data1Result0) { - using Ptr = typename TestFixture::template TPtr; - using Ext = typename TestFixture::TExt; +TYPED_TEST(SerializeExtensionStdSmartPtrPolymorphicType, Data1Result0) +{ + using Ptr = typename TestFixture::template TPtr; + using Ext = typename TestFixture::TExt; - Ptr baseData{new Derived{3, 78}}; - this->createSerializer().ext(baseData, Ext{}); - Ptr baseRes{}; - this->createDeserializer().ext(baseRes, Ext{}); + Ptr baseData{ new Derived{ 3, 78 } }; + this->createSerializer().ext(baseData, Ext{}); + Ptr baseRes{}; + this->createDeserializer().ext(baseRes, Ext{}); - auto* data = dynamic_cast(baseData.get()); - auto* res = dynamic_cast(baseRes.get()); + auto* data = dynamic_cast(baseData.get()); + auto* res = dynamic_cast(baseRes.get()); - EXPECT_THAT(data, ::testing::NotNull()); - EXPECT_THAT(res, ::testing::NotNull()); - EXPECT_THAT(res->x, Eq(data->x)); - EXPECT_THAT(res->y, Eq(data->y)); + EXPECT_THAT(data, ::testing::NotNull()); + EXPECT_THAT(res, ::testing::NotNull()); + EXPECT_THAT(res->x, Eq(data->x)); + EXPECT_THAT(res->y, Eq(data->y)); } -TYPED_TEST(SerializeExtensionStdSmartPtrPolymorphicType, DataAndResultWithDifferentRuntimeTypes) { - using Ptr = typename TestFixture::template TPtr; - using Ext = typename TestFixture::TExt; +TYPED_TEST(SerializeExtensionStdSmartPtrPolymorphicType, + DataAndResultWithDifferentRuntimeTypes) +{ + using Ptr = typename TestFixture::template TPtr; + using Ext = typename TestFixture::TExt; - Ptr baseData{new Derived{3, 78}}; - this->createSerializer().ext(baseData, Ext{}); - Ptr baseRes{new Base{}}; - this->createDeserializer().ext(baseRes, Ext{}); + Ptr baseData{ new Derived{ 3, 78 } }; + this->createSerializer().ext(baseData, Ext{}); + Ptr baseRes{ new Base{} }; + this->createDeserializer().ext(baseRes, Ext{}); - auto* data = dynamic_cast(baseData.get()); - auto* res = dynamic_cast(baseRes.get()); + auto* data = dynamic_cast(baseData.get()); + auto* res = dynamic_cast(baseRes.get()); - EXPECT_THAT(data, ::testing::NotNull()); - EXPECT_THAT(res, ::testing::NotNull()); - EXPECT_THAT(res->x, Eq(data->x)); - EXPECT_THAT(res->y, Eq(data->y)); + EXPECT_THAT(data, ::testing::NotNull()); + EXPECT_THAT(res, ::testing::NotNull()); + EXPECT_THAT(res->x, Eq(data->x)); + EXPECT_THAT(res->y, Eq(data->y)); } -class SerializeExtensionStdSmartSharedPtr : public testing::Test { +class SerializeExtensionStdSmartSharedPtr : public testing::Test +{ public: + using TContext = std::tuple>; + using SerContext = BasicSerializationContext; - using TContext = std::tuple>; - using SerContext = BasicSerializationContext; + // this is useful for PolymorphicContext to bind classes to + // serializer/deserializer + using TSerializer = typename SerContext::TSerializer; + using TDeserializer = typename SerContext::TDeserializer; -//this is useful for PolymorphicContext to bind classes to serializer/deserializer - using TSerializer = typename SerContext::TSerializer; - using TDeserializer = typename SerContext::TDeserializer; + TContext plctx{}; + SerContext sctx{}; - TContext plctx{}; - SerContext sctx{}; + typename SerContext::TSerializer& createSerializer() + { + auto& res = sctx.createSerializer(plctx); + std::get<2>(plctx).clear(); + // bind serializer with classes + std::get<2>(plctx).registerBasesList( + bitsery::ext::PolymorphicClassesList{}); + return res; + } - typename SerContext::TSerializer& createSerializer() { - auto& res = sctx.createSerializer(plctx); - std::get<2>(plctx).clear(); - //bind serializer with classes - std::get<2>(plctx).registerBasesList(bitsery::ext::PolymorphicClassesList{}); - return res; - } + typename SerContext::TDeserializer& createDeserializer() + { + auto& res = sctx.createDeserializer(plctx); + std::get<2>(plctx).clear(); + // bind deserializer with classes + std::get<2>(plctx).registerBasesList( + bitsery::ext::PolymorphicClassesList{}); + return res; + } - typename SerContext::TDeserializer& createDeserializer() { - auto& res = sctx.createDeserializer(plctx); - std::get<2>(plctx).clear(); - //bind deserializer with classes - std::get<2>(plctx).registerBasesList(bitsery::ext::PolymorphicClassesList{}); - return res; - } + size_t getBufferSize() const { return sctx.getBufferSize(); } - size_t getBufferSize() const { - return sctx.getBufferSize(); - } + bool isPointerContextValid() { return std::get<0>(plctx).isValid(); } - bool isPointerContextValid() { - return std::get<0>(plctx).isValid(); - } - - void clearSharedState() { - return std::get<0>(plctx).clearSharedState(); - } + void clearSharedState() { return std::get<0>(plctx).clearSharedState(); } }; -TEST_F(SerializeExtensionStdSmartSharedPtr, SameSharedObjectIsSerializedOnce) { +TEST_F(SerializeExtensionStdSmartSharedPtr, SameSharedObjectIsSerializedOnce) +{ - std::shared_ptr baseData1{new Derived{3, 78}}; - std::shared_ptr baseData2{baseData1}; - auto& ser = createSerializer(); - ser.ext(baseData1, StdSmartPtr{}); - ser.ext(baseData1, StdSmartPtr{}); - createDeserializer(); + std::shared_ptr baseData1{ new Derived{ 3, 78 } }; + std::shared_ptr baseData2{ baseData1 }; + auto& ser = createSerializer(); + ser.ext(baseData1, StdSmartPtr{}); + ser.ext(baseData1, StdSmartPtr{}); + createDeserializer(); - //1b linking context (for 1st time) - //1b dynamic type info - //2b Derived object - //1b linking context (for 2nd time) - EXPECT_THAT(getBufferSize(), Eq(5)); - EXPECT_TRUE(isPointerContextValid()); + // 1b linking context (for 1st time) + // 1b dynamic type info + // 2b Derived object + // 1b linking context (for 2nd time) + EXPECT_THAT(getBufferSize(), Eq(5)); + EXPECT_TRUE(isPointerContextValid()); } -TEST_F(SerializeExtensionStdSmartSharedPtr, PointerLinkingContextCorrectlyClearSharedState) { +TEST_F(SerializeExtensionStdSmartSharedPtr, + PointerLinkingContextCorrectlyClearSharedState) +{ - std::shared_ptr baseData1{new Derived{3, 78}}; + std::shared_ptr baseData1{ new Derived{ 3, 78 } }; - auto& ser = createSerializer(); - ser.ext(baseData1, StdSmartPtr{}); - std::shared_ptr baseRes1{}; - auto& des = createDeserializer(); - des.ext(baseRes1, StdSmartPtr{}); - EXPECT_THAT(baseRes1.use_count(), Eq(2)); - clearSharedState(); - EXPECT_THAT(baseRes1.use_count(), Eq(1)); - EXPECT_TRUE(isPointerContextValid()); + auto& ser = createSerializer(); + ser.ext(baseData1, StdSmartPtr{}); + std::shared_ptr baseRes1{}; + auto& des = createDeserializer(); + des.ext(baseRes1, StdSmartPtr{}); + EXPECT_THAT(baseRes1.use_count(), Eq(2)); + clearSharedState(); + EXPECT_THAT(baseRes1.use_count(), Eq(1)); + EXPECT_TRUE(isPointerContextValid()); } -TEST_F(SerializeExtensionStdSmartSharedPtr, CorrectlyManagesSameSharedObject) { +TEST_F(SerializeExtensionStdSmartSharedPtr, CorrectlyManagesSameSharedObject) +{ - std::shared_ptr baseData1{new Derived{3, 78}}; - std::shared_ptr baseData2{new Derived{55, 11}}; - std::shared_ptr baseData21{baseData2}; - auto& ser = createSerializer(); - ser.ext(baseData1, StdSmartPtr{}); - ser.ext(baseData2, StdSmartPtr{}); - ser.ext(baseData21, StdSmartPtr{}); + std::shared_ptr baseData1{ new Derived{ 3, 78 } }; + std::shared_ptr baseData2{ new Derived{ 55, 11 } }; + std::shared_ptr baseData21{ baseData2 }; + auto& ser = createSerializer(); + ser.ext(baseData1, StdSmartPtr{}); + ser.ext(baseData2, StdSmartPtr{}); + ser.ext(baseData21, StdSmartPtr{}); - std::shared_ptr baseRes1{}; - std::shared_ptr baseRes2{}; - std::shared_ptr baseRes21{}; - auto& des = createDeserializer(); - des.ext(baseRes1, StdSmartPtr{}); - des.ext(baseRes2, StdSmartPtr{}); - des.ext(baseRes21, StdSmartPtr{}); + std::shared_ptr baseRes1{}; + std::shared_ptr baseRes2{}; + std::shared_ptr baseRes21{}; + auto& des = createDeserializer(); + des.ext(baseRes1, StdSmartPtr{}); + des.ext(baseRes2, StdSmartPtr{}); + des.ext(baseRes21, StdSmartPtr{}); - auto* data = dynamic_cast(baseRes1.get()); - EXPECT_THAT(data, ::testing::NotNull()); + auto* data = dynamic_cast(baseRes1.get()); + EXPECT_THAT(data, ::testing::NotNull()); - clearSharedState(); + clearSharedState(); - EXPECT_THAT(baseRes1.use_count(), Eq(1)); - EXPECT_THAT(baseRes2.use_count(), Eq(2)); - EXPECT_THAT(baseRes21.use_count(), Eq(2)); - baseRes2.reset(); - EXPECT_THAT(baseRes21.use_count(), Eq(1)); - EXPECT_TRUE(isPointerContextValid()); + EXPECT_THAT(baseRes1.use_count(), Eq(1)); + EXPECT_THAT(baseRes2.use_count(), Eq(2)); + EXPECT_THAT(baseRes21.use_count(), Eq(2)); + baseRes2.reset(); + EXPECT_THAT(baseRes21.use_count(), Eq(1)); + EXPECT_TRUE(isPointerContextValid()); } -TEST_F(SerializeExtensionStdSmartSharedPtr, FirstSharedThenWeakPtr) { +TEST_F(SerializeExtensionStdSmartSharedPtr, FirstSharedThenWeakPtr) +{ - std::shared_ptr baseData1{new Derived{3, 78}}; - std::weak_ptr baseData11{baseData1}; - std::weak_ptr baseData12{baseData11}; - auto& ser = createSerializer(); - ser.ext(baseData1, StdSmartPtr{}); - ser.ext(baseData11, StdSmartPtr{}); - ser.ext(baseData12, StdSmartPtr{}); + std::shared_ptr baseData1{ new Derived{ 3, 78 } }; + std::weak_ptr baseData11{ baseData1 }; + std::weak_ptr baseData12{ baseData11 }; + auto& ser = createSerializer(); + ser.ext(baseData1, StdSmartPtr{}); + ser.ext(baseData11, StdSmartPtr{}); + ser.ext(baseData12, StdSmartPtr{}); - std::shared_ptr baseRes1{}; - std::weak_ptr baseRes11{}; - std::weak_ptr baseRes12{}; - auto& des = createDeserializer(); - des.ext(baseRes1, StdSmartPtr{}); - des.ext(baseRes11, StdSmartPtr{}); - des.ext(baseRes12, StdSmartPtr{}); + std::shared_ptr baseRes1{}; + std::weak_ptr baseRes11{}; + std::weak_ptr baseRes12{}; + auto& des = createDeserializer(); + des.ext(baseRes1, StdSmartPtr{}); + des.ext(baseRes11, StdSmartPtr{}); + des.ext(baseRes12, StdSmartPtr{}); - auto* data = dynamic_cast(baseRes1.get()); - EXPECT_THAT(data, ::testing::NotNull()); + auto* data = dynamic_cast(baseRes1.get()); + EXPECT_THAT(data, ::testing::NotNull()); - clearSharedState(); + clearSharedState(); - EXPECT_THAT(baseRes1.use_count(), Eq(1)); - EXPECT_THAT(baseRes11.use_count(), Eq(1)); - EXPECT_THAT(baseRes12.use_count(), Eq(1)); - baseRes1.reset(); - EXPECT_THAT(baseRes11.use_count(), Eq(0)); - EXPECT_TRUE(isPointerContextValid()); + EXPECT_THAT(baseRes1.use_count(), Eq(1)); + EXPECT_THAT(baseRes11.use_count(), Eq(1)); + EXPECT_THAT(baseRes12.use_count(), Eq(1)); + baseRes1.reset(); + EXPECT_THAT(baseRes11.use_count(), Eq(0)); + EXPECT_TRUE(isPointerContextValid()); } -TEST_F(SerializeExtensionStdSmartSharedPtr, FirstWeakThenSharedPtr) { +TEST_F(SerializeExtensionStdSmartSharedPtr, FirstWeakThenSharedPtr) +{ - std::shared_ptr baseData1{new MyStruct1{3, 78}}; - std::weak_ptr baseData11{baseData1}; - std::weak_ptr baseData2{}; - auto& ser = createSerializer(); - ser.ext(baseData2, StdSmartPtr{}); - ser.ext(baseData11, StdSmartPtr{}); - ser.ext(baseData1, StdSmartPtr{}); + std::shared_ptr baseData1{ new MyStruct1{ 3, 78 } }; + std::weak_ptr baseData11{ baseData1 }; + std::weak_ptr baseData2{}; + auto& ser = createSerializer(); + ser.ext(baseData2, StdSmartPtr{}); + ser.ext(baseData11, StdSmartPtr{}); + ser.ext(baseData1, StdSmartPtr{}); - std::shared_ptr baseRes1{}; - std::weak_ptr baseRes11{}; - std::weak_ptr baseRes2{}; - auto& des = createDeserializer(); - des.ext(baseRes2, StdSmartPtr{}); - des.ext(baseRes11, StdSmartPtr{}); - des.ext(baseRes1, StdSmartPtr{}); + std::shared_ptr baseRes1{}; + std::weak_ptr baseRes11{}; + std::weak_ptr baseRes2{}; + auto& des = createDeserializer(); + des.ext(baseRes2, StdSmartPtr{}); + des.ext(baseRes11, StdSmartPtr{}); + des.ext(baseRes1, StdSmartPtr{}); - clearSharedState(); + clearSharedState(); - - EXPECT_THAT(*baseData1, Eq(*baseRes1)); - EXPECT_THAT(baseRes1.use_count(), Eq(1)); - EXPECT_THAT(baseRes2.use_count(), Eq(0)); - EXPECT_THAT(baseRes11.use_count(), Eq(1)); - baseRes1.reset(); - EXPECT_THAT(baseRes11.use_count(), Eq(0)); - EXPECT_TRUE(isPointerContextValid()); + EXPECT_THAT(*baseData1, Eq(*baseRes1)); + EXPECT_THAT(baseRes1.use_count(), Eq(1)); + EXPECT_THAT(baseRes2.use_count(), Eq(0)); + EXPECT_THAT(baseRes11.use_count(), Eq(1)); + baseRes1.reset(); + EXPECT_THAT(baseRes11.use_count(), Eq(0)); + EXPECT_TRUE(isPointerContextValid()); } -TEST_F(SerializeExtensionStdSmartSharedPtr, WeakPtrFirstPolymorphicData0Result1) { +TEST_F(SerializeExtensionStdSmartSharedPtr, WeakPtrFirstPolymorphicData0Result1) +{ - std::shared_ptr baseData1{}; - std::weak_ptr baseData2{}; - auto& ser = createSerializer(); - ser.ext(baseData2, StdSmartPtr{}); - ser.ext(baseData1, StdSmartPtr{}); + std::shared_ptr baseData1{}; + std::weak_ptr baseData2{}; + auto& ser = createSerializer(); + ser.ext(baseData2, StdSmartPtr{}); + ser.ext(baseData1, StdSmartPtr{}); - std::shared_ptr baseRes1{new Base{}}; - std::weak_ptr baseRes2{baseRes1}; - auto& des = createDeserializer(); - des.ext(baseRes2, StdSmartPtr{}); - des.ext(baseRes1, StdSmartPtr{}); + std::shared_ptr baseRes1{ new Base{} }; + std::weak_ptr baseRes2{ baseRes1 }; + auto& des = createDeserializer(); + des.ext(baseRes2, StdSmartPtr{}); + des.ext(baseRes1, StdSmartPtr{}); + clearSharedState(); - clearSharedState(); - - EXPECT_THAT(baseRes1.use_count(), Eq(0)); - EXPECT_THAT(baseRes2.use_count(), Eq(0)); - baseRes1.reset(); - EXPECT_TRUE(isPointerContextValid()); + EXPECT_THAT(baseRes1.use_count(), Eq(0)); + EXPECT_THAT(baseRes2.use_count(), Eq(0)); + baseRes1.reset(); + EXPECT_TRUE(isPointerContextValid()); } -TEST_F(SerializeExtensionStdSmartSharedPtr, WeakPtrFirstNonPolymorphicData0Result1) { +TEST_F(SerializeExtensionStdSmartSharedPtr, + WeakPtrFirstNonPolymorphicData0Result1) +{ - std::shared_ptr baseData1{}; - std::weak_ptr baseData2{}; - auto& ser = createSerializer(); - ser.ext(baseData2, StdSmartPtr{}); - ser.ext(baseData1, StdSmartPtr{}); + std::shared_ptr baseData1{}; + std::weak_ptr baseData2{}; + auto& ser = createSerializer(); + ser.ext(baseData2, StdSmartPtr{}); + ser.ext(baseData1, StdSmartPtr{}); - std::shared_ptr baseRes1{new MyStruct2{MyStruct2::MyEnum::V4, {1, 87}}}; - std::weak_ptr baseRes2{baseRes1}; - auto& des = createDeserializer(); - des.ext(baseRes2, StdSmartPtr{}); - des.ext(baseRes1, StdSmartPtr{}); + std::shared_ptr baseRes1{ new MyStruct2{ MyStruct2::MyEnum::V4, + { 1, 87 } } }; + std::weak_ptr baseRes2{ baseRes1 }; + auto& des = createDeserializer(); + des.ext(baseRes2, StdSmartPtr{}); + des.ext(baseRes1, StdSmartPtr{}); + clearSharedState(); - clearSharedState(); - - EXPECT_THAT(baseRes1.use_count(), Eq(0)); - EXPECT_THAT(baseRes2.use_count(), Eq(0)); - baseRes1.reset(); - EXPECT_TRUE(isPointerContextValid()); + EXPECT_THAT(baseRes1.use_count(), Eq(0)); + EXPECT_THAT(baseRes2.use_count(), Eq(0)); + baseRes1.reset(); + EXPECT_TRUE(isPointerContextValid()); } -TEST_F(SerializeExtensionStdSmartSharedPtr, FewPtrsAreEmpty) { +TEST_F(SerializeExtensionStdSmartSharedPtr, FewPtrsAreEmpty) +{ - std::shared_ptr baseData1{new Derived{3, 78}}; - std::shared_ptr baseData2{}; - std::weak_ptr baseData3{}; - std::weak_ptr baseData11{baseData1}; - auto& ser = createSerializer(); - ser.ext(baseData1, StdSmartPtr{}); - ser.ext(baseData2, StdSmartPtr{}); - ser.ext(baseData3, StdSmartPtr{}); - ser.ext(baseData11, StdSmartPtr{}); + std::shared_ptr baseData1{ new Derived{ 3, 78 } }; + std::shared_ptr baseData2{}; + std::weak_ptr baseData3{}; + std::weak_ptr baseData11{ baseData1 }; + auto& ser = createSerializer(); + ser.ext(baseData1, StdSmartPtr{}); + ser.ext(baseData2, StdSmartPtr{}); + ser.ext(baseData3, StdSmartPtr{}); + ser.ext(baseData11, StdSmartPtr{}); - std::shared_ptr baseRes1{}; - std::shared_ptr baseRes2{new Derived{3, 78}}; - std::weak_ptr baseRes3{baseRes2}; - std::weak_ptr baseRes11{}; - auto& des = createDeserializer(); - des.ext(baseRes1, StdSmartPtr{}); - des.ext(baseRes2, StdSmartPtr{}); - des.ext(baseRes3, StdSmartPtr{}); - des.ext(baseRes11, StdSmartPtr{}); + std::shared_ptr baseRes1{}; + std::shared_ptr baseRes2{ new Derived{ 3, 78 } }; + std::weak_ptr baseRes3{ baseRes2 }; + std::weak_ptr baseRes11{}; + auto& des = createDeserializer(); + des.ext(baseRes1, StdSmartPtr{}); + des.ext(baseRes2, StdSmartPtr{}); + des.ext(baseRes3, StdSmartPtr{}); + des.ext(baseRes11, StdSmartPtr{}); - clearSharedState(); + clearSharedState(); - EXPECT_THAT(baseRes1.use_count(), Eq(1)); - EXPECT_THAT(baseRes2.use_count(), Eq(0)); - EXPECT_THAT(baseRes3.use_count(), Eq(0)); - EXPECT_THAT(baseRes11.use_count(), Eq(1)); - baseRes1.reset(); - EXPECT_THAT(baseRes11.use_count(), Eq(0)); - EXPECT_TRUE(isPointerContextValid()); + EXPECT_THAT(baseRes1.use_count(), Eq(1)); + EXPECT_THAT(baseRes2.use_count(), Eq(0)); + EXPECT_THAT(baseRes3.use_count(), Eq(0)); + EXPECT_THAT(baseRes11.use_count(), Eq(1)); + baseRes1.reset(); + EXPECT_THAT(baseRes11.use_count(), Eq(0)); + EXPECT_TRUE(isPointerContextValid()); } +TEST_F(SerializeExtensionStdSmartSharedPtr, WhenResultObjectExistsSameType) +{ -TEST_F(SerializeExtensionStdSmartSharedPtr, WhenResultObjectExistsSameType) { + std::shared_ptr baseData1{ new Derived{ 3, 78 } }; + auto& ser = createSerializer(); + ser.ext(baseData1, StdSmartPtr{}); - std::shared_ptr baseData1{new Derived{3, 78}}; - auto& ser = createSerializer(); - ser.ext(baseData1, StdSmartPtr{}); + std::shared_ptr baseRes1{ new Derived{ 0, 0 } }; + auto& des = createDeserializer(); + des.ext(baseRes1, StdSmartPtr{}); - std::shared_ptr baseRes1{new Derived{0, 0}}; - auto& des = createDeserializer(); - des.ext(baseRes1, StdSmartPtr{}); + clearSharedState(); - clearSharedState(); - - EXPECT_THAT(baseRes1.use_count(), Eq(1)); - EXPECT_THAT(baseRes1->x, Eq(baseData1->x)); - EXPECT_TRUE(isPointerContextValid()); + EXPECT_THAT(baseRes1.use_count(), Eq(1)); + EXPECT_THAT(baseRes1->x, Eq(baseData1->x)); + EXPECT_TRUE(isPointerContextValid()); } -TEST_F(SerializeExtensionStdSmartSharedPtr, WhenResultObjectExistsDifferentType) { +TEST_F(SerializeExtensionStdSmartSharedPtr, WhenResultObjectExistsDifferentType) +{ - std::shared_ptr baseData1{new Derived{3, 78}}; - auto& ser = createSerializer(); - ser.ext(baseData1, StdSmartPtr{}); + std::shared_ptr baseData1{ new Derived{ 3, 78 } }; + auto& ser = createSerializer(); + ser.ext(baseData1, StdSmartPtr{}); - std::shared_ptr baseRes1{new Base{}}; - auto& des = createDeserializer(); - des.ext(baseRes1, StdSmartPtr{}); + std::shared_ptr baseRes1{ new Base{} }; + auto& des = createDeserializer(); + des.ext(baseRes1, StdSmartPtr{}); - clearSharedState(); + clearSharedState(); - EXPECT_THAT(baseRes1.use_count(), Eq(1)); - EXPECT_THAT(baseRes1->x, Eq(baseData1->x)); - EXPECT_THAT(dynamic_cast(baseRes1.get()), ::testing::NotNull()); - EXPECT_TRUE(isPointerContextValid()); + EXPECT_THAT(baseRes1.use_count(), Eq(1)); + EXPECT_THAT(baseRes1->x, Eq(baseData1->x)); + EXPECT_THAT(dynamic_cast(baseRes1.get()), ::testing::NotNull()); + EXPECT_TRUE(isPointerContextValid()); } -TEST_F(SerializeExtensionStdSmartSharedPtr, WhenOnlyWeakPtrIsSerializedThenPointerCointextIsInvalid) { - std::shared_ptr tmp{new Derived{3, 78}}; - std::weak_ptr baseData1{tmp}; - auto& ser = createSerializer(); - ser.ext(baseData1, StdSmartPtr{}); +TEST_F(SerializeExtensionStdSmartSharedPtr, + WhenOnlyWeakPtrIsSerializedThenPointerCointextIsInvalid) +{ + std::shared_ptr tmp{ new Derived{ 3, 78 } }; + std::weak_ptr baseData1{ tmp }; + auto& ser = createSerializer(); + ser.ext(baseData1, StdSmartPtr{}); - EXPECT_FALSE(isPointerContextValid()); + EXPECT_FALSE(isPointerContextValid()); } -TEST_F(SerializeExtensionStdSmartSharedPtr, WhenOnlyWeakPtrIsDeserializedThenPointerCointextIsInvalid) { - std::shared_ptr baseData1{new Derived{3, 78}}; - auto& ser = createSerializer(); - ser.ext(baseData1, StdSmartPtr{}); +TEST_F(SerializeExtensionStdSmartSharedPtr, + WhenOnlyWeakPtrIsDeserializedThenPointerCointextIsInvalid) +{ + std::shared_ptr baseData1{ new Derived{ 3, 78 } }; + auto& ser = createSerializer(); + ser.ext(baseData1, StdSmartPtr{}); - std::weak_ptr baseRes1{}; - auto& des = createDeserializer(); - des.ext(baseRes1, StdSmartPtr{}); + std::weak_ptr baseRes1{}; + auto& des = createDeserializer(); + des.ext(baseRes1, StdSmartPtr{}); - EXPECT_FALSE(isPointerContextValid()); - - EXPECT_THAT(baseRes1.use_count(), Eq(1)); - clearSharedState(); - EXPECT_THAT(baseRes1.use_count(), Eq(0)); + EXPECT_FALSE(isPointerContextValid()); + EXPECT_THAT(baseRes1.use_count(), Eq(1)); + clearSharedState(); + EXPECT_THAT(baseRes1.use_count(), Eq(0)); } -struct TestSharedFromThis : public std::enable_shared_from_this { - float x{}; +struct TestSharedFromThis + : public std::enable_shared_from_this +{ + float x{}; - explicit TestSharedFromThis() : std::enable_shared_from_this() {} + explicit TestSharedFromThis() + : std::enable_shared_from_this() + { + } - template - void serialize(S& s) { - s.value4b(x); - } + template + void serialize(S& s) + { + s.value4b(x); + } }; -TEST_F(SerializeExtensionStdSmartSharedPtr, EnableSharedFromThis) { - std::shared_ptr dataPtr(new TestSharedFromThis{}); - std::shared_ptr resPtr{}; - createSerializer().ext(dataPtr, StdSmartPtr{}); - createDeserializer().ext(resPtr, StdSmartPtr{}); - clearSharedState(); - auto resPtr2 = resPtr->shared_from_this(); - EXPECT_THAT(resPtr->x, Eq(dataPtr->x)); - EXPECT_THAT(resPtr2.use_count(), Eq(2)); +TEST_F(SerializeExtensionStdSmartSharedPtr, EnableSharedFromThis) +{ + std::shared_ptr dataPtr(new TestSharedFromThis{}); + std::shared_ptr resPtr{}; + createSerializer().ext(dataPtr, StdSmartPtr{}); + createDeserializer().ext(resPtr, StdSmartPtr{}); + clearSharedState(); + auto resPtr2 = resPtr->shared_from_this(); + EXPECT_THAT(resPtr->x, Eq(dataPtr->x)); + EXPECT_THAT(resPtr2.use_count(), Eq(2)); } -struct CustomDeleter { - void operator()(Base* p) { - delete p; - } +struct CustomDeleter +{ + void operator()(Base* p) { delete p; } }; -class SerializeExtensionStdSmartUniquePtr : public SerializeExtensionStdSmartSharedPtr { -}; +class SerializeExtensionStdSmartUniquePtr + : public SerializeExtensionStdSmartSharedPtr +{}; -TEST_F(SerializeExtensionStdSmartUniquePtr, WithCustomDeleter) { - std::unique_ptr dataPtr(new Derived{87, 7}); - std::unique_ptr resPtr{}; - createSerializer().ext(dataPtr, StdSmartPtr{}); - createDeserializer().ext(resPtr, StdSmartPtr{}); - clearSharedState(); - EXPECT_THAT(resPtr->x, Eq(dataPtr->x)); - EXPECT_THAT(dynamic_cast(resPtr.get()), ::testing::NotNull()); +TEST_F(SerializeExtensionStdSmartUniquePtr, WithCustomDeleter) +{ + std::unique_ptr dataPtr(new Derived{ 87, 7 }); + std::unique_ptr resPtr{}; + createSerializer().ext(dataPtr, StdSmartPtr{}); + createDeserializer().ext(resPtr, StdSmartPtr{}); + clearSharedState(); + EXPECT_THAT(resPtr->x, Eq(dataPtr->x)); + EXPECT_THAT(dynamic_cast(resPtr.get()), ::testing::NotNull()); } diff --git a/tests/serialization_ext_std_stack.cpp b/tests/serialization_ext_std_stack.cpp index 7bf5f1e..4c86584 100644 --- a/tests/serialization_ext_std_stack.cpp +++ b/tests/serialization_ext_std_stack.cpp @@ -1,59 +1,61 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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 "serialization_test_utils.h" #include #include -#include "serialization_test_utils.h" - using StdStack = bitsery::ext::StdStack; using testing::Eq; - -template -void test(SerializationContext& ctx, const T& v, T& r) { - ctx.createSerializer().ext4b(v, StdStack{10}); - ctx.createDeserializer().ext4b(r, StdStack{10}); +template +void +test(SerializationContext& ctx, const T& v, T& r) +{ + ctx.createSerializer().ext4b(v, StdStack{ 10 }); + ctx.createDeserializer().ext4b(r, StdStack{ 10 }); } -TEST(SerializeExtensionStdStack, DefaultContainer) { - std::stack t1{}; - t1.push(3); - t1.push(-4854); - std::stack r1{}; +TEST(SerializeExtensionStdStack, DefaultContainer) +{ + std::stack t1{}; + t1.push(3); + t1.push(-4854); + std::stack r1{}; - SerializationContext ctx1; - test(ctx1,t1, r1); - EXPECT_THAT(t1, Eq(r1)); + SerializationContext ctx1; + test(ctx1, t1, r1); + EXPECT_THAT(t1, Eq(r1)); } -TEST(SerializeExtensionStdStack, VectorContainer) { - std::stack> t1{}; - t1.push(3); - t1.push(-4854); - std::stack> r1{}; +TEST(SerializeExtensionStdStack, VectorContainer) +{ + std::stack> t1{}; + t1.push(3); + t1.push(-4854); + std::stack> r1{}; - SerializationContext ctx1; - test(ctx1,t1, r1); - EXPECT_THAT(t1, Eq(r1)); + SerializationContext ctx1; + test(ctx1, t1, r1); + EXPECT_THAT(t1, Eq(r1)); } diff --git a/tests/serialization_ext_std_tuple.cpp b/tests/serialization_ext_std_tuple.cpp index 16f4034..1ec4345 100644 --- a/tests/serialization_ext_std_tuple.cpp +++ b/tests/serialization_ext_std_tuple.cpp @@ -1,27 +1,27 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. +// 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::Eq; @@ -32,94 +32,109 @@ using testing::Eq; template using OverloadValue = bitsery::ext::OverloadValue; -TEST(SerializeExtensionStdTuple, UseDefaultSerializeFunction) { - std::tuple t1{MyStruct1{-789, 45}, MyStruct2{MyStruct2::MyEnum::V3, MyStruct1{}}}; - std::tuple r1{}; - SerializationContext ctx; - ctx.createSerializer().ext(t1, bitsery::ext::StdTuple{}); - ctx.createDeserializer().ext(r1, bitsery::ext::StdTuple{}); - EXPECT_THAT(t1, Eq(r1)); +TEST(SerializeExtensionStdTuple, UseDefaultSerializeFunction) +{ + std::tuple t1{ + MyStruct1{ -789, 45 }, MyStruct2{ MyStruct2::MyEnum::V3, MyStruct1{} } + }; + std::tuple r1{}; + SerializationContext ctx; + ctx.createSerializer().ext(t1, bitsery::ext::StdTuple{}); + ctx.createDeserializer().ext(r1, bitsery::ext::StdTuple{}); + EXPECT_THAT(t1, Eq(r1)); } -TEST(SerializeExtensionStdTuple, ValueTypesCanBeSerializedWithLambdaAndOrCallableObject) { - std::tuple t1{123.456f, -898754656}; - std::tuple r1{}; - SerializationContext ctx; - auto exec = [](auto& s, auto& o) { - s.ext(o, bitsery::ext::StdTuple{ - [](auto& s1, float& o1) { - s1.value4b(o1); - }, - OverloadValue{} - }); - }; - ctx.createSerializer().object(t1, exec); - ctx.createDeserializer().object(r1, exec); - EXPECT_THAT(t1, Eq(r1)); +TEST(SerializeExtensionStdTuple, + ValueTypesCanBeSerializedWithLambdaAndOrCallableObject) +{ + std::tuple t1{ 123.456f, -898754656 }; + std::tuple r1{}; + SerializationContext ctx; + auto exec = [](auto& s, auto& o) { + s.ext(o, + bitsery::ext::StdTuple{ [](auto& s1, float& o1) { s1.value4b(o1); }, + OverloadValue{} }); + }; + ctx.createSerializer().object(t1, exec); + ctx.createDeserializer().object(r1, exec); + EXPECT_THAT(t1, Eq(r1)); } -TEST(SerializeExtensionStdTuple, CanOverloadDefaultSerializeFunction) { - std::tuple t1{MyStruct1{-789, 45}, MyStruct2{MyStruct2::MyEnum::V3, MyStruct1{}}}; - std::tuple r1{}; - SerializationContext ctx; - auto exec = [](auto& s, auto& o) { - s.ext(o, bitsery::ext::StdTuple{ +TEST(SerializeExtensionStdTuple, CanOverloadDefaultSerializeFunction) +{ + std::tuple t1{ + MyStruct1{ -789, 45 }, MyStruct2{ MyStruct2::MyEnum::V3, MyStruct1{} } + }; + std::tuple r1{}; + SerializationContext ctx; + auto exec = [](auto& s, auto& o) { + s.ext(o, + bitsery::ext::StdTuple{ [](auto& s1, MyStruct1& o1) { - s1.value4b(o1.i1); - //do not serialize other element, it should be 0 (default) + s1.value4b(o1.i1); + // do not serialize other element, it should be 0 (default) }, - }); - }; - ctx.createSerializer().object(t1, exec); - ctx.createDeserializer().object(r1, exec); - EXPECT_THAT(std::get<1>(t1), Eq(std::get<1>(r1))); - EXPECT_THAT(std::get<0>(t1).i1, Eq(std::get<0>(r1).i1)); - EXPECT_THAT(std::get<0>(t1).i2, ::testing::Ne(std::get<0>(r1).i2)); + }); + }; + ctx.createSerializer().object(t1, exec); + ctx.createDeserializer().object(r1, exec); + EXPECT_THAT(std::get<1>(t1), Eq(std::get<1>(r1))); + EXPECT_THAT(std::get<0>(t1).i1, Eq(std::get<0>(r1).i1)); + EXPECT_THAT(std::get<0>(t1).i2, ::testing::Ne(std::get<0>(r1).i2)); } -TEST(SerializeExtensionStdTuple, EmptyTuple) { - std::tuple<> t1{}; - std::tuple<> r1{}; - SerializationContext ctx; - ctx.createSerializer().ext(t1, bitsery::ext::StdTuple{}); - ctx.createDeserializer().ext(r1, bitsery::ext::StdTuple{}); - EXPECT_THAT(t1, Eq(r1)); +TEST(SerializeExtensionStdTuple, EmptyTuple) +{ + std::tuple<> t1{}; + std::tuple<> r1{}; + SerializationContext ctx; + ctx.createSerializer().ext(t1, bitsery::ext::StdTuple{}); + ctx.createDeserializer().ext(r1, bitsery::ext::StdTuple{}); + EXPECT_THAT(t1, Eq(r1)); } -struct NonDefaultConstructable { - explicit NonDefaultConstructable(float x) : _x{x} {} +struct NonDefaultConstructable +{ + explicit NonDefaultConstructable(float x) + : _x{ x } + { + } - float _x; + float _x; - bool operator==(const NonDefaultConstructable& rhs) const { - return _x == rhs._x; - } + bool operator==(const NonDefaultConstructable& rhs) const + { + return _x == rhs._x; + } private: - friend class bitsery::Access; + friend class bitsery::Access; - NonDefaultConstructable() : _x{0.0f} {}; + NonDefaultConstructable() + : _x{ 0.0f } {}; }; -TEST(SerializeExtensionStdTuple, NonDefaultConstructable) { - std::tuple t1{34.0f}; - std::tuple r1{8.0f}; - SerializationContext ctx; - ctx.createSerializer().ext(t1, bitsery::ext::StdTuple{ - [](auto& s, NonDefaultConstructable& v) { - s.value4b(v._x); - }, +TEST(SerializeExtensionStdTuple, NonDefaultConstructable) +{ + std::tuple t1{ 34.0f }; + std::tuple r1{ 8.0f }; + SerializationContext ctx; + ctx.createSerializer().ext( + t1, + bitsery::ext::StdTuple{ + [](auto& s, NonDefaultConstructable& v) { s.value4b(v._x); }, }); - ctx.createDeserializer().ext(r1, bitsery::ext::StdTuple{ - [](auto& s, NonDefaultConstructable& v) { - s.value4b(v._x); - }, + ctx.createDeserializer().ext( + r1, + bitsery::ext::StdTuple{ + [](auto& s, NonDefaultConstructable& v) { s.value4b(v._x); }, }); - EXPECT_THAT(t1, Eq(r1)); + EXPECT_THAT(t1, Eq(r1)); } #elif defined(_MSC_VER) -#pragma message("C++17 and /Zc:__cplusplus option is required to enable std::tuple tests") +#pragma message( \ + "C++17 and /Zc:__cplusplus option is required to enable std::tuple tests") #else #pragma message("C++17 is required to enable std::tuple tests") #endif diff --git a/tests/serialization_ext_std_variant.cpp b/tests/serialization_ext_std_variant.cpp index bbccc10..831e017 100644 --- a/tests/serialization_ext_std_variant.cpp +++ b/tests/serialization_ext_std_variant.cpp @@ -1,28 +1,27 @@ -//MIT License +// MIT License // -//Copyright (c) 2019 Mindaugas Vinkelis +// Copyright (c) 2019 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: +// 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 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. +// 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 #if __cplusplus > 201402L @@ -33,142 +32,153 @@ using testing::Eq; template using OverloadValue = bitsery::ext::OverloadValue; -TEST(SerializeExtensionStdVariant, UseSerializeFunction) { +TEST(SerializeExtensionStdVariant, UseSerializeFunction) +{ - std::variant t1{MyStruct1{978, 15}}; - std::variant r1{MyStruct2{}}; - SerializationContext ctx; - ctx.createSerializer().ext(t1, bitsery::ext::StdVariant{}); - ctx.createDeserializer().ext(r1, bitsery::ext::StdVariant{}); - EXPECT_THAT(t1, Eq(r1)); + std::variant t1{ MyStruct1{ 978, 15 } }; + std::variant r1{ MyStruct2{} }; + SerializationContext ctx; + ctx.createSerializer().ext(t1, bitsery::ext::StdVariant{}); + ctx.createDeserializer().ext(r1, bitsery::ext::StdVariant{}); + EXPECT_THAT(t1, Eq(r1)); } -TEST(SerializeExtensionStdVariant, WhenTwoIndicesWithSameTypeThenDeserializeCorrectIndex) { +TEST(SerializeExtensionStdVariant, + WhenTwoIndicesWithSameTypeThenDeserializeCorrectIndex) +{ - std::variant t1{std::in_place_index_t<2>{}, MyStruct1{978, 15}}; - std::variant r1{MyStruct2{}}; - SerializationContext ctx; - ctx.createSerializer().ext(t1, bitsery::ext::StdVariant{}); - ctx.createDeserializer().ext(r1, bitsery::ext::StdVariant{}); - EXPECT_THAT(t1, Eq(r1)); + std::variant t1{ std::in_place_index_t<2>{}, + MyStruct1{ 978, 15 } }; + std::variant r1{ MyStruct2{} }; + SerializationContext ctx; + ctx.createSerializer().ext(t1, bitsery::ext::StdVariant{}); + ctx.createDeserializer().ext(r1, bitsery::ext::StdVariant{}); + EXPECT_THAT(t1, Eq(r1)); } -TEST(SerializeExtensionStdVariant, ValueTypesCanBeSerializedWithLambda) { +TEST(SerializeExtensionStdVariant, ValueTypesCanBeSerializedWithLambda) +{ - std::variant t1{5.6f}; - std::variant r1{MyStruct1{}}; - SerializationContext ctx; - auto fncFloat = [](auto& s, float& v) { - s.value4b(v); - }; - auto fncChar = [](auto& s, char& v) { - s.value1b(v); - }; - ctx.createSerializer().ext(t1, bitsery::ext::StdVariant{fncFloat, fncChar}); - ctx.createDeserializer().ext(r1, bitsery::ext::StdVariant{fncFloat, fncChar}); - EXPECT_THAT(t1, Eq(r1)); + std::variant t1{ 5.6f }; + std::variant r1{ MyStruct1{} }; + SerializationContext ctx; + auto fncFloat = [](auto& s, float& v) { s.value4b(v); }; + auto fncChar = [](auto& s, char& v) { s.value1b(v); }; + ctx.createSerializer().ext(t1, bitsery::ext::StdVariant{ fncFloat, fncChar }); + ctx.createDeserializer().ext(r1, + bitsery::ext::StdVariant{ fncFloat, fncChar }); + EXPECT_THAT(t1, Eq(r1)); } -TEST(SerializeExtensionStdVariant, ValueTypesCanBeSerializedWithLambdaAndOrCallableObject) { - std::variant t1{'Z'}; - std::variant r1{MyStruct1{}}; - SerializationContext ctx; - auto fncFloat = [](auto& s, float& v) { - s.value4b(v); - }; +TEST(SerializeExtensionStdVariant, + ValueTypesCanBeSerializedWithLambdaAndOrCallableObject) +{ + std::variant t1{ 'Z' }; + std::variant r1{ MyStruct1{} }; + SerializationContext ctx; + auto fncFloat = [](auto& s, float& v) { s.value4b(v); }; - ctx.createSerializer().ext(t1, bitsery::ext::StdVariant{fncFloat, OverloadValue{}}); - ctx.createDeserializer().ext(r1, bitsery::ext::StdVariant{fncFloat, OverloadValue{}}); - EXPECT_THAT(t1, Eq(r1)); + ctx.createSerializer().ext( + t1, bitsery::ext::StdVariant{ fncFloat, OverloadValue{} }); + ctx.createDeserializer().ext( + r1, bitsery::ext::StdVariant{ fncFloat, OverloadValue{} }); + EXPECT_THAT(t1, Eq(r1)); } -TEST(SerializeExtensionStdVariant, CanOverloadDefaultSerializationFunction) { - std::variant t1{MyStruct1{5, 9}}; - std::variant r1{MyStruct1{}}; - SerializationContext ctx; - auto exec = [](auto& s, std::variant& o) { - using S = decltype(s); - s.ext(o, bitsery::ext::StdVariant{ - [](S& s, MyStruct1& v) { - s.value4b(v.i1); - //do not serialize other element, it should be 0 (default) - }, - OverloadValue{} - }); - }; +TEST(SerializeExtensionStdVariant, CanOverloadDefaultSerializationFunction) +{ + std::variant t1{ MyStruct1{ 5, 9 } }; + std::variant r1{ MyStruct1{} }; + SerializationContext ctx; + auto exec = [](auto& s, std::variant& o) { + using S = decltype(s); + s.ext(o, + bitsery::ext::StdVariant{ [](S& s, MyStruct1& v) { + s.value4b(v.i1); + // do not serialize other element, it + // should be 0 (default) + }, + OverloadValue{} }); + }; - ctx.createSerializer().object(t1, exec); - ctx.createDeserializer().object(r1, exec); - EXPECT_THAT(std::get<1>(r1).i2, Eq(0)); + ctx.createSerializer().object(t1, exec); + ctx.createDeserializer().object(r1, exec); + EXPECT_THAT(std::get<1>(r1).i2, Eq(0)); } +struct NonDefaultConstructable +{ + explicit NonDefaultConstructable(float x) + : _x{ x } + { + } -struct NonDefaultConstructable { - explicit NonDefaultConstructable(float x) : _x{x} {} + float _x; - float _x; - - bool operator==(const NonDefaultConstructable& rhs) const { - return _x == rhs._x; - } + bool operator==(const NonDefaultConstructable& rhs) const + { + return _x == rhs._x; + } private: - friend class bitsery::Access; + friend class bitsery::Access; - NonDefaultConstructable() : _x{0.0f} {}; + NonDefaultConstructable() + : _x{ 0.0f } {}; }; -TEST(SerializeExtensionStdVariant, CanUseNonDefaultConstructableTypes) { - std::variant t1{NonDefaultConstructable{123.456f}}; - std::variant r1{MyStruct1{}}; - SerializationContext ctx; +TEST(SerializeExtensionStdVariant, CanUseNonDefaultConstructableTypes) +{ + std::variant t1{ + NonDefaultConstructable{ 123.456f } + }; + std::variant r1{ MyStruct1{} }; + SerializationContext ctx; - auto exec = [](auto& s, std::variant& o) { - using S = decltype(s); - s.ext(o, bitsery::ext::StdVariant{ - [](S& s, NonDefaultConstructable& v) { - s.value4b(v._x); - }, - OverloadValue{} - }); - }; + auto exec = [](auto& s, + std::variant& o) { + using S = decltype(s); + s.ext(o, + bitsery::ext::StdVariant{ + [](S& s, NonDefaultConstructable& v) { s.value4b(v._x); }, + OverloadValue{} }); + }; - ctx.createSerializer().object(t1, exec); - ctx.createDeserializer().object(r1, exec); + ctx.createSerializer().object(t1, exec); + ctx.createDeserializer().object(r1, exec); - EXPECT_THAT(t1, Eq(r1)); + EXPECT_THAT(t1, Eq(r1)); } +TEST(SerializeExtensionStdVariant, CorrectlyHandleMonoState) +{ + std::variant t1{}; + std::variant r1{}; + SerializationContext ctx; -TEST(SerializeExtensionStdVariant, CorrectlyHandleMonoState) { - std::variant t1{}; - std::variant r1{}; - SerializationContext ctx; + auto exec = [](auto& s, auto& o) { + using S = decltype(s); + s.ext(o, + bitsery::ext::StdVariant{ + [](S& s, NonDefaultConstructable& v) { s.value4b(v._x); }, + }); + }; - auto exec = [](auto& s, auto& o) { - using S = decltype(s); - s.ext(o, bitsery::ext::StdVariant{ - [](S& s, NonDefaultConstructable& v) { - s.value4b(v._x); - }, - }); - }; - - ctx.createSerializer().object(t1, exec); - ctx.createDeserializer().object(r1, exec); - - EXPECT_THAT(t1, Eq(r1)); - std::variant t2{}; - std::variant r2{}; - SerializationContext ctx1; - ctx1.createSerializer().ext(t2, bitsery::ext::StdVariant{}); - ctx1.createDeserializer().ext(r2, bitsery::ext::StdVariant{}); - EXPECT_THAT(t2, Eq(r2)); + ctx.createSerializer().object(t1, exec); + ctx.createDeserializer().object(r1, exec); + EXPECT_THAT(t1, Eq(r1)); + std::variant t2{}; + std::variant r2{}; + SerializationContext ctx1; + ctx1.createSerializer().ext(t2, bitsery::ext::StdVariant{}); + ctx1.createDeserializer().ext(r2, bitsery::ext::StdVariant{}); + EXPECT_THAT(t2, Eq(r2)); } #elif defined(_MSC_VER) -#pragma message("C++17 and /Zc:__cplusplus option is required to enable std::variant tests") +#pragma message( \ + "C++17 and /Zc:__cplusplus option is required to enable std::variant tests") #else #pragma message("C++17 is required to enable std::variant tests") #endif diff --git a/tests/serialization_ext_value_range.cpp b/tests/serialization_ext_value_range.cpp index 18f863c..f159057 100644 --- a/tests/serialization_ext_value_range.cpp +++ b/tests/serialization_ext_value_range.cpp @@ -1,29 +1,28 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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 "serialization_test_utils.h" #include #include -#include "serialization_test_utils.h" using namespace testing; using bitsery::details::RangeSpec; @@ -32,20 +31,20 @@ using bitsery::ext::ValueRange; #if __cplusplus > 201103L -TEST(SerializeExtensionValueRange, RequiredBitsIsConstexpr) { - constexpr RangeSpec r1{0, 31}; - static_assert(r1.bitsRequired == 5, "r1.bitsRequired == 5"); +TEST(SerializeExtensionValueRange, RequiredBitsIsConstexpr) +{ + constexpr RangeSpec r1{ 0, 31 }; + static_assert(r1.bitsRequired == 5, "r1.bitsRequired == 5"); - constexpr RangeSpec r2{MyEnumClass::E1, MyEnumClass::E4}; - static_assert(r2.bitsRequired == 2, "r2.bitsRequired == 2"); + constexpr RangeSpec r2{ MyEnumClass::E1, MyEnumClass::E4 }; + static_assert(r2.bitsRequired == 2, "r2.bitsRequired == 2"); - constexpr RangeSpec r3{-1.0,1.0, BitsConstraint{5u}}; - //EXPECT_THAT(r1.bitsRequired, Eq(5)); - static_assert(r3.bitsRequired == 5, "r3.bitsRequired == 5"); - - constexpr RangeSpec r4{-1.0f,1.0f, 0.01f}; - static_assert(r4.bitsRequired == 8, "r4.bitsRequired == 8"); + constexpr RangeSpec r3{ -1.0, 1.0, BitsConstraint{ 5u } }; + // EXPECT_THAT(r1.bitsRequired, Eq(5)); + static_assert(r3.bitsRequired == 5, "r3.bitsRequired == 5"); + constexpr RangeSpec r4{ -1.0f, 1.0f, 0.01f }; + static_assert(r4.bitsRequired == 8, "r4.bitsRequired == 8"); } #endif @@ -53,158 +52,157 @@ TEST(SerializeExtensionValueRange, RequiredBitsIsConstexpr) { using BPSer = SerializationContext::TSerializerBPEnabled; using BPDes = SerializationContext::TDeserializerBPEnabled; +TEST(SerializeExtensionValueRange, IntegerNegative) +{ + SerializationContext ctx; + ValueRange r1{ -50, 50 }; + int t1{ -8 }; + int res1; + ctx.createSerializer().enableBitPacking( + [&t1, &r1](BPSer& ser) { ser.ext(t1, r1); }); + ctx.createDeserializer().enableBitPacking( + [&res1, &r1](BPDes& des) { des.ext(res1, r1); }); -TEST(SerializeExtensionValueRange, IntegerNegative) { - SerializationContext ctx; - ValueRange r1{-50, 50}; - int t1{-8}; - int res1; - ctx.createSerializer().enableBitPacking([&t1, &r1](BPSer& ser) { - ser.ext(t1, r1); - }); - ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) { - des.ext(res1, r1); - }); - - EXPECT_THAT(ctx.getBufferSize(), Eq(1)); - EXPECT_THAT(res1, Eq(t1)); - + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); + EXPECT_THAT(res1, Eq(t1)); } -TEST(SerializeExtensionValueRange, IntegerPositive) { - SerializationContext ctx; - ValueRange r1{4u, 10u}; - unsigned t1{8}; - unsigned res1; +TEST(SerializeExtensionValueRange, IntegerPositive) +{ + SerializationContext ctx; + ValueRange r1{ 4u, 10u }; + unsigned t1{ 8 }; + unsigned res1; - ctx.createSerializer().enableBitPacking([&t1, &r1](BPSer& ser) { - ser.ext(t1, r1); - }); - ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) { - des.ext(res1, r1); - }); - - EXPECT_THAT(ctx.getBufferSize(), Eq(1)); - EXPECT_THAT(res1, Eq(t1)); + ctx.createSerializer().enableBitPacking( + [&t1, &r1](BPSer& ser) { ser.ext(t1, r1); }); + ctx.createDeserializer().enableBitPacking( + [&res1, &r1](BPDes& des) { des.ext(res1, r1); }); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); + EXPECT_THAT(res1, Eq(t1)); } -TEST(SerializeExtensionValueRange, EnumTypes) { - SerializationContext ctx; - ValueRange r1{MyEnumClass::E2, MyEnumClass::E4}; - MyEnumClass t1{MyEnumClass::E2}; - MyEnumClass res1; +TEST(SerializeExtensionValueRange, EnumTypes) +{ + SerializationContext ctx; + ValueRange r1{ MyEnumClass::E2, MyEnumClass::E4 }; + MyEnumClass t1{ MyEnumClass::E2 }; + MyEnumClass res1; - ctx.createSerializer().enableBitPacking([&t1, &r1](BPSer& ser) { - ser.ext(t1, r1); - }); - ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) { - des.ext(res1, r1); - }); - - EXPECT_THAT(ctx.getBufferSize(), Eq(1)); - EXPECT_THAT(res1, Eq(t1)); + ctx.createSerializer().enableBitPacking( + [&t1, &r1](BPSer& ser) { ser.ext(t1, r1); }); + ctx.createDeserializer().enableBitPacking( + [&res1, &r1](BPDes& des) { des.ext(res1, r1); }); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); + EXPECT_THAT(res1, Eq(t1)); } -TEST(SerializeExtensionValueRange, FloatUsingPrecisionConstraint1) { - SerializationContext ctx; - constexpr float precision{0.01f}; - constexpr float min{-1.0f}; - constexpr float max{1.0f}; - float t1{0.5f}; - ValueRange r1{min, max, precision}; +TEST(SerializeExtensionValueRange, FloatUsingPrecisionConstraint1) +{ + SerializationContext ctx; + constexpr float precision{ 0.01f }; + constexpr float min{ -1.0f }; + constexpr float max{ 1.0f }; + float t1{ 0.5f }; + ValueRange r1{ min, max, precision }; - float res1; + float res1; - ctx.createSerializer().enableBitPacking([&t1, &r1](BPSer& ser) { - ser.ext(t1, r1); - }); - ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) { - des.ext(res1, r1); - }); + ctx.createSerializer().enableBitPacking( + [&t1, &r1](BPSer& ser) { ser.ext(t1, r1); }); + ctx.createDeserializer().enableBitPacking( + [&res1, &r1](BPDes& des) { des.ext(res1, r1); }); - EXPECT_THAT(ctx.getBufferSize(), Eq(1)); - EXPECT_THAT(res1, ::testing::FloatNear(t1, (max - min) * precision)); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); + EXPECT_THAT(res1, ::testing::FloatNear(t1, (max - min) * precision)); } -TEST(SerializeExtensionValueRange, DoubleUsingPrecisionConstraint2) { - SerializationContext ctx; - constexpr double precision{0.000002}; - constexpr double min{50.0}; - constexpr double max{100000.0}; - double t1{38741.0}; - ValueRange r1{min, max, precision}; +TEST(SerializeExtensionValueRange, DoubleUsingPrecisionConstraint2) +{ + SerializationContext ctx; + constexpr double precision{ 0.000002 }; + constexpr double min{ 50.0 }; + constexpr double max{ 100000.0 }; + double t1{ 38741.0 }; + ValueRange r1{ min, max, precision }; - double res1; + double res1; - ctx.createSerializer().enableBitPacking([&t1, &r1](BPSer& ser) { - ser.ext(t1, r1); - }); - ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) { - des.ext(res1, r1); - }); + ctx.createSerializer().enableBitPacking( + [&t1, &r1](BPSer& ser) { ser.ext(t1, r1); }); + ctx.createDeserializer().enableBitPacking( + [&res1, &r1](BPDes& des) { des.ext(res1, r1); }); - EXPECT_THAT(ctx.getBufferSize(), Eq(5)); - EXPECT_THAT(res1, ::testing::DoubleNear(t1, (max - min) * precision)); + EXPECT_THAT(ctx.getBufferSize(), Eq(5)); + EXPECT_THAT(res1, ::testing::DoubleNear(t1, (max - min) * precision)); } -TEST(SerializeExtensionValueRange, FloatUsingBitsSizeConstraint1) { - SerializationContext ctx; - constexpr size_t bits = 8; - constexpr float min{-1.0f}; - constexpr float max{1.0f}; - float t1{0.5f}; - ValueRange r1{min, max, BitsConstraint(bits)}; +TEST(SerializeExtensionValueRange, FloatUsingBitsSizeConstraint1) +{ + SerializationContext ctx; + constexpr size_t bits = 8; + constexpr float min{ -1.0f }; + constexpr float max{ 1.0f }; + float t1{ 0.5f }; + ValueRange r1{ min, max, BitsConstraint(bits) }; - float res1; + float res1; - ctx.createSerializer().enableBitPacking([&t1, &r1](BPSer& ser) { - ser.ext(t1, r1); - }); - ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) { - des.ext(res1, r1); - }); + ctx.createSerializer().enableBitPacking( + [&t1, &r1](BPSer& ser) { ser.ext(t1, r1); }); + ctx.createDeserializer().enableBitPacking( + [&res1, &r1](BPDes& des) { des.ext(res1, r1); }); - EXPECT_THAT(ctx.getBufferSize(), Eq(1)); - EXPECT_THAT(res1, ::testing::FloatNear(t1, (max - min) / (static_cast>(1) << bits))); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); + EXPECT_THAT( + res1, + ::testing::FloatNear( + t1, + (max - min) / + (static_cast>(1) << bits))); } -TEST(SerializeExtensionValueRange, DoubleUsingBitsSizeConstraint2) { - SerializationContext ctx; - constexpr size_t bits = 50; - constexpr double min{50.0}; - constexpr double max{100000.0}; - double t1{38741}; - ValueRange r1{min, max, BitsConstraint(bits)}; +TEST(SerializeExtensionValueRange, DoubleUsingBitsSizeConstraint2) +{ + SerializationContext ctx; + constexpr size_t bits = 50; + constexpr double min{ 50.0 }; + constexpr double max{ 100000.0 }; + double t1{ 38741 }; + ValueRange r1{ min, max, BitsConstraint(bits) }; - double res1; + double res1; - ctx.createSerializer().enableBitPacking([&t1, &r1](BPSer& ser) { - ser.ext(t1, r1); - }); - ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) { - des.ext(res1, r1); - }); + ctx.createSerializer().enableBitPacking( + [&t1, &r1](BPSer& ser) { ser.ext(t1, r1); }); + ctx.createDeserializer().enableBitPacking( + [&res1, &r1](BPDes& des) { des.ext(res1, r1); }); - EXPECT_THAT(ctx.getBufferSize(), Eq(7)); - EXPECT_THAT(res1, ::testing::DoubleNear(t1, (max - min) / (static_cast>(1) << bits))); + EXPECT_THAT(ctx.getBufferSize(), Eq(7)); + EXPECT_THAT( + res1, + ::testing::DoubleNear( + t1, + (max - min) / + (static_cast>(1) << bits))); } -TEST(SerializeExtensionValueRange, WhenDataIsInvalidThenReturnMinimumRangeValue) { - SerializationContext ctx; - ValueRange r1{4, 10};//6 is max, but 3bits required - int res1; - uint8_t tmp{0xFF};//write all 1 so when reading 3 bits we get 7 +TEST(SerializeExtensionValueRange, WhenDataIsInvalidThenReturnMinimumRangeValue) +{ + SerializationContext ctx; + ValueRange r1{ 4, 10 }; // 6 is max, but 3bits required + int res1; + uint8_t tmp{ 0xFF }; // write all 1 so when reading 3 bits we get 7 - ctx.createSerializer().enableBitPacking([&tmp](BPSer& ser) { - ser.value1b(tmp); - }); - ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) { - des.ext(res1, r1); - }); + ctx.createSerializer().enableBitPacking( + [&tmp](BPSer& ser) { ser.value1b(tmp); }); + ctx.createDeserializer().enableBitPacking( + [&res1, &r1](BPDes& des) { des.ext(res1, r1); }); - EXPECT_THAT(ctx.getBufferSize(), Eq(1)); - EXPECT_THAT(res1, Eq(4)); - EXPECT_THAT(ctx.des->adapter().error(), Eq(bitsery::ReaderError::InvalidData)); + EXPECT_THAT(ctx.getBufferSize(), Eq(1)); + EXPECT_THAT(res1, Eq(4)); + EXPECT_THAT(ctx.des->adapter().error(), + Eq(bitsery::ReaderError::InvalidData)); } diff --git a/tests/serialization_objects.cpp b/tests/serialization_objects.cpp index 0ebc3bc..ec8290e 100644 --- a/tests/serialization_objects.cpp +++ b/tests/serialization_objects.cpp @@ -1,128 +1,132 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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 +#include -#include #include "serialization_test_utils.h" +#include +using testing::ContainerEq; 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 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 Y +{ + int y{}; + int carr[3]{}; + std::array arr{}; + std::vector vx{}; + std::string s{}; }; -struct Z { X x{}; Y y{}; }; - - -template -void serialize(S& s, Z& o) +struct Z { - s.object(o.x); - s.object(o.y); + X x{}; + Y y{}; +}; + +template +void +serialize(S& s, Z& o) +{ + s.object(o.x); + s.object(o.y); } -template -void serialize(S& s, X& o) +template +void +serialize(S& s, X& o) { - s.template value(o.x); - s.template text<1>(o.s, 1000); + s.template value(o.x); + s.template text<1>(o.s, 1000); } -template -void serialize(S& s, Y& o) +template +void +serialize(S& s, Y& o) { - auto writeInt = [](S& s, int& v) { s.template value(v); }; - s.template text<1>(o.s, 10000); - s.template value(o.y); - s.container(o.arr, writeInt); - s.container(o.carr, writeInt); - s.container(o.vx, 10000, [](S& s, X& v) { s.object(v); }); + auto writeInt = [](S& s, int& v) { s.template value(v); }; + s.template text<1>(o.s, 10000); + s.template value(o.y); + s.container(o.arr, writeInt); + s.container(o.carr, writeInt); + s.container(o.vx, 10000, [](S& s, X& v) { s.object(v); }); } +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"; -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 }; - Z z{}; - z.y = y; - z.x = X{ 234 }; - + auto& ser = ctx.createSerializer(); + ser.object(y); + ser.object(z); - auto& ser = ctx.createSerializer(); - ser.object(y); - ser.object(z); + Y yres{}; + Z zres{}; + auto& des = ctx.createDeserializer(); + des.object(yres); + des.object(zres); - 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)); + 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)); } \ No newline at end of file diff --git a/tests/serialization_size.cpp b/tests/serialization_size.cpp index cb0a1c0..dda38a3 100644 --- a/tests/serialization_size.cpp +++ b/tests/serialization_size.cpp @@ -1,64 +1,68 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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::Eq; -bool SerializeDeserializeContainerSize(SerializationContext& ctx, const size_t size) { - std::vector t1(size); - auto& ser = ctx.createSerializer(); - ser.container(t1, size+1, [](decltype(ser)& , char& ){}); - t1.clear(); - auto& des = ctx.createDeserializer(); - des.container(t1, size+1, [](decltype(des)&, char& ){}); - return t1.size() == size; +bool +SerializeDeserializeContainerSize(SerializationContext& ctx, const size_t size) +{ + std::vector t1(size); + auto& ser = ctx.createSerializer(); + ser.container(t1, size + 1, [](decltype(ser)&, char&) {}); + t1.clear(); + auto& des = ctx.createDeserializer(); + des.container(t1, size + 1, [](decltype(des)&, char&) {}); + return t1.size() == size; } -TEST(SerializeSize, WhenLengthLessThan128Then1Byte) { - SerializationContext ctx1{}; - EXPECT_TRUE(SerializeDeserializeContainerSize(ctx1, 127)); - EXPECT_THAT(ctx1.getBufferSize(), Eq(1u)); - SerializationContext ctx2; - EXPECT_TRUE(SerializeDeserializeContainerSize(ctx2, 128)); - EXPECT_THAT(ctx2.getBufferSize(), testing::Gt(1u)); +TEST(SerializeSize, WhenLengthLessThan128Then1Byte) +{ + SerializationContext ctx1{}; + EXPECT_TRUE(SerializeDeserializeContainerSize(ctx1, 127)); + EXPECT_THAT(ctx1.getBufferSize(), Eq(1u)); + SerializationContext ctx2; + EXPECT_TRUE(SerializeDeserializeContainerSize(ctx2, 128)); + EXPECT_THAT(ctx2.getBufferSize(), testing::Gt(1u)); } -TEST(SerializeSize, WhenLengthLessThan16384Then2Bytes) { - SerializationContext ctx1; - EXPECT_TRUE(SerializeDeserializeContainerSize(ctx1, 16383)); - EXPECT_THAT(ctx1.getBufferSize(), Eq(2u)); - SerializationContext ctx2; - EXPECT_TRUE(SerializeDeserializeContainerSize(ctx2, 16384)); - EXPECT_THAT(ctx2.getBufferSize(), testing::Gt(2u)); +TEST(SerializeSize, WhenLengthLessThan16384Then2Bytes) +{ + SerializationContext ctx1; + EXPECT_TRUE(SerializeDeserializeContainerSize(ctx1, 16383)); + EXPECT_THAT(ctx1.getBufferSize(), Eq(2u)); + SerializationContext ctx2; + EXPECT_TRUE(SerializeDeserializeContainerSize(ctx2, 16384)); + EXPECT_THAT(ctx2.getBufferSize(), testing::Gt(2u)); } -TEST(SerializeSize, WhenGreaterThan16383Then4Bytes) { - SerializationContext ctx1; - EXPECT_TRUE(SerializeDeserializeContainerSize(ctx1, 16384)); - EXPECT_THAT(ctx1.getBufferSize(), Eq(4u)); - SerializationContext ctx2; - EXPECT_TRUE(SerializeDeserializeContainerSize(ctx2, 66384)); - EXPECT_THAT(ctx2.getBufferSize(), Eq(4u)); +TEST(SerializeSize, WhenGreaterThan16383Then4Bytes) +{ + SerializationContext ctx1; + EXPECT_TRUE(SerializeDeserializeContainerSize(ctx1, 16384)); + EXPECT_THAT(ctx1.getBufferSize(), Eq(4u)); + SerializationContext ctx2; + EXPECT_TRUE(SerializeDeserializeContainerSize(ctx2, 66384)); + EXPECT_THAT(ctx2.getBufferSize(), Eq(4u)); } diff --git a/tests/serialization_test_utils.h b/tests/serialization_test_utils.h index a58d7bd..d04608c 100644 --- a/tests/serialization_test_utils.h +++ b/tests/serialization_test_utils.h @@ -1,167 +1,210 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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_TEST_UTILS_H #define BITSERY_SERIALIZER_TEST_UTILS_H -#include +#include #include #include -#include +#include /* * define some types for testing */ -struct MyStruct1 { - MyStruct1(int32_t v1, int32_t v2) : i1{v1}, i2{v2} {} +struct MyStruct1 +{ + MyStruct1(int32_t v1, int32_t v2) + : i1{ v1 } + , i2{ v2 } + { + } - MyStruct1() : MyStruct1{0, 0} {} + MyStruct1() + : MyStruct1{ 0, 0 } + { + } - int32_t i1; - int32_t i2; + int32_t i1; + int32_t i2; - bool operator==(const MyStruct1 &rhs) const { - return i1 == rhs.i1 && i2 == rhs.i2; - } - friend bool operator < (const MyStruct1 &lhs, const MyStruct1 &rhs) { - return lhs.i1 < rhs.i1 || (lhs.i1 == rhs.i1 && lhs.i2 < rhs.i2); - } + bool operator==(const MyStruct1& rhs) const + { + return i1 == rhs.i1 && i2 == rhs.i2; + } + friend bool operator<(const MyStruct1& lhs, const MyStruct1& rhs) + { + return lhs.i1 < rhs.i1 || (lhs.i1 == rhs.i1 && lhs.i2 < rhs.i2); + } - static constexpr size_t SIZE = sizeof(MyStruct1::i1) + sizeof(MyStruct1::i2); + static constexpr size_t SIZE = sizeof(MyStruct1::i1) + sizeof(MyStruct1::i2); }; -template -void serialize(S& s, MyStruct1& o) { - s.template value(o.i1); - s.template value(o.i2); +template +void +serialize(S& s, MyStruct1& o) +{ + s.template value(o.i1); + s.template value(o.i2); } -enum class MyEnumClass:int32_t { - E1, E2, E3, E4, E5, E6 +enum class MyEnumClass : int32_t +{ + E1, + E2, + E3, + E4, + E5, + E6 }; -struct MyStruct2 { - enum MyEnum { - V1, V2, V3, V4, V5, V6 - }; +struct MyStruct2 +{ + enum MyEnum + { + V1, + V2, + V3, + V4, + V5, + V6 + }; - MyStruct2(MyEnum e, MyStruct1 s) : e1{e}, s1{s} {} + MyStruct2(MyEnum e, MyStruct1 s) + : e1{ e } + , s1{ s } + { + } - MyStruct2() : MyStruct2{V1, {0, 0}} {} + MyStruct2() + : MyStruct2{ V1, { 0, 0 } } + { + } - MyEnum e1; - MyStruct1 s1; + MyEnum e1; + MyStruct1 s1; - bool operator==(const MyStruct2 &rhs) const { - return e1 == rhs.e1 && s1 == rhs.s1; - } + bool operator==(const MyStruct2& rhs) const + { + return e1 == rhs.e1 && s1 == rhs.s1; + } - static constexpr size_t SIZE = MyStruct1::SIZE + sizeof(MyStruct2::e1); + static constexpr size_t SIZE = MyStruct1::SIZE + sizeof(MyStruct2::e1); }; -template -void serialize(S&s, MyStruct2& o) { - s.template value(o.e1); - s.object(o.s1); +template +void +serialize(S& s, MyStruct2& o) +{ + s.template value(o.e1); + s.object(o.s1); } using Buffer = std::vector; using Reader = bitsery::InputBufferAdapter; using Writer = bitsery::OutputBufferAdapter; -template -class BasicSerializationContext { +template +class BasicSerializationContext +{ public: - using TSerializer = bitsery::Serializer; - using TDeserializer = bitsery::Deserializer; - using TSerializerBPEnabled = typename TSerializer::BPEnabledType; - using TDeserializerBPEnabled = typename TDeserializer::BPEnabledType; + using TSerializer = bitsery::Serializer; + using TDeserializer = bitsery::Deserializer; + using TSerializerBPEnabled = typename TSerializer::BPEnabledType; + using TDeserializerBPEnabled = typename TDeserializer::BPEnabledType; - Buffer buf{}; - std::unique_ptr ser{}; - std::unique_ptr des{}; + Buffer buf{}; + std::unique_ptr ser{}; + std::unique_ptr des{}; - template ::value>::type* = nullptr> - TSerializer& createSerializer() { - if (!ser) { - ser = std::unique_ptr(new TSerializer{buf}); - } - return *ser; + template::value>::type* = nullptr> + TSerializer& createSerializer() + { + if (!ser) { + ser = std::unique_ptr(new TSerializer{ buf }); } + return *ser; + } - template - TSerializer& createSerializer(typename std::enable_if::value, T>::type& ctx) { - if (!ser) { - ser = std::unique_ptr(new TSerializer{ctx, buf}); - } - return *ser; + template + TSerializer& createSerializer( + typename std::enable_if::value, T>::type& ctx) + { + if (!ser) { + ser = std::unique_ptr(new TSerializer{ ctx, buf }); } + return *ser; + } - - template ::value>::type* = nullptr> - TDeserializer& createDeserializer() { - size_t writtenBytes = 0; - if (ser) { - ser->adapter().flush(); - writtenBytes = ser->adapter().writtenBytesCount(); - } - if (!des) { - des = std::unique_ptr(new TDeserializer{buf.begin(), writtenBytes}); - } - return *des; + template::value>::type* = nullptr> + TDeserializer& createDeserializer() + { + size_t writtenBytes = 0; + if (ser) { + ser->adapter().flush(); + writtenBytes = ser->adapter().writtenBytesCount(); } - - template - TDeserializer& createDeserializer(typename std::enable_if::value, T>::type& ctx) { - size_t writtenBytes = 0; - if (ser) { - ser->adapter().flush(); - writtenBytes = ser->adapter().writtenBytesCount(); - } - if (!des) { - des = std::unique_ptr(new TDeserializer{ctx, buf.begin(), writtenBytes}); - } - return *des; + if (!des) { + des = std::unique_ptr( + new TDeserializer{ buf.begin(), writtenBytes }); } + return *des; + } - size_t getBufferSize() const { - return ser->adapter().writtenBytesCount(); + template + TDeserializer& createDeserializer( + typename std::enable_if::value, T>::type& ctx) + { + size_t writtenBytes = 0; + if (ser) { + ser->adapter().flush(); + writtenBytes = ser->adapter().writtenBytesCount(); } - - //since all containers .size() method returns size_t, it cannot be directly serialized, because size_t is platform dependant - //this function returns number of bytes written 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; + if (!des) { + des = std::unique_ptr( + new TDeserializer{ ctx, buf.begin(), writtenBytes }); } + return *des; + } + size_t getBufferSize() const { return ser->adapter().writtenBytesCount(); } + + // since all containers .size() method returns size_t, it cannot be directly + // serialized, because size_t is platform dependant this function returns + // number of bytes written 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; + } }; -//helper type +// helper type using SerializationContext = BasicSerializationContext; -#endif //BITSERY_SERIALIZER_TEST_UTILS_H +#endif // BITSERY_SERIALIZER_TEST_UTILS_H diff --git a/tests/serialization_text.cpp b/tests/serialization_text.cpp index 8f0fa56..2d76c7f 100644 --- a/tests/serialization_text.cpp +++ b/tests/serialization_text.cpp @@ -1,129 +1,140 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. - +// 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 "serialization_test_utils.h" #include #include -#include "serialization_test_utils.h" using namespace testing; -TEST(SerializeText, BasicString) { - SerializationContext ctx; - std::string t1 = "some random text"; - std::string res; +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)); + 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"); +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); + ctx.createSerializer().text(t1, 1000); + ctx.createDeserializer().text(res, 1000); - EXPECT_THAT(res, ContainerEq(t1)); + 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); +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); + 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()))); + 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); + 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())); + 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)); + 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]{}; +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); + 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(ctx.getBufferSize(), + Eq(ctx.containerSizeSerializedBytesCount(CARR_LENGTH) + + std::char_traits::length(t1))); - EXPECT_THAT(r1, StrEq(t1)); - EXPECT_THAT(r1, ContainerEq(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); + // 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)); + EXPECT_THAT(ctx2.getBufferSize(), + Eq(ctx2.containerSizeSerializedBytesCount(CARR_LENGTH))); + EXPECT_THAT(r1, StrEq(t1)); + EXPECT_THAT(r1, ContainerEq(t1)); } #ifndef NDEBUG -TEST(SerializeText, WhenCArrayNotNullterminatedThenAssert) { - SerializationContext ctx; - char16_t t1[CARR_LENGTH]{u"some text"}; - //make last character not nullterminated - t1[CARR_LENGTH-1] = 'x'; - EXPECT_DEATH(ctx.createSerializer().text<2>(t1), ""); +TEST(SerializeText, WhenCArrayNotNullterminatedThenAssert) +{ + SerializationContext ctx; + char16_t t1[CARR_LENGTH]{ u"some text" }; + // make last character not nullterminated + t1[CARR_LENGTH - 1] = 'x'; + EXPECT_DEATH(ctx.createSerializer().text<2>(t1), ""); } #endif -TEST(SerializeText, WhenContainerOrTextSizeIsMoreThanMaxThenInvalidDataError) { - SerializationContext ctx; - std::string tmp = "larger text then allowed"; - ctx.createSerializer().text1b(tmp,100); - ctx.createDeserializer().text1b(tmp, 10); - EXPECT_THAT(ctx.des->adapter().error(), Eq(bitsery::ReaderError::InvalidData)); +TEST(SerializeText, WhenContainerOrTextSizeIsMoreThanMaxThenInvalidDataError) +{ + SerializationContext ctx; + std::string tmp = "larger text then allowed"; + ctx.createSerializer().text1b(tmp, 100); + ctx.createDeserializer().text1b(tmp, 10); + EXPECT_THAT(ctx.des->adapter().error(), + Eq(bitsery::ReaderError::InvalidData)); } \ No newline at end of file diff --git a/tests/serialization_values.cpp b/tests/serialization_values.cpp index ea1768c..55f151c 100644 --- a/tests/serialization_values.cpp +++ b/tests/serialization_values.cpp @@ -1,112 +1,133 @@ -//MIT License +// MIT License // -//Copyright (c) 2017 Mindaugas Vinkelis +// 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: +// 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 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. +// 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::Eq; -template -bool SerializeDeserializeValue(const T& v) { - T res{}; - SerializationContext ctx; - ctx.createSerializer().value(v); - ctx.createDeserializer().value(res); - return v == res; +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, 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, 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, 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); +TEST(SerializeValues, ValueSizeOverload1Byte) +{ + int8_t v{ 54 }; + int8_t res; + constexpr size_t TSIZE = sizeof(v); - SerializationContext ctx; - ctx.createSerializer().value1b(v); - ctx.createDeserializer().value1b(res); + SerializationContext ctx; + ctx.createSerializer().value1b(v); + ctx.createDeserializer().value1b(res); - EXPECT_THAT(res, Eq(v)); - EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize())); + 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); +TEST(SerializeValues, ValueSizeOverload2Byte) +{ + int16_t v{ 54 }; + int16_t res; + constexpr size_t TSIZE = sizeof(v); - SerializationContext ctx; - ctx.createSerializer().value2b(v); - ctx.createDeserializer().value2b(res); + SerializationContext ctx; + ctx.createSerializer().value2b(v); + ctx.createDeserializer().value2b(res); - EXPECT_THAT(res, Eq(v)); - EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize())); + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize())); } -TEST(SerializeValues, ValueSizeOverload4Byte) { - float v{54.498f}; - float res; - constexpr size_t TSIZE = sizeof(v); +TEST(SerializeValues, ValueSizeOverload4Byte) +{ + float v{ 54.498f }; + float res; + constexpr size_t TSIZE = sizeof(v); - SerializationContext ctx; - ctx.createSerializer().value4b(v); - ctx.createDeserializer().value4b(res); + SerializationContext ctx; + ctx.createSerializer().value4b(v); + ctx.createDeserializer().value4b(res); - EXPECT_THAT(res, Eq(v)); - EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize())); + 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); +TEST(SerializeValues, ValueSizeOverload8Byte) +{ + int64_t v{ 54 }; + int64_t res; + constexpr size_t TSIZE = sizeof(v); - SerializationContext ctx; - ctx.createSerializer().value8b(v); - ctx.createDeserializer().value8b(res); + SerializationContext ctx; + ctx.createSerializer().value8b(v); + ctx.createDeserializer().value8b(res); - EXPECT_THAT(res, Eq(v)); - EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize())); + EXPECT_THAT(res, Eq(v)); + EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize())); }