13 Commits

Author SHA1 Message Date
Mindaugas Vinkelis
8a00183c80 release 5.2.0 2020-11-09 18:59:24 +02:00
Mindaugas Vinkelis
8a5e12a125 fixed typo 2020-11-07 12:07:14 +02:00
Michael Puskas
ee7bb2cb93 Fixed unknown-pragmas warnings on non-MSVC. (#69)
Changes:
Surrounded the MSVC-specific "disable warning" pragmas with MSVC
guards.
2020-11-07 12:05:36 +02:00
Mindaugas Vinkelis
d787680819 release v5.1.0 2020-06-08 14:32:18 +03:00
domgho
a519d333e2 Fix typo (#57) 2020-05-16 20:32:33 +03:00
Nick Renieris
826b8d4269 std::atomic support (#54) 2020-05-02 22:05:04 +03:00
Mindaugas Vinkelis
16f637da0d integer casts part3 2020-04-21 10:04:09 +03:00
tower120
9cade41dbb msvc warnings suppression (#47) 2020-04-21 08:38:16 +03:00
tower120
3dc5940c16 Integer casts. Part 2. (#41) 2020-04-21 08:35:32 +03:00
tower120
a544879b22 basic_ios <=> basic_ostream (#45)
basic_ios changed to basic_ostream and basic_istream
2020-04-16 21:48:49 +03:00
tower120
d47ee834e4 fix integer cast warnings. (#38) 2020-04-15 13:17:44 +03:00
Mindaugas Vinkelis
c556c75100 fixed some include paths 2020-04-15 12:46:42 +03:00
Mindaugas Vinkelis
541632fa9e VIP tutorial on Version extension 2020-02-06 20:00:42 +02:00
59 changed files with 774 additions and 244 deletions

View File

@@ -50,9 +50,9 @@ before_install:
- export CC=$CC_COMPILER
install:
- wget https://github.com/google/googletest/archive/release-1.8.0.tar.gz
- tar xf release-1.8.0.tar.gz
- cd googletest-release-1.8.0
- wget https://github.com/google/googletest/archive/release-1.10.0.tar.gz
- tar xf release-1.10.0.tar.gz
- cd googletest-release-1.10.0
- cmake -DBUILD_SHARED_LIBS=ON .
- make
- sudo make install

View File

@@ -1,3 +1,29 @@
# [5.2.0](https://github.com/fraillt/bitsery/compare/v5.1.0...v5.2.0) (2020-11-09)
### Features
* new extension **StdBitset**.
### Improvements
* removed unused variable warnings in release build, where `max_size` variable during serialization is ignored.
* removed unknown pragmas warnings for GCC/Clang (thanks to [Mmpuskas](https://github.com/Mmpuskas)).
# [5.1.0](https://github.com/fraillt/bitsery/compare/v5.0.3...v5.1.0) (2020-06-08)
### Features
* new extension **StdAtomic** (thanks for [VelocityRa](https://github.com/VelocityRa)).
### Improvements
* [examples](examples) no longer include bitsery in global namespace (removed `using namespace bitsery`).
* removed multiple warning regarding integer conversions (thanks to [tower120](https://github.com/tower120)).
* removed unnecessary `dynamic_cast` from BasicInput/OutputStreamAdapter (thanks to [tower120](https://github.com/tower120)).
* fixed some include paths, now you can basically to copy/paste bitsery include directory to your project without cmake support.
### Other notes
* added tutorial of how to write your own extension ([here](doc/tutorial/first_extension.md)).
* now gtest 1.10 is required if you want to build tests.
# [5.0.3](https://github.com/fraillt/bitsery/compare/v5.0.2...v5.0.3) (2020-01-29)
### Improvements

View File

@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.1)
project(bitsery
LANGUAGES CXX
VERSION 5.0.3)
VERSION 5.2.0)
#======== build options ===================================
option(BITSERY_BUILD_EXAMPLES "Build examples" OFF)

View File

@@ -64,11 +64,9 @@ void serialize(S& s, MyStruct& o) {
s.container4b(o.fs, 10);
}
using namespace bitsery;
using Buffer = std::vector<uint8_t>;
using OutputAdapter = OutputBufferAdapter<Buffer>;
using InputAdapter = InputBufferAdapter<Buffer>;
using OutputAdapter = bitsery::OutputBufferAdapter<Buffer>;
using InputAdapter = bitsery::InputBufferAdapter<Buffer>;
int main() {
MyStruct data{8941, MyEnum::V2, {15.0f, -8.5f, 0.045f}};
@@ -76,10 +74,10 @@ int main() {
Buffer buffer;
auto writtenSize = quickSerialization<OutputAdapter>(buffer, data);
auto state = quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
auto writtenSize = bitsery::quickSerialization<OutputAdapter>(buffer, data);
auto state = bitsery::quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
assert(state.first == ReaderError::NoError && state.second);
assert(state.first == bitsery::ReaderError::NoError && state.second);
assert(data.fs == res.fs && data.i == res.i && data.e == res.e);
}
```

View File

@@ -1,8 +1,8 @@
The grand plan for this tutorial is to learn how to serialize/deserialize any object efficiently in time and space, so you could focus on other, more interesting things.
This tutorial will cover these main topics:
* `Hello World` write one control flow for both: serialization and deserialization.
* `Composer` efficiently compose complex serialization flows.
* [Getting started](hello_world.md) with bitsery, and serialize/deserialize your first object.
* [Extend to your needs](first_extension.md) by enabling serialization/deserialization depending on version number.
* `Squeeze Me!` compress your data when you know what it stores.
* `Anything is Possible` extend library for custom container, compress geometry and more.
* `Little or Big` change endianness if you want best performance on PowerPC.

View File

@@ -1,3 +0,0 @@
*document in progress*
* explain why *value* and *object* is fundamental functions.
* write about *Growable* extension

View File

@@ -0,0 +1,67 @@
... TODO explain step-by-step what we need and how to get there
Instead I immediately provide implementation for an extension.
```cpp
#include "../details/adapter_common.h"
#include "../traits/core/traits.h"
namespace bitsery {
namespace ext {
template<size_t VERSION>
class Version {
public:
template<typename Ser, typename T, typename Fnc>
void serialize(Ser &ser, const T &v, Fnc &&fnc) const {
details::writeSize(ser.adapter(), VERSION);
fnc(ser, const_cast<T&>(v), VERSION);
}
template<typename Des, typename T, typename Fnc>
void deserialize(Des &des, T &v, Fnc &&fnc) const {
size_t version{};
details::readSize(des.adapter(), version, 0u, std::false_type{});
fnc(des, v, version);
}
};
}
namespace traits {
template<typename T, size_t V>
struct ExtensionTraits<ext::Version<V>, T> {
using TValue = T;
static constexpr bool SupportValueOverload = false;
static constexpr bool SupportObjectOverload = false;
static constexpr bool SupportLambdaOverload = true;
};
}
}
```
Adding such extension to the bitsery itself is impractical because it is very easy to implement, but at the same time it has a lot of customization options that actual user might require e.g.:
* how do you want to handle reading/writing version number? (in this case use compact representation as size, but do not check for errors if version number is too large)
* maybe you want to be able to set ReaderError, when version is larger than deserialization implementation handles. (we simply ignore this case and later we'll probably get reading error later anyway)
* or maybe you want to wrap object in `Growable` extension? so that you could ignore unknown fields in newer version of object.
Example of how to use this provided implementation:
```cpp
struct TypeV2 {
uint16_t x{};
uint16_t y{};
};
template <typename S>
void serialize(S& ser, TypeV2& obj) {
ser.ext(obj, bitsery::ext::Version<2u>{}, [](S& s, TypeV2&o, size_t version) {
s.value2b(o.x);
if (version == 2u) {
s.value2b(o.y);
}
});
}
```

View File

@@ -18,11 +18,9 @@ There's nothing to build or make - **bitsery** is header only.
#include <bitsery/traits/vector.h>
#include <bitsery/traits/string.h>
using namespace bitsery;
using Buffer = std::vector<uint8_t>;
using OutputAdapter = OutputBufferAdapter<Buffer>;
using InputAdapter = InputBufferAdapter<Buffer>;
using OutputAdapter = bitsery::OutputBufferAdapter<Buffer>;
using InputAdapter = bitsery::InputBufferAdapter<Buffer>;
```
@@ -62,7 +60,7 @@ void serialize(S& s, MyStruct& o) {
This example we choosed probably unfamiliar verbose syntax, so lets explain core functionality that you'll use all the time:
* **s.value4b(o.i);** serialize fundamental types (ints, floats, enums) value**4b** means, that data type is 4 bytes. If you use same code on different machines, if it compiles it means it is compatible.
* **s.text1b(o.str);** serialize text (null-terminated) of char type, if you use *wchar* then you would write *text2b*.
* **s.text1b(o.str);** serialize text (null-terminated) of char type, if you use *wchar* then you would write *text2b* or *text4b* depending on the OS platform.
* **s.container4b(o.fs, 100);** serializes any container of fundamental types of size 4bytes, **100** is max size of container.
**Bitsery** is designed to be save with untrusted (malicious) data from network, so for dynamic containers you always need to provide max possible size available, to avoid buffer-overflow attacks.
**text** didn't had this max size specified, because it was serializing fixed size container.
@@ -76,8 +74,8 @@ Create buffer and use helper functions for serialization and deserialization.
```cpp
Buffer buffer;
auto writtenSize = quickSerialization(OutputAdapter{buffer}, data);
auto state = quickDeserialization(InputAdapter{buffer.begin(), writtenSize}, res);
auto writtenSize = bitsery::quickSerialization(OutputAdapter{buffer}, data);
auto state = bitsery::quickDeserialization(InputAdapter{buffer.begin(), writtenSize}, res);
```
These helper functions use default configuration *bitsery::DefaultConfig*
@@ -93,11 +91,9 @@ deserialization state has two properties, error code and bool that indicates if
#include <bitsery/traits/vector.h>
#include <bitsery/traits/string.h>
using namespace bitsery;
using Buffer = std::vector<uint8_t>;
using OutputAdapter = OutputBufferAdapter<Buffer>;
using InputAdapter = InputBufferAdapter<Buffer>;
using OutputAdapter = bitsery::OutputBufferAdapter<Buffer>;
using InputAdapter = bitsery::InputBufferAdapter<Buffer>;
struct MyStruct {
uint32_t i;
@@ -110,17 +106,17 @@ void serialize(S& s, MyStruct& o) {
s.value4b(o.i);
s.text1b(o.str);
s.container4b(o.fs, 100);
};
}
int main() {
MyStruct data{8941, "hello", {15.0f, -8.5f, 0.045f}};
MyStruct res{};
Buffer buffer;
auto writtenSize = quickSerialization(OutputAdapter{buffer}, data);
auto state = quickDeserialization(InputAdapter{buffer.begin(), writtenSize}, res);
auto writtenSize = bitsery::quickSerialization(OutputAdapter{buffer}, data);
auto state = bitsery::quickDeserialization(InputAdapter{buffer.begin(), writtenSize}, res);
assert(state.first == ReaderError::NoError && state.second);
assert(state.first == bitsery::ReaderError::NoError && state.second);
assert(data.fs == res.fs && data.i == res.i && std::strcmp(data.str, res.str) == 0);
}
```

View File

@@ -22,12 +22,10 @@ void serialize(S& s, MyStruct& o) {
s.container4b(o.fs, 10);//resizable containers also requires maxSize, to make it safe from buffer-overflow attacks
}
using namespace bitsery;
//some helper types
using Buffer = std::vector<uint8_t>;
using OutputAdapter = OutputBufferAdapter<Buffer>;
using InputAdapter = InputBufferAdapter<Buffer>;
using OutputAdapter = bitsery::OutputBufferAdapter<Buffer>;
using InputAdapter = bitsery::InputBufferAdapter<Buffer>;
int main() {
//set some random data
@@ -39,12 +37,12 @@ int main() {
//use quick serialization function,
//it will use default configuration to setup all the nesessary steps
//and serialize data to container
auto writtenSize = quickSerialization<OutputAdapter>(buffer, data);
auto writtenSize = bitsery::quickSerialization<OutputAdapter>(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 = quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
auto state = bitsery::quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
assert(state.first == ReaderError::NoError && state.second);
assert(state.first == bitsery::ReaderError::NoError && state.second);
assert(data.fs == res.fs && data.i == res.i && data.e == res.e);
}

View File

@@ -41,12 +41,10 @@ namespace MyTypes {
}
}
using namespace bitsery;
//use fixed-size buffer
using Buffer = std::array<uint8_t, 10000>;
using OutputAdapter = OutputBufferAdapter<Buffer>;
using InputAdapter = InputBufferAdapter<Buffer>;
using OutputAdapter = bitsery::OutputBufferAdapter<Buffer>;
using InputAdapter = bitsery::InputBufferAdapter<Buffer>;
int main() {
//set some random data
@@ -55,10 +53,10 @@ int main() {
//create buffer to store data to
Buffer buffer{};
auto writtenSize = quickSerialization<OutputAdapter>(buffer, data);
auto writtenSize = bitsery::quickSerialization<OutputAdapter>(buffer, data);
MyTypes::Monster res{};
auto state = quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
auto state = bitsery::quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
assert(state.first == ReaderError::NoError && state.second);
assert(state.first == bitsery::ReaderError::NoError && state.second);
}

View File

@@ -23,12 +23,10 @@ struct MyStruct {
};
using namespace bitsery;
//some helper types
using Buffer = std::vector<uint8_t>;
using OutputAdapter = OutputBufferAdapter<Buffer>;
using InputAdapter = InputBufferAdapter<Buffer>;
using OutputAdapter = bitsery::OutputBufferAdapter<Buffer>;
using InputAdapter = bitsery::InputBufferAdapter<Buffer>;
int main() {
//set some random data
@@ -37,10 +35,10 @@ int main() {
//serialization, deserialization flow is unchanged as in basic usage
Buffer buffer;
auto writtenSize = quickSerialization<OutputAdapter>(buffer, data);
auto writtenSize = bitsery::quickSerialization<OutputAdapter>(buffer, data);
auto state = quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
auto state = bitsery::quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
assert(state.first == ReaderError::NoError && state.second);
assert(state.first == bitsery::ReaderError::NoError && state.second);
assert(data.fs == res.fs && data.i == res.i && data.e == res.e);
}

View File

@@ -29,27 +29,24 @@ void serialize(S& s, MyStruct& o) {
using MyTuple = std::tuple<float, MyStruct>;
using MyVariant = std::variant<int64_t, MyTuple, MyStruct>;
// for convenience
using namespace bitsery;
// define default serialize function for MyVariant, so that we could use quickSerialization/Deserialization functions
template<typename S>
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, ext::StdVariant{
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, ext::StdTuple{
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);}
ext::OverloadValue<float, 4>{},
bitsery::ext::OverloadValue<float, 4>{},
// 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
ext::OverloadExtValue<int64_t, 8, ext::CompactValue>{},
bitsery::ext::OverloadExtValue<int64_t, 8, bitsery::ext::CompactValue>{},
// 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)
@@ -59,7 +56,7 @@ void serialize(S& s, MyVariant& o) {
[](S& s, MyStruct& o) {
s.value4b(o.f);
s.container(o.v, 1000, [](S& s, int32_t& v) {
s.ext4b(v, ext::CompactValue{});
s.ext4b(v, bitsery::ext::CompactValue{});
});
},
// NOTE.
@@ -78,8 +75,8 @@ void serialize(S& s, MyVariant& o) {
//some helper types
using Buffer = std::vector<uint8_t>;
using OutputAdapter = OutputBufferAdapter<Buffer>;
using InputAdapter = InputBufferAdapter<Buffer>;
using OutputAdapter = bitsery::OutputBufferAdapter<Buffer>;
using InputAdapter = bitsery::InputBufferAdapter<Buffer>;
int main() {
@@ -93,13 +90,13 @@ int main() {
//use quick serialization function,
//it will use default configuration to setup all the nesessary steps
//and serialize data to container
auto writtenSize = quickSerialization<OutputAdapter>(buffer, data);
auto writtenSize = bitsery::quickSerialization<OutputAdapter>(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 = quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
auto state = bitsery::quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
assert(state.first == ReaderError::NoError && state.second);
assert(state.first == bitsery::ReaderError::NoError && state.second);
assert(data == res);
}
#else

View File

@@ -67,10 +67,9 @@ using Context = std::tuple<int, std::pair<uint32_t, uint32_t>>;
//use fixed-size buffer
using Buffer = std::vector<uint8_t>;
using namespace bitsery;
// define adapter types,
using OutputAdapter = OutputBufferAdapter<Buffer>;
using InputAdapter = InputBufferAdapter<Buffer>;
using OutputAdapter = bitsery::OutputBufferAdapter<Buffer>;
using InputAdapter = bitsery::InputBufferAdapter<Buffer>;
int main() {
@@ -90,10 +89,10 @@ int main() {
//create buffer to store data to
Buffer buffer{};
auto writtenSize = quickSerialization(ctx, OutputAdapter{buffer}, data);
auto writtenSize = bitsery::quickSerialization(ctx, OutputAdapter{buffer}, data);
MyTypes::GameState res{};
auto state = quickDeserialization(ctx, InputAdapter{buffer.begin(), writtenSize}, res);
auto state = bitsery::quickDeserialization(ctx, InputAdapter{buffer.begin(), writtenSize}, res);
assert(state.first == ReaderError::NoError && state.second);
assert(state.first == bitsery::ReaderError::NoError && state.second);
}

View File

@@ -19,8 +19,6 @@ void serialize(S& s, MyStruct& o) {
s.value8b(o.f);
}
using namespace bitsery;
int main() {
//set some random data
MyStruct data{8941, MyEnum::V2, 0.045};
@@ -35,7 +33,7 @@ int main() {
}
//we cannot use quick serialization function, because streams cannot use writtenBytesCount method
Serializer<OutputBufferedStreamAdapter> ser{s};
bitsery::Serializer<bitsery::OutputBufferedStreamAdapter> ser{s};
ser.object(data);
//flush to writer
ser.adapter().flush();
@@ -50,8 +48,8 @@ int main() {
//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 = quickDeserialization<InputStreamAdapter>(s, res);
auto state = bitsery::quickDeserialization<bitsery::InputStreamAdapter>(s, res);
assert(state.first == ReaderError::NoError && state.second);
assert(state.first == bitsery::ReaderError::NoError && state.second);
assert(data.f == res.f && data.i == res.i && data.e == res.e);
}

View File

@@ -68,12 +68,10 @@ namespace MyTypes {
}
}
using namespace bitsery;
//use fixed-size buffer
using Buffer = std::array<uint8_t, 10000>;
using OutputAdapter = OutputBufferAdapter<Buffer>;
using InputAdapter = InputBufferAdapter<Buffer>;
using OutputAdapter = bitsery::OutputBufferAdapter<Buffer>;
using InputAdapter = bitsery::InputBufferAdapter<Buffer>;
int main() {
//set some random data
@@ -84,11 +82,11 @@ int main() {
//create buffer to store data to
Buffer buffer{};
//since we're using different configuration, we cannot use quickSerialization function.
auto writtenSize = quickSerialization<OutputAdapter>(buffer, data);
auto writtenSize = bitsery::quickSerialization<OutputAdapter>(buffer, data);
MyTypes::Monster res{};
//deserialize
auto state = quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
auto state = bitsery::quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
assert(state.first == ReaderError::NoError && state.second);
assert(state.first == bitsery::ReaderError::NoError && state.second);
}

View File

@@ -78,13 +78,10 @@ namespace bitsery {
struct SelectSerializeFnc<MultipleInheritance>:UseNonMemberFnc {};
}
using namespace bitsery;
//some helper types
using Buffer = std::vector<uint8_t>;
using Writer = OutputBufferAdapter<Buffer>;
using Reader = InputBufferAdapter<Buffer>;
using Writer = bitsery::OutputBufferAdapter<Buffer>;
using Reader = bitsery::InputBufferAdapter<Buffer>;
int main() {
@@ -95,13 +92,13 @@ int main() {
Buffer buf{};
ext::InheritanceContext ctx1;
auto writtenSize = quickSerialization(ctx1, Writer{buf}, data);
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};
ext::InheritanceContext ctx2;
auto state = quickDeserialization(ctx2, Reader{buf.begin(), writtenSize}, res);
assert(state.first == ReaderError::NoError && state.second);
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);
}

View File

@@ -30,12 +30,10 @@ public:
}
};
using namespace bitsery;
//some helper types
using Buffer = std::vector<uint8_t>;
using Writer = OutputBufferAdapter<Buffer>;
using Reader = InputBufferAdapter<Buffer>;
using Writer = bitsery::OutputBufferAdapter<Buffer>;
using Reader = bitsery::InputBufferAdapter<Buffer>;
int main() {
@@ -49,16 +47,16 @@ int main() {
//we cant use quick (de)serialization helper methods, because we ant to serialize container directly
//create writer and serialize container
Serializer<Writer> ser{buffer};
bitsery::Serializer<Writer> ser{buffer};
ser.container(data, 10);
ser.adapter().flush();
//create reader and deserialize container
Deserializer<Reader> des{buffer.begin(), ser.adapter().writtenBytesCount()};
bitsery::Deserializer<Reader> des{buffer.begin(), ser.adapter().writtenBytesCount()};
des.container(res, 10);
//check if everything went ok
assert(des.adapter().error() == ReaderError::NoError && des.adapter().isCompletedSuccessfully());
assert(des.adapter().error() == bitsery::ReaderError::NoError && des.adapter().isCompletedSuccessfully());
assert(res == data);
}

View File

@@ -78,12 +78,10 @@ private:
}
};
using namespace bitsery;
//some helper types
using Buffer = std::vector<uint8_t>;
using Writer = OutputBufferAdapter<Buffer>;
using Reader = InputBufferAdapter<Buffer>;
using Writer = bitsery::OutputBufferAdapter<Buffer>;
using Reader = bitsery::InputBufferAdapter<Buffer>;
//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:
@@ -114,7 +112,7 @@ int main() {
size_t writtenSize{};
//in order to use pointers, we need to pass pointer linking context serializer/deserializer
{
ext::PointerLinkingContext ctx{};
bitsery::ext::PointerLinkingContext ctx{};
writtenSize = quickSerialization(ctx, Writer{buffer}, data);
//make sure that pointer linking context is valid
@@ -125,10 +123,10 @@ int main() {
Test1Data res{};
{
ext::PointerLinkingContext ctx{};
bitsery::ext::PointerLinkingContext ctx{};
auto state = quickDeserialization(ctx, Reader{buffer.begin(), writtenSize}, res);
//check if everything went find
assert(state.first == ReaderError::NoError && state.second);
assert(state.first == bitsery::ReaderError::NoError && state.second);
//also check for dangling pointers, after deserialization
assert(ctx.isValid());
}

View File

@@ -181,23 +181,21 @@ namespace bitsery {
// also it automatically ensures, that classes is registered in the same order for serialization and deserialization
using MyPolymorphicClassesForRegistering = bitsery::ext::PolymorphicClassesList<Shape>;
//use bitsery namespace for convenience
using namespace bitsery;
//some helper types
using Buffer = std::vector<uint8_t>;
using Writer = OutputBufferAdapter<Buffer>;
using Reader = InputBufferAdapter<Buffer>;
using Writer = bitsery::OutputBufferAdapter<Buffer>;
using Reader = bitsery::InputBufferAdapter<Buffer>;
//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<ext::PointerLinkingContext, ext::PolymorphicContext<ext::StandardRTTI>>;
using TContext = std::tuple<
bitsery::ext::PointerLinkingContext,
bitsery::ext::PolymorphicContext<bitsery::ext::StandardRTTI>>;
//NOTE:
// RTTI can be customizable, if you can't use dynamic_cast and typeid, and have 'custom' solution
using MySerializer = Serializer<Writer, TContext>;
using MyDeserializer = Deserializer<Reader, TContext>;
using MySerializer = bitsery::Serializer<Writer, TContext>;
using MyDeserializer = bitsery::Deserializer<Reader, TContext>;
//checks if deserialized data is equal
void assertSameShapes(const SomeShapes &data, const SomeShapes &res) {
@@ -257,7 +255,7 @@ int main() {
//deserialize our data
MyDeserializer des{ctx, buffer.begin(), writtenSize};
des.object(res);
assert(des.adapter().error() == ReaderError::NoError && des.adapter().isCompletedSuccessfully());
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,

View File

@@ -48,7 +48,7 @@ namespace bitsery {
};
InputBufferAdapter(TIterator beginIt, TIterator endIt)
:InputBufferAdapter(beginIt, std::distance(beginIt, endIt)) {
:InputBufferAdapter(beginIt, static_cast<size_t>(std::distance(beginIt, endIt))) {
}
InputBufferAdapter(const InputBufferAdapter&) = delete;
@@ -103,6 +103,7 @@ namespace bitsery {
}
private:
using diff_t = typename std::iterator_traits<TIterator>::difference_type;
template <size_t SIZE>
void readInternalValue(TValue *data) {
@@ -115,17 +116,17 @@ namespace bitsery {
template <size_t SIZE>
void readInternalValueChecked(TValue *data, std::false_type) {
const auto newOffset = _currOffset + SIZE;
const size_t newOffset = _currOffset + SIZE;
assert(newOffset <= _endReadOffset);
std::copy_n(_beginIt + _currOffset, SIZE, data);
std::copy_n(_beginIt + static_cast<diff_t>(_currOffset), SIZE, data);
_currOffset = newOffset;
}
template <size_t SIZE>
void readInternalValueChecked(TValue *data, std::true_type) {
const auto newOffset = _currOffset + SIZE;
const size_t newOffset = _currOffset + SIZE;
if (newOffset <= _endReadOffset) {
std::copy_n(_beginIt + _currOffset, SIZE, data);
std::copy_n(_beginIt + static_cast<diff_t>(_currOffset), SIZE, data);
_currOffset = newOffset;
} else {
//set everything to zeros
@@ -136,16 +137,16 @@ namespace bitsery {
}
void readInternalBufferChecked(TValue *data, size_t size, std::false_type) {
const auto newOffset = _currOffset + size;
const size_t newOffset = _currOffset + size;
assert(newOffset <= _endReadOffset);
std::copy_n(_beginIt + _currOffset, size, data);
std::copy_n(_beginIt + static_cast<diff_t>(_currOffset), size, data);
_currOffset = newOffset;
}
void readInternalBufferChecked(TValue *data, size_t size, std::true_type) {
const auto newOffset = _currOffset + size;
const size_t newOffset = _currOffset + size;
if (newOffset <= _endReadOffset) {
std::copy_n(_beginIt + _currOffset, size, data);
std::copy_n(_beginIt + static_cast<diff_t>(_currOffset), size, data);
_currOffset = newOffset;
} else {
//set everything to zeros
@@ -229,6 +230,7 @@ namespace bitsery {
private:
using TResizable = std::integral_constant<bool, traits::ContainerTraits<Buffer>::isResizable>;
using diff_t = typename std::iterator_traits<TIterator>::difference_type;
template <size_t SIZE>
void writeInternalValue(const TValue *data) {
@@ -259,9 +261,9 @@ namespace bitsery {
template <size_t SIZE>
void writeInternalValueImpl(const TValue *data, std::true_type) {
const auto newOffset = _currOffset + SIZE;
const size_t newOffset = _currOffset + SIZE;
if (newOffset <= _bufferSize) {
std::copy_n(data, SIZE, _beginIt + _currOffset);
std::copy_n(data, SIZE, _beginIt + static_cast<diff_t>(_currOffset));
_currOffset = newOffset;
} else {
traits::BufferAdapterTraits<Buffer>::increaseBufferSize(*_buffer);
@@ -271,9 +273,9 @@ namespace bitsery {
}
void writeInternalBufferImpl(const TValue *data, const size_t size, std::true_type) {
const auto newOffset = _currOffset + size;
const size_t newOffset = _currOffset + size;
if (newOffset <= _bufferSize) {
std::copy_n(data, size, _beginIt + _currOffset);
std::copy_n(data, size, _beginIt + static_cast<diff_t>(_currOffset));
_currOffset = newOffset;
} else {
traits::BufferAdapterTraits<Buffer>::increaseBufferSize(*_buffer);
@@ -301,16 +303,16 @@ namespace bitsery {
template <size_t SIZE>
void writeInternalValueImpl(const TValue *data, std::false_type) {
const auto newOffset = _currOffset + SIZE;
const size_t newOffset = _currOffset + SIZE;
assert(newOffset <= _bufferSize);
std::copy_n(data, SIZE, _beginIt + _currOffset);
std::copy_n(data, SIZE, _beginIt + static_cast<diff_t>(_currOffset));
_currOffset = newOffset;
}
void writeInternalBufferImpl(const TValue *data, size_t size, std::false_type) {
const auto newOffset = _currOffset + size;
const size_t newOffset = _currOffset + size;
assert(newOffset <= _bufferSize);
std::copy_n(data, size, _beginIt + _currOffset);
std::copy_n(data, size, _beginIt + static_cast<diff_t>(_currOffset));
_currOffset = newOffset;
}

View File

@@ -93,7 +93,7 @@ namespace bitsery {
}
void readChecked(TValue* data, size_t size, std::true_type) {
if (size - static_cast<size_t>(_ios->rdbuf()->sgetn(data, size)) != _zeroIfNoErrors) {
if (size - static_cast<size_t>(_ios->rdbuf()->sgetn(data, static_cast<std::streamsize>(size))) != _zeroIfNoErrors) {
*data = {};
if (_zeroIfNoErrors == 0) {
error(_ios->rdstate() == std::ios_base::badbit
@@ -104,7 +104,7 @@ namespace bitsery {
}
void readChecked(TValue* data, size_t size, std::false_type) {
_ios->rdbuf()->sgetn(data , size);
_ios->rdbuf()->sgetn(data , static_cast<std::streamsize>(size));
}
std::basic_ios<TChar, CharTraits>* _ios;
@@ -119,8 +119,8 @@ namespace bitsery {
using TConfig = Config;
using TValue = TChar;
BasicOutputStreamAdapter(std::basic_ios<TChar, CharTraits>& ostream)
:_ios{std::addressof(ostream)} {}
BasicOutputStreamAdapter(std::basic_ostream<TChar, CharTraits>& ostream)
:_ostream{std::addressof(ostream)} {}
void currentWritePos(size_t ) {
static_assert(std::is_void<TChar>::value, "setting write position is not supported with StreamAdapter");
@@ -132,8 +132,7 @@ namespace bitsery {
}
void flush() {
if (auto ostream = dynamic_cast<std::basic_ostream<TChar, CharTraits>*>(_ios))
ostream->flush();
_ostream->flush();
}
size_t writtenBytesCount() const {
@@ -146,14 +145,14 @@ namespace bitsery {
template <size_t SIZE>
void writeInternalValue(const TValue* data) {
_ios->rdbuf()->sputn( data , SIZE );
_ostream->rdbuf()->sputn( data , SIZE );
}
void writeInternalBuffer(const TValue* data, size_t size) {
_ios->rdbuf()->sputn( data , size );
_ostream->rdbuf()->sputn( data , size );
}
std::basic_ios<TChar, CharTraits>* _ios;
std::basic_ostream<TChar, CharTraits>* _ostream;
};
template <typename TChar, typename Config, typename CharTraits, typename TBuffer = std::array<TChar, 256>>
@@ -169,14 +168,14 @@ namespace bitsery {
using TValue = TChar;
//bufferSize is used when buffer is dynamically allocated
BasicBufferedOutputStreamAdapter(std::basic_ios<TChar, CharTraits>& ostream, size_t bufferSize = 256)
:_ios(std::addressof(ostream)),
BasicBufferedOutputStreamAdapter(std::basic_ostream<TChar, CharTraits>& 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 atleast one value fits to buffer.
// buffer size must be atleast 16, because writeIntervalValue expect that at least one value fits to buffer.
assert(_bufferSize >= 16);
}
@@ -185,7 +184,7 @@ namespace bitsery {
BasicBufferedOutputStreamAdapter& operator = (const BasicBufferedOutputStreamAdapter&) = delete;
BasicBufferedOutputStreamAdapter(BasicBufferedOutputStreamAdapter&& rhs)
: _ios{rhs._ios},
: _ostream{rhs._ostream},
_buf{std::move(rhs._buf)},
_beginIt{std::begin(_buf)},
_currOffset{rhs._currOffset},
@@ -194,7 +193,7 @@ namespace bitsery {
};
BasicBufferedOutputStreamAdapter& operator = (BasicBufferedOutputStreamAdapter&& rhs) {
_ios = rhs._ios;
_ostream = rhs._ostream;
_buf = std::move(rhs._buf);
_beginIt = std::begin(_buf);
_currOffset = rhs._currOffset;
@@ -213,8 +212,7 @@ namespace bitsery {
void flush() {
writeBufferToStream();
if (auto ostream = dynamic_cast<std::basic_ostream<TChar, CharTraits>*>(_ios))
ostream->flush();
_ostream->flush();
}
size_t writtenBytesCount() const {
@@ -225,6 +223,7 @@ namespace bitsery {
private:
using TResizable = std::integral_constant<bool, traits::ContainerTraits<TBuffer>::isResizable>;
using diff_t = typename std::iterator_traits<BufferIt>::difference_type;
template <size_t SIZE>
void writeInternalValue(const TValue* data) {
@@ -233,24 +232,24 @@ namespace bitsery {
writeBufferToStream();
newOffset = SIZE;
}
std::copy_n(data, SIZE, _beginIt + _currOffset);
std::copy_n(data, SIZE, _beginIt + static_cast<diff_t>(_currOffset));
_currOffset = newOffset;
}
void writeInternalBuffer(const TValue* data, size_t size) {
const auto newOffset = _currOffset + size;
if (newOffset <= _bufferSize) {
std::copy_n(data, size, _beginIt + _currOffset);
std::copy_n(data, size, _beginIt + static_cast<diff_t>(_currOffset));
_currOffset = newOffset;
} else {
writeBufferToStream();
// write buffer directly to stream
_ios->rdbuf()->sputn(data, size);
_ostream->rdbuf()->sputn(data, size);
}
}
void writeBufferToStream() {
_ios->rdbuf()->sputn(std::addressof(*_beginIt), _currOffset);
_ostream->rdbuf()->sputn(std::addressof(*_beginIt), static_cast<std::streamsize>(_currOffset));
_currOffset = 0;
}
@@ -265,7 +264,7 @@ namespace bitsery {
_bufferSize = traits::ContainerTraits<Buffer>::size(_buf);
}
std::basic_ios<TChar, CharTraits>* _ios;
std::basic_ostream<TChar, CharTraits>* _ostream;
TBuffer _buf;
BufferIt _beginIt;
size_t _currOffset;
@@ -273,22 +272,24 @@ namespace bitsery {
};
template <typename TChar, typename Config, typename CharTraits>
class BasicIOStreamAdapter:public BasicInputStreamAdapter<TChar, Config, CharTraits>, public BasicOutputStreamAdapter<TChar, Config, CharTraits> {
class BasicIOStreamAdapter
: public BasicInputStreamAdapter<TChar, Config, CharTraits>
, public BasicOutputStreamAdapter<TChar, Config, CharTraits>
{
public:
using TValue = TChar;
//both bases contain reference to same iostream, so no need to do anything
BasicIOStreamAdapter(std::basic_ios<TChar, CharTraits>& iostream)
:BasicInputStreamAdapter<TChar, Config, CharTraits>{iostream},
BasicOutputStreamAdapter<TChar, Config, CharTraits>{iostream} {
}
BasicIOStreamAdapter(std::basic_iostream<TChar, CharTraits>& iostream)
:BasicInputStreamAdapter<TChar, Config, CharTraits>{iostream}
,BasicOutputStreamAdapter<TChar, Config, CharTraits>{iostream}
{}
};
//helper types for most common implementations for std streams
using OutputStreamAdapter = BasicOutputStreamAdapter<char, DefaultConfig, std::char_traits<char>>;
using InputStreamAdapter = BasicInputStreamAdapter<char, DefaultConfig, std::char_traits<char>>;
using IOStreamAdapter = BasicIOStreamAdapter<char, DefaultConfig, std::char_traits<char>>;
using InputStreamAdapter = BasicInputStreamAdapter<char, DefaultConfig, std::char_traits<char>>;
using IOStreamAdapter = BasicIOStreamAdapter<char, DefaultConfig, std::char_traits<char>>;
using OutputBufferedStreamAdapter = BasicBufferedOutputStreamAdapter<char, DefaultConfig, std::char_traits<char>>;
}

View File

@@ -25,8 +25,8 @@
#define BITSERY_BITSERY_H
#define BITSERY_MAJOR_VERSION 5
#define BITSERY_MINOR_VERSION 0
#define BITSERY_PATCH_VERSION 3
#define BITSERY_MINOR_VERSION 2
#define BITSERY_PATCH_VERSION 0
#define BITSERY_QUOTE_MACRO(name) #name
#define BITSERY_BUILD_VERSION_STR(major,minor, patch) \

View File

@@ -25,7 +25,7 @@
#define BITSERY_BRIEF_SYNTAX_H
#include "details/serialization_common.h"
#include "bitsery/details/brief_syntax_common.h"
#include "details/brief_syntax_common.h"
namespace bitsery {

View File

@@ -25,7 +25,7 @@
#define BITSERY_BRIEF_SYNTAX_TYPE_STD_ARRAY_H
#include "../traits/array.h"
#include "bitsery/details/brief_syntax_common.h"
#include "../details/brief_syntax_common.h"
namespace bitsery {
template<typename S, typename T, size_t N>

View File

@@ -0,0 +1,35 @@
//MIT License
//
//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:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
#ifndef BITSERY_BRIEF_SYNTAX_TYPE_STD_ATOMIC_H
#define BITSERY_BRIEF_SYNTAX_TYPE_STD_ATOMIC_H
#include "../ext/std_atomic.h"
namespace bitsery {
template<typename S, typename T>
void serialize(S &s, std::atomic<T> &obj) {
s.template ext<sizeof(T)>(obj, ext::StdAtomic{});
}
}
#endif //BITSERY_BRIEF_SYNTAX_TYPE_STD_ATOMIC_H

View File

@@ -25,7 +25,7 @@
#define BITSERY_BRIEF_SYNTAX_TYPE_STD_DEQUE_H
#include "../traits/deque.h"
#include "bitsery/details/brief_syntax_common.h"
#include "../details/brief_syntax_common.h"
namespace bitsery {
template<typename S, typename T, typename Allocator>

View File

@@ -25,7 +25,7 @@
#define BITSERY_BRIEF_SYNTAX_TYPE_STD_FORWARD_LIST_H
#include "../traits/forward_list.h"
#include "bitsery/details/brief_syntax_common.h"
#include "../details/brief_syntax_common.h"
namespace bitsery {
template<typename S, typename T, typename Allocator>

View File

@@ -25,7 +25,7 @@
#define BITSERY_BRIEF_SYNTAX_TYPE_STD_LIST_H
#include "../traits/list.h"
#include "bitsery/details/brief_syntax_common.h"
#include "../details/brief_syntax_common.h"
namespace bitsery {
template<typename S, typename T, typename Allocator>

View File

@@ -25,7 +25,7 @@
#define BITSERY_BRIEF_SYNTAX_TYPE_STD_STRING_H
#include "../traits/string.h"
#include "bitsery/details/brief_syntax_common.h"
#include "../details/brief_syntax_common.h"
namespace bitsery {
template<typename S, typename CharT, typename Traits, typename Allocator>

View File

@@ -25,7 +25,7 @@
#define BITSERY_BRIEF_SYNTAX_TYPE_STD_VECTOR_H
#include "../traits/vector.h"
#include "bitsery/details/brief_syntax_common.h"
#include "../details/brief_syntax_common.h"
namespace bitsery {
template<typename S, typename T, typename Allocator>

View File

@@ -130,7 +130,8 @@ namespace bitsery {
template<typename T>
void readBitsInternal(T &v, size_t size) {
auto bitsLeft = size;
T res{};
using TFast = typename FastType<T>::type;
TFast res{};
while (bitsLeft > 0) {
auto bits = (std::min)(bitsLeft, details::BitsSize<UnsignedValue>::value);
if (m_scratchBits < bits) {
@@ -141,12 +142,12 @@ namespace bitsery {
}
auto shiftedRes =
static_cast<T>(m_scratch & ((static_cast<ScratchType>(1) << bits) - 1)) << (size - bitsLeft);
res |= shiftedRes;
res = static_cast<TFast>(res | static_cast<TFast>(shiftedRes));
m_scratch >>= bits;
m_scratchBits -= bits;
bitsLeft -= bits;
}
v = res;
v = static_cast<T>(res);
}
void handleAlignErrors(ScratchType value, std::true_type) {
@@ -443,8 +444,10 @@ namespace bitsery {
void procContainer(It first, It last, std::true_type) {
using TValue = typename std::decay<decltype(*first)>::type;
using TIntegral = typename details::IntegralFromFundamental<TValue>::TValue;
if (first != last)
this->_adapter.template readBuffer<VSIZE>(reinterpret_cast<TIntegral*>(&(*first)), std::distance(first, last));
if (first != last){
const auto distance = std::distance(first, last);
this->_adapter.template readBuffer<VSIZE>(reinterpret_cast<TIntegral*>(&(*first)), static_cast<size_t>(distance));
}
}
//process by calling functions
@@ -465,7 +468,8 @@ namespace bitsery {
void procText(T& str, size_t length) {
auto begin = std::begin(str);
//end of string, not end of container
auto end = std::next(begin, length);
using diff_t = typename std::iterator_traits<decltype(begin)>::difference_type;
auto end = std::next(begin, static_cast<diff_t>(length));
procContainer<VSIZE>(begin, end, std::integral_constant<bool, traits::ContainerTraits<T>::isContiguous>{});
//null terminated character at the end
if (traits::TextTraits<T>::addNUL)

View File

@@ -81,9 +81,8 @@ namespace bitsery {
void handleReadMaxSize(Reader&, size_t&, size_t, std::false_type) {
}
template <typename Writter>
void writeSize(Writter& w, const size_t size) {
template <typename Writer>
void writeSize(Writer& w, const size_t size) {
if (size < 0x80u) {
w.template writeBytes<1>(static_cast<uint8_t>(size));
} else {
@@ -125,7 +124,7 @@ namespace bitsery {
}
static uint16_t exec(uint16_t value) {
return (value & 0x00ff) << 8 | (value & 0xff00) >> 8;
return static_cast<uint16_t>((value & 0x00ff) << 8 | (value & 0xff00) >> 8);
}
static uint8_t exec(uint8_t value) {
@@ -139,17 +138,24 @@ namespace bitsery {
using UT = typename std::conditional<TSize == 1, uint8_t,
typename std::conditional<TSize == 2, uint16_t,
typename std::conditional<TSize == 4, uint32_t, uint64_t>::type>::type>::type;
return SwapImpl::exec(static_cast<UT>(value));
return static_cast<TValue>(SwapImpl::exec(static_cast<UT>(value)));
}
/**
* endianness utils
*/
//add test data in separate struct, because some compilers only support constexpr functions with return-only body
// 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,
@@ -176,9 +182,55 @@ namespace bitsery {
template<>
struct ScratchType<uint8_t> {
using type = uint16_t;
using type = uint_fast16_t;
};
template<typename T>
struct FastType {
using type = T;
};
template<>
struct FastType<uint8_t> {
using type = uint_fast8_t;
};
template<>
struct FastType<uint16_t> {
using type = uint_fast16_t;
};
template<>
struct FastType<uint32_t> {
using type = uint_fast32_t;
};
template<>
struct FastType<uint64_t> {
using type = uint_fast64_t;
};
template<>
struct FastType<int8_t> {
using type = int_fast8_t;
};
template<>
struct FastType<int16_t> {
using type = int_fast16_t;
};
template<>
struct FastType<int32_t> {
using type = int_fast32_t;
};
template<>
struct FastType<int64_t> {
using type = int_fast64_t;
};
/**
* output/input adapter base that handles endianness
*/
@@ -290,7 +342,8 @@ namespace bitsery {
template<typename T>
void swapDataBits(T *v, size_t count, std::true_type) {
std::for_each(v, std::next(v, count), [](T &x) { x = details::swap(x); });
using diff_t = typename std::iterator_traits<T*>::difference_type;
std::for_each(v, std::next(v, static_cast<diff_t>(count)), [](T &x) { x = details::swap(x); });
}
template<typename T>

View File

@@ -91,18 +91,19 @@ namespace bitsery {
template<typename T>
SameSizeUnsigned<T> zigZagEncode(const T &v, std::true_type) const {
return (v << 1) ^ (v >> (BitsSize<T>::value - 1));
return static_cast<SameSizeUnsigned<T>>((v << 1) ^ (v >> (BitsSize<T>::value - 1)));
}
template<typename TResult, typename TUnsigned>
TResult zigZagDecode(TUnsigned v, std::true_type) const {
return (v >> 1) ^ (~(v & 1) + 1); // same as -(v & 1), but no warning on VisualStudio
return static_cast<TResult>((v >> 1) ^ (~(v & 1) + 1)); // same as -(v & 1), but no warning on VisualStudio
}
// write/read bytes one by one
template<typename Writer, typename T>
void writeBytes(Writer &w, const T &v) const {
auto val = v;
using TFast = typename FastType<T>::type;
auto val= static_cast<TFast>(v);
while(val > 0x7Fu) {
w.template writeBytes<1>(static_cast<uint8_t>(val | 0x80u));
val >>=7u;
@@ -112,13 +113,16 @@ namespace bitsery {
template<bool CheckErrors, typename Reader, typename T>
void readBytes(Reader &r, T &v) const {
using TFast = typename FastType<T>::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);
v += static_cast<T>(b1 & 0x7Fu) << i;
tmp += static_cast<TFast>(b1 & 0x7Fu) << i;
}
v = static_cast<T>(tmp);
handleReadOverflow<Reader, T>(r, i, b1,
std::integral_constant<bool, CheckOverflow && CheckErrors>{});
}

View File

@@ -74,8 +74,10 @@ namespace bitsery {
d.ext(index, ext::ValueRange<size_t>{0u, traits::ContainerTraits<TContainer>::size(_values)});
if (_alignBeforeData)
d.adapter().align();
if (index)
obj = *std::next(std::begin(_values), index-1);
if (index) {
using TDiff = typename std::iterator_traits<decltype(std::begin(_values))>::difference_type;
obj = static_cast<T>(*std::next(std::begin(_values), static_cast<TDiff>(index-1)));
}
else
fnc(d, obj);
}

View File

@@ -25,7 +25,7 @@
#include <unordered_set>
#include "../traits/core/traits.h"
#include "bitsery/ext/utils/memory_resource.h"
#include "../ext/utils/memory_resource.h"
namespace bitsery {

View File

@@ -0,0 +1,65 @@
//MIT License
//
//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:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
#ifndef BITSERY_EXT_STD_ATOMIC_H
#define BITSERY_EXT_STD_ATOMIC_H
#include "../traits/core/traits.h"
#include <atomic>
namespace bitsery {
namespace ext {
class StdAtomic {
public:
template<typename Ser, typename T, typename Fnc>
void serialize(Ser& ser, const std::atomic<T>& obj, Fnc&& fnc) const {
auto res = obj.load();
fnc(ser, res);
}
template<typename Des, typename T, typename Fnc>
void deserialize(Des& des, std::atomic<T>& obj, Fnc&& fnc) const {
T res{};
fnc(des, res);
obj.store(res);
}
};
}
namespace traits {
template<typename T>
struct ExtensionTraits<ext::StdAtomic, std::atomic<T>> {
using TValue = T;
static constexpr bool SupportValueOverload = true;
static constexpr bool SupportObjectOverload = false;
static constexpr bool SupportLambdaOverload = false;
};
}
}
#endif //BITSERY_EXT_STD_ATOMIC_H

View File

@@ -0,0 +1,148 @@
//MIT License
//
//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:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
#ifndef BITSERY_EXT_STD_BITSET_H
#define BITSERY_EXT_STD_BITSET_H
#include "../traits/core/traits.h"
#include <bitset>
namespace bitsery {
namespace ext {
class StdBitset {
public:
template<typename Ser, typename Fnc, size_t N>
void serialize(Ser &ser, const std::bitset<N> &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<uint8_t>(data));
}
} else {
// more performant way
auto data = obj.to_ullong();
for(size_t i = 0u; i < BYTES; ++i) {
ser.value1b(static_cast<uint8_t>(data & 0xFF));
data >>= 1;
}
}
if (LEFTOVER > 0) {
serializeLeftover(ser.adapter(), obj, N - LEFTOVER, N);
}
}
template<typename Des, typename Fnc, size_t N>
void deserialize(Des &des, std::bitset<N> &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) {
deserializeLeftover(des.adapter(), obj, N - LEFTOVER, N);
}
}
private:
template<typename Writer, size_t N>
void serializeLeftover(Writer& w, const std::bitset<N> &obj, size_t from, size_t to) const {
serializeLeftoverImpl(w, obj, from, to, std::integral_constant<bool, Writer::BitPackingEnabled> {});
}
template<typename Writer, size_t N>
void serializeLeftoverImpl(Writer& w, const std::bitset<N> &obj, size_t from, size_t to, std::integral_constant<bool, false>) const {
auto data = 0;
for (auto i = from; i < to; ++i) {
data += obj[i] << (i - from);
}
w.template writeBytes<1>(static_cast<uint8_t>(data));
}
template<typename Writer, size_t N>
void serializeLeftoverImpl(Writer& w, const std::bitset<N> &obj, size_t from, size_t to, std::integral_constant<bool, true>) const {
for (auto i = from; i < to; ++i) {
w.writeBits(obj[i], 1);
}
}
template<typename Reader, size_t N>
void deserializeLeftover(Reader& r, std::bitset<N> &obj, size_t from, size_t to) const {
deserializeLeftoverImpl(r, obj, from, to, std::integral_constant<bool, Reader::BitPackingEnabled> {});
}
template<typename Reader, size_t N>
void deserializeLeftoverImpl(Reader& r, std::bitset<N> &obj, size_t from, size_t to, std::integral_constant<bool, false>) const {
uint8_t data = 0u;
r.template readBytes<1>(data);
for (auto i = from; i < to; ++i) {
obj[i] = data & (1u << (i - from));
}
}
template<typename Reader, size_t N>
void deserializeLeftoverImpl(Reader& r, std::bitset<N> &obj, size_t from, size_t to, std::integral_constant<bool, true>) const {
for (auto i = from; i < to; ++i) {
uint8_t res = 0u;
r.readBits(res, 1);
obj[i] = res;
}
}
};
}
namespace traits {
template<size_t N>
struct ExtensionTraits<ext::StdBitset, std::bitset<N>> {
using TValue = void;
static constexpr bool SupportValueOverload = false;
static constexpr bool SupportObjectOverload = true;
static constexpr bool SupportLambdaOverload = false;
};
}
}
#endif //BITSERY_EXT_STD_BITSET_H

View File

@@ -45,7 +45,7 @@ namespace bitsery {
};
// default implementation for MemResourceBase using new and delete
class MemResourceNewDelete : public MemResourceBase {
class MemResourceNewDelete final: public MemResourceBase {
public:
inline void* allocate(size_t bytes, size_t /*alignment*/, size_t /*typeId*/) final {
return (::operator new(bytes));

View File

@@ -71,7 +71,7 @@ namespace bitsery {
StdPolyAlloc<PointerSharedStateBase> alloc{_memResource};
alloc.deallocate(data, 1);
}
MemResourceBase* _memResource;
MemResourceBase* _memResource = nullptr;
};
//PLC info is internal classes for serializer, and deserializer
@@ -376,12 +376,12 @@ namespace bitsery {
std::true_type, OwnershipType<PointerOwnershipType::Owner>) const {
const auto& ctx = des.template context<TPolymorphicContext<RTTI>>();
ctx.deserialize(des, TPtrManager<T>::getPtr(obj),
[&obj, this, memResource](
[&obj, memResource](
const std::shared_ptr<PolymorphicHandlerBase>& handler) {
TPtrManager<T>::createPolymorphic(obj, memResource, handler);
return TPtrManager<T>::getPtr(obj);
},
[&obj, memResource, this](const std::shared_ptr<PolymorphicHandlerBase>& handler) {
[&obj, memResource](const std::shared_ptr<PolymorphicHandlerBase>& handler) {
TPtrManager<T>::destroyPolymorphic(obj, memResource, handler);
});
ptrInfo.processOwner(TPtrManager<T>::getPtr(obj));
@@ -414,7 +414,7 @@ namespace bitsery {
obj, memResource, handler);
return TPtrManager<T>::getPtr(obj);
},
[&obj, memResource, this](const std::shared_ptr<PolymorphicHandlerBase>& handler) {
[&obj, memResource](const std::shared_ptr<PolymorphicHandlerBase>& handler) {
TPtrManager<T>::destroyPolymorphic(obj, memResource, handler);
});
if (!ptrInfo.sharedState)

View File

@@ -121,8 +121,8 @@ namespace bitsery {
details::SameSizeUnsigned<T> getRangeValue(const T &v, const RangeSpec<T> &r) {
using VT = details::SameSizeUnsigned<T>;
const VT maxUint = (static_cast<VT>(1) << r.bitsRequired) - 1;
const auto ratio = (v - r.min) / (r.max - r.min);
return static_cast<VT>(ratio * maxUint);
const T ratio = (v - r.min) / (r.max - r.min);
return static_cast<VT>(ratio * static_cast<T>(maxUint));
}
template<typename T, typename std::enable_if<std::is_integral<T>::value>::type * = nullptr>
@@ -141,7 +141,7 @@ namespace bitsery {
using UIT = details::SameSizeUnsigned<T>;
const auto intRep = reinterpret_cast<UIT &>(v);
const UIT maxUint = (static_cast<UIT>(1) << r.bitsRequired) - 1;
v = r.min + (static_cast<T>(intRep) / maxUint) * (r.max - r.min);
v = r.min + (static_cast<T>(intRep) / static_cast<T>(maxUint)) * (r.max - r.min);
}
template<typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>

View File

@@ -120,8 +120,8 @@ namespace bitsery {
template<typename T>
void writeBitsInternal(const T &v, size_t size) {
constexpr size_t valueSize = details::BitsSize<UnsignedType>::value;
auto value = v;
auto bitsLeft = size;
T value = v;
size_t bitsLeft = size;
while (bitsLeft > 0) {
auto bits = (std::min)(bitsLeft, valueSize);
_scratch |= static_cast<ScratchType>( value ) << _scratchBits;
@@ -132,7 +132,7 @@ namespace bitsery {
_scratch >>= valueSize;
_scratchBits -= valueSize;
value >>= valueSize;
value = static_cast<T>(value >> valueSize);
}
bitsLeft -= bits;
}
@@ -289,6 +289,7 @@ namespace bitsery {
static_assert(traits::ContainerTraits<T>::isResizable,
"use container(const T&, Fnc) overload without `maxSize` for static containers");
auto size = traits::ContainerTraits<T>::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>(fnc));
@@ -302,6 +303,7 @@ namespace bitsery {
"use container(const T&) overload without `maxSize` for static containers");
static_assert(VSIZE > 0, "");
auto size = traits::ContainerTraits<T>::size(obj);
(void)maxSize; // unused in release
assert(size <= maxSize);
details::writeSize(this->_adapter, size);
@@ -315,6 +317,7 @@ namespace bitsery {
static_assert(traits::ContainerTraits<T>::isResizable,
"use container(const T&) overload without `maxSize` for static containers");
auto size = traits::ContainerTraits<T>::size(obj);
(void)maxSize; // unused in release
assert(size <= maxSize);
details::writeSize(this->_adapter, size);
procContainer(std::begin(obj), std::end(obj));
@@ -452,11 +455,13 @@ namespace bitsery {
//process text,
template<size_t VSIZE, typename T>
void procText(const T& str, size_t maxSize) {
auto length = traits::TextTraits<T>::length(str);
const size_t length = traits::TextTraits<T>::length(str);
(void)maxSize; // unused in release
assert((length + (traits::TextTraits<T>::addNUL ? 1u : 0u)) <= maxSize);
details::writeSize(this->_adapter, length);
auto begin = std::begin(str);
procContainer<VSIZE>(begin, std::next(begin, length), std::integral_constant<bool, traits::ContainerTraits<T>::isContiguous>{});
using diff_t = typename std::iterator_traits<decltype(begin)>::difference_type;
procContainer<VSIZE>(begin, std::next(begin, static_cast<diff_t>(length)), std::integral_constant<bool, traits::ContainerTraits<T>::isContiguous>{});
}
//process object types

View File

@@ -56,6 +56,8 @@ namespace bitsery {
resizeImpl(container, size, std::is_default_constructible<TValue>{});
}
private:
using diff_t = typename T::difference_type;
static void resizeImpl(T& container, size_t size, std::true_type) {
container.resize(size);
}
@@ -65,7 +67,7 @@ namespace bitsery {
container.push_back(::bitsery::Access::create<TValue>());
}
if (oldSize > newSize) {
container.erase(std::next(std::begin(container), newSize), std::end(container));
container.erase(std::next(std::begin(container), static_cast<diff_t>(newSize)), std::end(container));
}
}
@@ -85,7 +87,7 @@ namespace bitsery {
static void increaseBufferSize(T& container) {
//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<size_t>(container.size() * 1.5 + 128);
auto newSize = static_cast<size_t>(static_cast<double>(container.size()) * 1.5) + 128;
//make data cache friendly
newSize -= newSize % 64;//64 is cache line size
container.resize((std::max)(newSize, container.capacity()));

View File

@@ -44,6 +44,7 @@ namespace bitsery {
resizeImpl(container, size, std::is_default_constructible<TValue>{});
}
private:
using diff_t = typename std::forward_list<T, Allocator>::difference_type;
static void resizeImpl(std::forward_list<T, Allocator>& container, size_t size, std::true_type) {
container.resize(size);
}
@@ -55,7 +56,7 @@ namespace bitsery {
if (oldSize > newSize) {
//erase_after must have atleast one element to work
if (newSize > 0)
container.erase_after(std::next(std::begin(container), newSize-1));
container.erase_after(std::next(std::begin(container), static_cast<diff_t>(newSize-1)));
else
container.clear();
}

View File

@@ -23,7 +23,7 @@
cmake_minimum_required(VERSION 3.10)
project(bitsery_tests CXX)
find_package(GTest 1.8 REQUIRED)
find_package(GTest 1.10 REQUIRED)
if (NOT TARGET Bitsery::bitsery)
message(FATAL_ERROR "Bitsery::bitsery alias not set. Please generate CMake from bitsery root directory.")
@@ -39,7 +39,10 @@ foreach (TestFile ${TestSourceFiles})
add_executable(${TestName} ${TestFile})
target_link_libraries(${TestName} PRIVATE GTest::Main Bitsery::bitsery)
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(${TestName} PRIVATE -Wextra -Wno-missing-braces -Wpedantic -Weffc++ -Wno-c++14-extensions)
target_compile_options(${TestName} PRIVATE -Wextra -Wconversion -Wno-missing-braces -Wpedantic -Weffc++ -Werror)
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_options(${TestName} PRIVATE -Wno-c++14-extensions)
endif()
gtest_discover_tests(${TestName})

View File

@@ -286,7 +286,7 @@ template <typename TConfig>
class InputAll: public AdapterConfig<TConfig> {
};
TYPED_TEST_CASE(InputAll, AdapterInputTypes);
TYPED_TEST_SUITE(InputAll, AdapterInputTypes,);
TYPED_TEST(InputAll, SettingMultipleErrorsAlwaysReturnsFirstError) {
@@ -455,7 +455,7 @@ template <typename TConfig>
class OutputAll: public AdapterConfig<TConfig> {
};
TYPED_TEST_CASE(OutputAll, AdapterOutputTypes);
TYPED_TEST_SUITE(OutputAll, AdapterOutputTypes,);
TYPED_TEST(OutputAll, CanBeMoveConstructedAndMoveAssigned) {
auto w = this->config.createWriter();
@@ -500,7 +500,7 @@ using BufferedAdapterInternalBufferTypes = ::testing::Types<
std::string
>;
TYPED_TEST_CASE(OutputStreamBuffered, BufferedAdapterInternalBufferTypes);
TYPED_TEST_SUITE(OutputStreamBuffered, BufferedAdapterInternalBufferTypes,);
TYPED_TEST(OutputStreamBuffered, WhenInternalBufferIsFullThenWriteBufferToStream) {
uint8_t x{};

View File

@@ -22,6 +22,7 @@
#include <bitsery/brief_syntax.h>
#include <bitsery/brief_syntax/array.h>
#include <bitsery/brief_syntax/atomic.h>
#include <bitsery/brief_syntax/chrono.h>
#include <bitsery/brief_syntax/deque.h>
#include <bitsery/brief_syntax/forward_list.h>
@@ -39,16 +40,19 @@
#include <bitsery/brief_syntax/tuple.h>
#include <bitsery/brief_syntax/variant.h>
#else
#if defined(_MSC_VER)
/*#if defined(_MSC_VER)
#pragma message("tuple and variant only works with c++17")
#else
#warning "tuple and variant only works with c++17"
#endif
#endif*/
#endif
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <atomic>
#include <utility>
using testing::Eq;
TEST(BriefSyntax, FundamentalTypesAndBool) {
@@ -151,6 +155,14 @@ T procBriefSyntax(const T& testData) {
return res;
}
template<typename T>
T&& procBriefSyntaxRvalue(T&& init_value, const T& testData) {
SerializationContext ctx;
ctx.createSerializer()(testData);
ctx.createDeserializer()(init_value);
return std::move(init_value);
}
template<typename T>
T procBriefSyntaxWithMaxSize(const T& testData) {
SerializationContext ctx;
@@ -411,6 +423,21 @@ TEST(BriefSyntax, StdTimePoint) {
EXPECT_TRUE(procBriefSyntax(data) == data);
}
TEST(BriefSyntax, StdAtomic) {
std::atomic<int32_t> atm0{54654};
EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic<int32_t>{}, atm0) == atm0);
std::atomic<bool> atm1{false};
EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic<bool>{}, atm1) == atm1);
std::atomic<bool> atm2{true};
EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic<bool>{}, atm2) == atm2);
std::atomic<uint16_t> atm3;
atm3.store(0x1337);
EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic<uint16_t>{}, atm3).load() == 0x1337);
}
#if __cplusplus > 201402L
TEST(BriefSyntax, StdTuple) {

View File

@@ -42,7 +42,7 @@ using FixedContainer = std::array<uint8_t, 100>;
using ContainerTypes = ::testing::Types<FixedContainer,NonFixedContainer>;
TYPED_TEST_CASE(DataWriting, ContainerTypes);
TYPED_TEST_SUITE(DataWriting, ContainerTypes,);
static constexpr size_t DATA_SIZE = 14u;

View File

@@ -96,7 +96,7 @@ using SequenceContainersWithArthmeticTypes = ::testing::Types<
std::forward_list<int>,
std::deque<unsigned short>>;
TYPED_TEST_CASE(SerializeContainerDynamicSizeArthmeticTypes, SequenceContainersWithArthmeticTypes);
TYPED_TEST_SUITE(SerializeContainerDynamicSizeArthmeticTypes, SequenceContainersWithArthmeticTypes,);
TYPED_TEST(SerializeContainerDynamicSizeArthmeticTypes, Values) {
SerializationContext ctx{};
@@ -125,7 +125,7 @@ TYPED_TEST(SerializeContainerDynamicSizeArthmeticTypes, CustomFunctionIncrements
});
//decrement result by 1, before comparing for eq
for (auto &v:this->res)
v -= 1;
v = static_cast<TValue>(v-1);
EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx)));
EXPECT_THAT(this->res, ContainerEq(this->src));
@@ -151,7 +151,7 @@ using SerializeContainerDynamicSizeWithCompositeTypes = ::testing::Types<
std::vector<MyStruct1>,
std::list<MyStruct2>>;
TYPED_TEST_CASE(SerializeContainerDynamicSizeCompositeTypes, SerializeContainerDynamicSizeWithCompositeTypes);
TYPED_TEST_SUITE(SerializeContainerDynamicSizeCompositeTypes, SerializeContainerDynamicSizeWithCompositeTypes,);
TYPED_TEST(SerializeContainerDynamicSizeCompositeTypes, DefaultSerializeFunction) {
SerializationContext ctx{};
@@ -166,7 +166,6 @@ TYPED_TEST(SerializeContainerDynamicSizeCompositeTypes, DefaultSerializeFunction
TYPED_TEST(SerializeContainerDynamicSizeCompositeTypes, CustomFunctionThatDoNothing) {
SerializationContext ctx{};
using TValue = typename TestFixture::TValue;
ctx.createSerializer().container(this->src, 1000, EmptyFtor{});
ctx.createDeserializer().container(this->res, 1000, EmptyFtor{});
@@ -189,7 +188,7 @@ using StaticContainersWithIntegralTypes = ::testing::Types<
std::array<int16_t, 4>,
int16_t[4]>;
TYPED_TEST_CASE(SerializeContainerFixedSizeArithmeticTypes, StaticContainersWithIntegralTypes);
TYPED_TEST_SUITE(SerializeContainerFixedSizeArithmeticTypes, StaticContainersWithIntegralTypes,);
TYPED_TEST(SerializeContainerFixedSizeArithmeticTypes, ArithmeticValues) {
using Container = typename TestFixture::TContainer;
@@ -214,7 +213,7 @@ class SerializeContainerFixedSizeCompositeTypes : public SerializeContainerFixed
using StaticContainersWithCompositeTypes = ::testing::Types<
std::array<MyStruct1, 4>, MyStruct1[4]>;
TYPED_TEST_CASE(SerializeContainerFixedSizeCompositeTypes, StaticContainersWithCompositeTypes);
TYPED_TEST_SUITE(SerializeContainerFixedSizeCompositeTypes, StaticContainersWithCompositeTypes,);
TYPED_TEST(SerializeContainerFixedSizeCompositeTypes, DefaultSerializationFunction) {
using Container = typename TestFixture::TContainer;
@@ -269,6 +268,5 @@ TEST_P(SerializeContainer, SizeHasVariableLength) {
EXPECT_THAT(ctx.getBufferSize(), Eq(ctx.containerSizeSerializedBytesCount(src.size())));
}
//last comma is to suppress error that otherwise can be suppressed by clang/gcc with -Wgnu-zero-variadic-macro-arguments
INSTANTIATE_TEST_CASE_P(LargeContainerSize, SerializeContainer, ::testing::Values(0x01, 0x80, 0x4000),);
INSTANTIATE_TEST_SUITE_P(LargeContainerSize, SerializeContainer, ::testing::Values(0x01, 0x80, 0x4000));

View File

@@ -37,17 +37,17 @@ using bitsery::EndiannessType;
// helper function, that gets value filled with specified number of bits
template <typename TValue>
TValue getValue(bool isPositive, size_t significantBits) {
TValue v = isPositive ? 0 : -1;
TValue v = isPositive ? 0 : static_cast<TValue>(-1);
if (significantBits == 0)
return v;
using TUnsigned = typename std::make_unsigned<TValue>::type;
TUnsigned mask = {};
mask = ~mask; // invert shiftByBits
mask = static_cast<TUnsigned>(~mask); // invert shiftByBits
auto shiftBy = bitsery::details::BitsSize<TValue>::value - significantBits;
mask >>= shiftBy;
mask = static_cast<TUnsigned>(mask >> shiftBy);
//cast to unsigned when applying mask
return (TUnsigned)v ^ mask;
return v ^ static_cast<TValue>(mask);
}
// helper function, that serialize and return deserialized value
@@ -118,7 +118,7 @@ using AllValueSizesTestCases = ::testing::Types<
TC<int64_t, false, BigEndianConfig>
>;
TYPED_TEST_CASE(SerializeExtensionCompactValueCorrectness, AllValueSizesTestCases);
TYPED_TEST_SUITE(SerializeExtensionCompactValueCorrectness, AllValueSizesTestCases,);
TYPED_TEST(SerializeExtensionCompactValueCorrectness, TestDifferentSizeValues) {
using TCase = typename TestFixture::TestCase;
@@ -202,7 +202,7 @@ using RequiredBytesTestCases = ::testing::Types<
SizeTC<int64_t, false, 63,10>
>;
TYPED_TEST_CASE(SerializeExtensionCompactValueRequiredBytes, RequiredBytesTestCases);
TYPED_TEST_SUITE(SerializeExtensionCompactValueRequiredBytes, RequiredBytesTestCases,);
TYPED_TEST(SerializeExtensionCompactValueRequiredBytes, Test) {
using TCase = typename TestFixture::TestCase;

View File

@@ -176,7 +176,7 @@ TEST(SerializeExtensionEntropy, CustomFunctionNotEntropyEncodedWithAlignBeforeDa
});
EXPECT_THAT(res, Eq(v));
auto bitsForIndex = 8; //because aligned
auto bitsForIndex = 8u; //because aligned
EXPECT_THAT(ctx.getBufferSize(), Eq((bitsForIndex + rangeForValue.getRequiredBits() * 2 - 1) / 8 + 1 ));
}

View File

@@ -87,7 +87,7 @@ struct MultipleVirtualInheritance : Derived1, Derived2 {
MultipleVirtualInheritance() = default;
MultipleVirtualInheritance(uint8_t x_, uint8_t y1_, uint8_t y2_, uint8_t z_) {
MultipleVirtualInheritance(uint8_t x_, uint8_t y1_, uint8_t y2_, int8_t z_) {
x = x_;
y1 = y1_;
y2 = y2_;

View File

@@ -0,0 +1,119 @@
//MIT License
//
//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:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
#include <bitsery/ext/std_bitset.h>
#include <bitsery/ext/value_range.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
using StdBitset = bitsery::ext::StdBitset;
using ValueRange = bitsery::ext::ValueRange<int>;
using testing::Eq;
TEST(SerializeExtensionStdBitset, BitsetSmallerThanULongLong) {
SerializationContext ctx;
std::bitset<9> data;
data[2] = true;
data[8] = true;
std::bitset<9> res;
ctx.createSerializer().ext(data, StdBitset{});
ctx.createDeserializer().ext(res, StdBitset{});
EXPECT_THAT(res, Eq(data));
}
TEST(SerializeExtensionStdBitset, BitsetSmallerThanULongLong2) {
SerializationContext ctx;
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));
}
TEST(SerializeExtensionStdBitset, BitsetLargerThanULongLong) {
SerializationContext ctx;
std::bitset<200> data;
data[1] = 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));
}
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{};
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});
});
EXPECT_THAT(res, Eq(data));
EXPECT_THAT(other_res, Eq(other_data));
EXPECT_THAT(ctx.getBufferSize(), Eq(2));
}
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{};
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});
});
EXPECT_THAT(res, Eq(data));
EXPECT_THAT(other_res, Eq(other_data));
EXPECT_THAT(ctx.getBufferSize(), Eq(26));
}

View File

@@ -89,7 +89,7 @@ using SerializeExtensionStdMapTypes = ::testing::Types<
std::multimap<int32_t ,int64_t>
>;
TYPED_TEST_CASE(SerializeExtensionStdMap, SerializeExtensionStdMapTypes);
TYPED_TEST_SUITE(SerializeExtensionStdMap, SerializeExtensionStdMapTypes,);
namespace bitsery {

View File

@@ -121,9 +121,9 @@ TEST(SerializeExtensionStdOptional, NoAlignAfterStateWriteRead) {
}
#else
#if defined(_MSC_VER)
/*#if defined(_MSC_VER)
#pragma message("Tests for StdOptional requires C++17")
#else
#warning "Tests for StdOptional requires C++17"
#endif
#endif*/
#endif

View File

@@ -44,7 +44,7 @@ using SerializeExtensionStdSetTypes = ::testing::Types<
std::set<int32_t>,
std::multiset<int32_t>>;
TYPED_TEST_CASE(SerializeExtensionStdSet, SerializeExtensionStdSetTypes);
TYPED_TEST_SUITE(SerializeExtensionStdSet, SerializeExtensionStdSetTypes,);
TYPED_TEST(SerializeExtensionStdSet, ValuesSyntaxDifferentSetTypes) {
SerializationContext ctx1;

View File

@@ -71,7 +71,7 @@ void serialize(S& s, Derived& o) {
}
struct MoreDerived : Derived {
int8_t z{};
uint8_t z{};
MoreDerived() = default;
@@ -197,13 +197,13 @@ using TestingWithNonPolymorphicTypes = ::testing::Types<
UniquePtrTest,
SharedPtrTest>;
TYPED_TEST_CASE(SerializeExtensionStdSmartPtrNonPolymorphicType, TestingWithNonPolymorphicTypes);
TYPED_TEST_SUITE(SerializeExtensionStdSmartPtrNonPolymorphicType, TestingWithNonPolymorphicTypes,);
using TestingWithPolymorphicTypes = ::testing::Types<
UniquePtrTest,
SharedPtrTest>;
TYPED_TEST_CASE(SerializeExtensionStdSmartPtrPolymorphicType, TestingWithPolymorphicTypes);
TYPED_TEST_SUITE(SerializeExtensionStdSmartPtrPolymorphicType, TestingWithPolymorphicTypes,);
TYPED_TEST(SerializeExtensionStdSmartPtrNonPolymorphicType, Data0Result0) {
using Ptr = typename TestFixture::template TPtr<MyStruct1>;

View File

@@ -119,9 +119,9 @@ TEST(SerializeExtensionStdTuple, NonDefaultConstructable) {
}
#else
#if defined(_MSC_VER)
/*#if defined(_MSC_VER)
#pragma message("Tests for StdTuple requires C++17")
#else
#warning "Tests for StdTuple requires C++17"
#endif
#endif*/
#endif

View File

@@ -168,9 +168,9 @@ TEST(SerializeExtensionStdVariant, CorrectlyHandleMonoState) {
}
#else
#if defined(_MSC_VER)
/*#if defined(_MSC_VER)
#pragma message("Tests for StdVariant requires C++17")
#else
#warning "Tests for StdVariant requires C++17"
#endif
#endif*/
#endif