mirror of
https://github.com/fraillt/bitsery.git
synced 2026-06-08 08:13:56 +00:00
maxSize archive modifying function now works with extensions
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# [4.0.0](https://github.com/fraillt/bitsery/compare/v3.0.0...v4.0.0) (2017-10-02)
|
# [4.0.0](https://github.com/fraillt/bitsery/compare/v3.0.0...v4.0.0) (2017-10-13)
|
||||||
|
|
||||||
I feel that current library public API is complete, and should be stable for long time.
|
I feel that current library public API is complete, and should be stable for long time.
|
||||||
Most changes was made to improve performance or/and make library usage easier.
|
Most changes was made to improve performance or/and make library usage easier.
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -27,16 +27,18 @@ All cross-platform requirements are enforced at compile time, so serialized data
|
|||||||
|
|
||||||
## Why to use bitsery
|
## Why to use bitsery
|
||||||
|
|
||||||
Look at the numbers and features list, and decide yourself. *(benchmarked on Ubuntu with GCC 7.1)*
|
Look at the numbers and features list, and decide yourself.
|
||||||
|
|
||||||
| | serialize | deserialize | data size | executable size |
|
| | binary size | data size | serialize | deserialize |
|
||||||
|-----------------------------------------------------------|-----------|-------------|-------------|-----------------|
|
|------------------------------|-------------|-----------|-------------|-------------|
|
||||||
| flatbuffers | 1852 ms. | 777 ms. | 27252 bytes | 74544 bytes |
|
| **test_bitsery** | 64704 | **7565** | **1229 ms** | **1086 ms** |
|
||||||
| cereal | 1069 ms. | 1385 ms. | 20208 bytes | 72336 bytes |
|
| **test_bitsery_compression** | 44000 | **4784** | **1370 ms** | **2463 ms** |
|
||||||
| bitsery | 808 ms. | 737 ms. | 14803 bytes | 69784 bytes |
|
| test_yas | 63864 | 11311 | 1616 ms | 1712 ms |
|
||||||
| bitsery fixed-size buffer | 297 ms. | 738 ms. | 14803 bytes | 69928 bytes |
|
| test_yas_compression | 72688 | 8523 | 2387 ms | 2890 ms |
|
||||||
| bitsery optimized serialization flow | 686 ms. | 997 ms. | 6601 bytes | 69320 bytes |
|
| test_cereal | 74848 | 11261 | 6708 ms | 6799 ms |
|
||||||
| bitsery optimized serialization flow + fixed-size buffer | 446 ms. | 996 ms. | 6601 bytes | 69464 bytes |
|
| test_flatbuffers | 67032 | 16100 | 8793 ms | 3028 ms |
|
||||||
|
|
||||||
|
*benchmarked on Ubuntu with GCC 7.1.0, more details can be found [here](https://github.com/fraillt/cpp_serializers_benchmark.git)*
|
||||||
|
|
||||||
If still not convinced read more in library [motivation](doc/design/README.md) section.
|
If still not convinced read more in library [motivation](doc/design/README.md) section.
|
||||||
|
|
||||||
|
|||||||
59
examples/file_stream.cpp
Normal file
59
examples/file_stream.cpp
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#include <bitsery/bitsery.h>
|
||||||
|
//in order to work with streams include stream adapter
|
||||||
|
#include <bitsery/adapter/stream.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
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 <typename S>
|
||||||
|
void serialize(S& s, MyStruct& o) {
|
||||||
|
s.value4b(o.i);
|
||||||
|
s.value2b(o.e);
|
||||||
|
s.value8b(o.f);
|
||||||
|
};
|
||||||
|
|
||||||
|
using namespace bitsery;
|
||||||
|
|
||||||
|
//some helper types
|
||||||
|
using Stream = std::fstream;
|
||||||
|
using IOAdapter = IOStreamAdapter;
|
||||||
|
|
||||||
|
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";
|
||||||
|
Stream s{fileName, s.binary | s.trunc | s.out};
|
||||||
|
if (!s.is_open()) {
|
||||||
|
std::cout << "cannot open " << fileName << " for writing\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//use same quick serialization function
|
||||||
|
//streams do not return written size
|
||||||
|
quickSerialization<IOAdapter>(s, data);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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<IOAdapter>(s, res);
|
||||||
|
|
||||||
|
assert(state.first == ReaderError::NoError && state.second);
|
||||||
|
assert(data.f == res.f && data.i == res.i && data.e == res.e);
|
||||||
|
}
|
||||||
45
examples/flexible_assert_linux_x64.cpp
Normal file
45
examples/flexible_assert_linux_x64.cpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#include <bitsery/bitsery.h>
|
||||||
|
#include <bitsery/adapter/buffer.h>
|
||||||
|
#include <bitsery/flexible.h>
|
||||||
|
#include <bitsery/flexible/vector.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct MyStruct {
|
||||||
|
int i;
|
||||||
|
unsigned short s;
|
||||||
|
std::vector<long> vl;
|
||||||
|
long long ll;
|
||||||
|
|
||||||
|
template <typename S>
|
||||||
|
void serialize(S& s) {
|
||||||
|
//now we can use flexible syntax with
|
||||||
|
//member function has same name as parameter
|
||||||
|
s.archive(this->s, i, vl, ll);
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
using namespace bitsery;
|
||||||
|
|
||||||
|
//some helper types
|
||||||
|
using Buffer = std::vector<uint8_t>;
|
||||||
|
using OutputAdapter = OutputBufferAdapter<Buffer>;
|
||||||
|
using InputAdapter = InputBufferAdapter<Buffer>;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
//this will only work on linux or mac x64
|
||||||
|
bitsery::assertFundamentalTypeSizes<2,4,8,8>();
|
||||||
|
//set some random data
|
||||||
|
MyStruct data{8941, 3, {15l, -8l, 045l}, 8459845ll};
|
||||||
|
MyStruct res{};
|
||||||
|
|
||||||
|
//serialization, deserialization flow is unchanged as in basic usage
|
||||||
|
Buffer buffer;
|
||||||
|
auto writtenSize = quickSerialization<OutputAdapter>(buffer, data);
|
||||||
|
|
||||||
|
auto state = quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
|
||||||
|
|
||||||
|
assert(state.first == ReaderError::NoError && state.second);
|
||||||
|
assert(data.vl == res.vl && data.s == res.s && data.i == res.i && data.ll == res.ll);
|
||||||
|
}
|
||||||
47
examples/flexible_syntax.cpp
Normal file
47
examples/flexible_syntax.cpp
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#include <bitsery/bitsery.h>
|
||||||
|
#include <bitsery/adapter/buffer.h>
|
||||||
|
//include flexible header, to use flexible syntax
|
||||||
|
#include <bitsery/flexible.h>
|
||||||
|
//we also need additional traits to work with container types,
|
||||||
|
//instead of including <bitsery/traits/vector.h> for vector traits, now we also need traits to work with flexible types.
|
||||||
|
//so include everything from <bitsery/flexible/...> instead of <bitsery/traits/...>
|
||||||
|
//otherwise we'll get static assert error, saying to define serialize function.
|
||||||
|
#include <bitsery/flexible/vector.h>
|
||||||
|
|
||||||
|
enum class MyEnum:uint16_t { V1,V2,V3 };
|
||||||
|
struct MyStruct {
|
||||||
|
uint32_t i;
|
||||||
|
MyEnum e;
|
||||||
|
std::vector<float> fs;
|
||||||
|
|
||||||
|
//define serialize function as usual
|
||||||
|
template <typename S>
|
||||||
|
void serialize(S& s) {
|
||||||
|
//now we can use flexible syntax with
|
||||||
|
s.archive(i, e, fs);
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
using namespace bitsery;
|
||||||
|
|
||||||
|
//some helper types
|
||||||
|
using Buffer = std::vector<uint8_t>;
|
||||||
|
using OutputAdapter = OutputBufferAdapter<Buffer>;
|
||||||
|
using InputAdapter = InputBufferAdapter<Buffer>;
|
||||||
|
|
||||||
|
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 = quickSerialization<OutputAdapter>(buffer, data);
|
||||||
|
|
||||||
|
auto state = quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
|
||||||
|
|
||||||
|
assert(state.first == ReaderError::NoError && state.second);
|
||||||
|
assert(data.fs == res.fs && data.i == res.i && data.e == res.e);
|
||||||
|
}
|
||||||
@@ -41,11 +41,12 @@ namespace bitsery {
|
|||||||
:_ios{istream} {}
|
:_ios{istream} {}
|
||||||
|
|
||||||
void read(TValue* data, size_t size) {
|
void read(TValue* data, size_t size) {
|
||||||
_ios.rdbuf()->sgetn( data , size );
|
if (static_cast<size_t>(_ios.rdbuf()->sgetn( data , size )) != size)
|
||||||
|
*data = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ReaderError error() const {
|
ReaderError error() const {
|
||||||
if (!_ios.bad())
|
if (_ios.good())
|
||||||
return ReaderError::NoError;
|
return ReaderError::NoError;
|
||||||
return _ios.eof()
|
return _ios.eof()
|
||||||
? ReaderError::DataOverflow
|
? ReaderError::DataOverflow
|
||||||
|
|||||||
@@ -56,9 +56,10 @@ namespace bitsery {
|
|||||||
|
|
||||||
AdapterReader &operator=(const AdapterReader &) = delete;
|
AdapterReader &operator=(const AdapterReader &) = delete;
|
||||||
|
|
||||||
AdapterReader(AdapterReader &&) noexcept = default;
|
//todo add conditional noexcept
|
||||||
|
AdapterReader(AdapterReader &&) = default;
|
||||||
|
|
||||||
AdapterReader &operator=(AdapterReader &&) noexcept = default;
|
AdapterReader &operator=(AdapterReader &&) = default;
|
||||||
|
|
||||||
~AdapterReader() noexcept = default;
|
~AdapterReader() noexcept = default;
|
||||||
|
|
||||||
|
|||||||
@@ -117,9 +117,10 @@ namespace bitsery {
|
|||||||
|
|
||||||
AdapterWriter &operator=(const AdapterWriter &) = delete;
|
AdapterWriter &operator=(const AdapterWriter &) = delete;
|
||||||
|
|
||||||
AdapterWriter(AdapterWriter &&) noexcept = default;
|
//todo add conditional noexcept
|
||||||
|
AdapterWriter(AdapterWriter &&) = default;
|
||||||
|
|
||||||
AdapterWriter &operator=(AdapterWriter &&) noexcept = default;
|
AdapterWriter &operator=(AdapterWriter &&) = default;
|
||||||
|
|
||||||
~AdapterWriter() {
|
~AdapterWriter() {
|
||||||
flush();
|
flush();
|
||||||
|
|||||||
@@ -113,9 +113,34 @@ namespace bitsery {
|
|||||||
size_t maxSize;
|
size_t maxSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//if container, then call procesContainer, this memcpy for fundamental types contiguous container
|
||||||
|
template<typename S, typename T>
|
||||||
|
void processMaxSize(S &s, T& data, size_t maxSize, std::true_type) {
|
||||||
|
processContainer(s, data, maxSize);
|
||||||
|
};
|
||||||
|
|
||||||
|
//overload for const T&
|
||||||
|
template<typename S, typename T>
|
||||||
|
void processMaxSize(S &s, const T& data, size_t maxSize, std::true_type) {
|
||||||
|
processContainer(s, const_cast<T&>(data), maxSize);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//try to call serialize overload with maxsize, extensions use this technique
|
||||||
|
template<typename S, typename T>
|
||||||
|
void processMaxSize(S &s, T& data, size_t maxSize, std::false_type) {
|
||||||
|
serialize(s, data, maxSize);
|
||||||
|
};
|
||||||
|
|
||||||
|
//overload for const T&
|
||||||
|
template<typename S, typename T>
|
||||||
|
void processMaxSize(S &s, const T& data, size_t maxSize, std::false_type) {
|
||||||
|
serialize(s, const_cast<T&>(data), maxSize);
|
||||||
|
};
|
||||||
|
|
||||||
template<typename S, typename T>
|
template<typename S, typename T>
|
||||||
void serialize(S &s, const MaxSize<T> &ms) {
|
void serialize(S &s, const MaxSize<T> &ms) {
|
||||||
processContainer(s, ms.data, ms.maxSize);
|
processMaxSize(s, ms.data, ms.maxSize, details::IsContainerTraitsDefined<typename std::decay<T>::type>{});
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ namespace bitsery {
|
|||||||
return {obj, max};
|
return {obj, max};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//define serialize function for fundamental types
|
//define serialize function for fundamental types
|
||||||
template<typename S>
|
template<typename S>
|
||||||
void serialize(S &s, bool &v) {
|
void serialize(S &s, bool &v) {
|
||||||
|
|||||||
@@ -29,10 +29,10 @@
|
|||||||
|
|
||||||
namespace bitsery {
|
namespace bitsery {
|
||||||
template<typename S, typename ... TArgs>
|
template<typename S, typename ... TArgs>
|
||||||
void serialize(S &s, std::map<TArgs ... > &obj) {
|
void serialize(S &s, std::map<TArgs ... > &obj, size_t maxSize = std::numeric_limits<size_t>::max()) {
|
||||||
using TKey = typename std::map<TArgs...>::key_type;
|
using TKey = typename std::map<TArgs...>::key_type;
|
||||||
using TValue = typename std::map<TArgs...>::mapped_type;
|
using TValue = typename std::map<TArgs...>::mapped_type;
|
||||||
s.ext(obj, ext::StdMap{std::numeric_limits<size_t>::max()},
|
s.ext(obj, ext::StdMap{maxSize},
|
||||||
[&s](TKey& key, TValue& value) {
|
[&s](TKey& key, TValue& value) {
|
||||||
s.object(key);
|
s.object(key);
|
||||||
s.object(value);
|
s.object(value);
|
||||||
@@ -40,10 +40,10 @@ namespace bitsery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename S, typename ... TArgs>
|
template<typename S, typename ... TArgs>
|
||||||
void serialize(S &s, std::multimap<TArgs ... > &obj) {
|
void serialize(S &s, std::multimap<TArgs ... > &obj, size_t maxSize = std::numeric_limits<size_t>::max()) {
|
||||||
using TKey = typename std::multimap<TArgs...>::key_type;
|
using TKey = typename std::multimap<TArgs...>::key_type;
|
||||||
using TValue = typename std::multimap<TArgs...>::mapped_type;
|
using TValue = typename std::multimap<TArgs...>::mapped_type;
|
||||||
s.ext(obj, ext::StdMap{std::numeric_limits<size_t>::max()},
|
s.ext(obj, ext::StdMap{maxSize},
|
||||||
[&s](TKey& key, TValue& value) {
|
[&s](TKey& key, TValue& value) {
|
||||||
s.object(key);
|
s.object(key);
|
||||||
s.object(value);
|
s.object(value);
|
||||||
|
|||||||
@@ -28,13 +28,13 @@
|
|||||||
|
|
||||||
namespace bitsery {
|
namespace bitsery {
|
||||||
template<typename S, typename T, typename C>
|
template<typename S, typename T, typename C>
|
||||||
void serialize(S &s, std::queue<T, C> &obj) {
|
void serialize(S &s, std::queue<T, C> &obj, size_t maxSize = std::numeric_limits<size_t>::max()) {
|
||||||
s.ext(obj, ext::StdQueue{std::numeric_limits<size_t>::max()});
|
s.ext(obj, ext::StdQueue{maxSize});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename S, typename T, typename C, typename Comp>
|
template<typename S, typename T, typename C, typename Comp>
|
||||||
void serialize(S &s, std::priority_queue<T, C, Comp> &obj) {
|
void serialize(S &s, std::priority_queue<T, C, Comp> &obj, size_t maxSize = std::numeric_limits<size_t>::max()) {
|
||||||
s.ext(obj, ext::StdQueue{std::numeric_limits<size_t>::max()});
|
s.ext(obj, ext::StdQueue{maxSize});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,13 +29,13 @@
|
|||||||
|
|
||||||
namespace bitsery {
|
namespace bitsery {
|
||||||
template<typename S, typename ... TArgs>
|
template<typename S, typename ... TArgs>
|
||||||
void serialize(S &s, std::set<TArgs...> &obj) {
|
void serialize(S &s, std::set<TArgs...> &obj, size_t maxSize = std::numeric_limits<size_t>::max()) {
|
||||||
s.ext(obj, ext::StdSet{std::numeric_limits<size_t>::max()});
|
s.ext(obj, ext::StdSet{maxSize});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename S, typename ... TArgs>
|
template<typename S, typename ... TArgs>
|
||||||
void serialize(S &s, std::multiset<TArgs...> &obj) {
|
void serialize(S &s, std::multiset<TArgs...> &obj, size_t maxSize = std::numeric_limits<size_t>::max()) {
|
||||||
s.ext(obj, ext::StdSet{std::numeric_limits<size_t>::max()});
|
s.ext(obj, ext::StdSet{maxSize});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,8 @@
|
|||||||
|
|
||||||
namespace bitsery {
|
namespace bitsery {
|
||||||
template<typename S, typename T, typename C>
|
template<typename S, typename T, typename C>
|
||||||
void serialize(S &s, std::stack<T, C> &obj) {
|
void serialize(S &s, std::stack<T, C> &obj, size_t maxSize = std::numeric_limits<size_t>::max()) {
|
||||||
s.ext(obj, ext::StdStack{std::numeric_limits<size_t>::max()});
|
s.ext(obj, ext::StdStack{maxSize});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,10 +29,10 @@
|
|||||||
|
|
||||||
namespace bitsery {
|
namespace bitsery {
|
||||||
template<typename S, typename ... TArgs>
|
template<typename S, typename ... TArgs>
|
||||||
void serialize(S &s, std::unordered_map<TArgs ... > &obj) {
|
void serialize(S &s, std::unordered_map<TArgs ... > &obj, size_t maxSize = std::numeric_limits<size_t>::max()) {
|
||||||
using TKey = typename std::unordered_map<TArgs...>::key_type;
|
using TKey = typename std::unordered_map<TArgs...>::key_type;
|
||||||
using TValue = typename std::unordered_map<TArgs...>::mapped_type;
|
using TValue = typename std::unordered_map<TArgs...>::mapped_type;
|
||||||
s.ext(obj, ext::StdMap{std::numeric_limits<size_t>::max()},
|
s.ext(obj, ext::StdMap{maxSize},
|
||||||
[&s](TKey& key, TValue& value) {
|
[&s](TKey& key, TValue& value) {
|
||||||
s.object(key);
|
s.object(key);
|
||||||
s.object(value);
|
s.object(value);
|
||||||
@@ -40,10 +40,10 @@ namespace bitsery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename S, typename ... TArgs>
|
template<typename S, typename ... TArgs>
|
||||||
void serialize(S &s, std::unordered_multimap<TArgs ... > &obj) {
|
void serialize(S &s, std::unordered_multimap<TArgs ... > &obj, size_t maxSize = std::numeric_limits<size_t>::max()) {
|
||||||
using TKey = typename std::unordered_multimap<TArgs...>::key_type;
|
using TKey = typename std::unordered_multimap<TArgs...>::key_type;
|
||||||
using TValue = typename std::unordered_multimap<TArgs...>::mapped_type;
|
using TValue = typename std::unordered_multimap<TArgs...>::mapped_type;
|
||||||
s.ext(obj, ext::StdMap{std::numeric_limits<size_t>::max()},
|
s.ext(obj, ext::StdMap{maxSize},
|
||||||
[&s](TKey& key, TValue& value) {
|
[&s](TKey& key, TValue& value) {
|
||||||
s.object(key);
|
s.object(key);
|
||||||
s.object(value);
|
s.object(value);
|
||||||
|
|||||||
@@ -29,13 +29,13 @@
|
|||||||
|
|
||||||
namespace bitsery {
|
namespace bitsery {
|
||||||
template<typename S, typename ... TArgs>
|
template<typename S, typename ... TArgs>
|
||||||
void serialize(S &s, std::unordered_set<TArgs...> &obj) {
|
void serialize(S &s, std::unordered_set<TArgs...> &obj, size_t maxSize = std::numeric_limits<size_t>::max()) {
|
||||||
s.ext(obj, ext::StdSet{std::numeric_limits<size_t>::max()});
|
s.ext(obj, ext::StdSet{maxSize});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename S, typename ... TArgs>
|
template<typename S, typename ... TArgs>
|
||||||
void serialize(S &s, std::unordered_multiset<TArgs...> &obj) {
|
void serialize(S &s, std::unordered_multiset<TArgs...> &obj, size_t maxSize = std::numeric_limits<size_t>::max()) {
|
||||||
s.ext(obj, ext::StdSet{std::numeric_limits<size_t>::max()});
|
s.ext(obj, ext::StdSet{maxSize});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
109
tests/adapter_stream.cpp
Normal file
109
tests/adapter_stream.cpp
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
//MIT License
|
||||||
|
//
|
||||||
|
//Copyright (c) 2017 Mindaugas Vinkelis
|
||||||
|
//
|
||||||
|
//Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
//of this software and associated documentation files (the "Software"), to deal
|
||||||
|
//in the Software without restriction, including without limitation the rights
|
||||||
|
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
//copies of the Software, and to permit persons to whom the Software is
|
||||||
|
//furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
//The above copyright notice and this permission notice shall be included in all
|
||||||
|
//copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
//SOFTWARE.
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <bitsery/adapter/stream.h>
|
||||||
|
#include <bitsery/adapter_writer.h>
|
||||||
|
#include <bitsery/adapter_reader.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
//some helper types
|
||||||
|
using Stream = std::stringstream;
|
||||||
|
using OutputAdapter = bitsery::OutputStreamAdapter;
|
||||||
|
using InputAdapter = bitsery::InputStreamAdapter ;
|
||||||
|
using Writer = bitsery::AdapterWriter<bitsery::OutputStreamAdapter, bitsery::DefaultConfig>;
|
||||||
|
using Reader = bitsery::AdapterReader<bitsery::InputStreamAdapter, bitsery::DefaultConfig>;
|
||||||
|
|
||||||
|
using testing::Eq;
|
||||||
|
|
||||||
|
TEST(AdapterIOStream, WrittenBytesCountReturns0) {
|
||||||
|
//setup data
|
||||||
|
uint8_t t1 = 111;
|
||||||
|
|
||||||
|
Stream buf{};
|
||||||
|
Writer w{{buf}};
|
||||||
|
w.writeBytes<1>(t1);
|
||||||
|
w.flush();
|
||||||
|
|
||||||
|
EXPECT_THAT(buf.str().size(), Eq(1));
|
||||||
|
EXPECT_THAT(w.writtenBytesCount(), Eq(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AdapterIOStream, CorrectlyReturnsIsCompletedSuccessfully) {
|
||||||
|
//setup data
|
||||||
|
uint8_t t1 = 111;
|
||||||
|
|
||||||
|
Stream buf{};
|
||||||
|
Writer w{{buf}};
|
||||||
|
w.writeBytes<1>(t1);
|
||||||
|
w.flush();
|
||||||
|
|
||||||
|
Reader r{{buf}};
|
||||||
|
|
||||||
|
uint8_t r1{};
|
||||||
|
EXPECT_THAT(r.isCompletedSuccessfully(), Eq(false));
|
||||||
|
r.readBytes<1>(r1);
|
||||||
|
EXPECT_THAT(r.isCompletedSuccessfully(), Eq(true));
|
||||||
|
EXPECT_THAT(r1, Eq(t1));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AdapterIOStream, ReadingMoreThanAvailableReturnsZero) {
|
||||||
|
//setup data
|
||||||
|
uint8_t t1 = 111;
|
||||||
|
|
||||||
|
Stream buf{};
|
||||||
|
Writer w{{buf}};
|
||||||
|
w.writeBytes<1>(t1);
|
||||||
|
w.flush();
|
||||||
|
|
||||||
|
Reader r{{buf}};
|
||||||
|
|
||||||
|
uint8_t r1{};
|
||||||
|
r.readBytes<1>(r1);
|
||||||
|
r.readBytes<1>(r1);
|
||||||
|
EXPECT_THAT(r1, Eq(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
//this is strange, but probably stringstream doesnt use any of the base methods that sets io_base::iostate flags
|
||||||
|
TEST(AdapterIOStream, WhenReadingStringStreamThenErrorCodeAlwaysReturnsNoError) {
|
||||||
|
//setup data
|
||||||
|
uint8_t t1 = 111;
|
||||||
|
|
||||||
|
Stream buf{};
|
||||||
|
Writer w{{buf}};
|
||||||
|
w.writeBytes<1>(t1);
|
||||||
|
w.flush();
|
||||||
|
|
||||||
|
Reader r{{buf}};
|
||||||
|
|
||||||
|
uint8_t r1{};
|
||||||
|
EXPECT_THAT(r.isCompletedSuccessfully(), Eq(false));
|
||||||
|
EXPECT_THAT(r.error(), Eq(bitsery::ReaderError::NoError));
|
||||||
|
r.readBytes<1>(r1);
|
||||||
|
EXPECT_THAT(r.isCompletedSuccessfully(), Eq(true));
|
||||||
|
EXPECT_THAT(r.error(), Eq(bitsery::ReaderError::NoError));
|
||||||
|
EXPECT_THAT(r1, Eq(t1));
|
||||||
|
r.readBytes<1>(r1);
|
||||||
|
EXPECT_THAT(r1, Eq(0));
|
||||||
|
//should by overflow error, but it all iostate flags are set to false...
|
||||||
|
EXPECT_THAT(r.error(), Eq(bitsery::ReaderError::NoError));
|
||||||
|
}
|
||||||
@@ -141,6 +141,15 @@ T procArchive(const T& testData) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T procArchiveWithMaxSize(const T& testData) {
|
||||||
|
SerializationContext ctx;
|
||||||
|
ctx.createSerializer().archive(bitsery::maxSize(testData, 100));
|
||||||
|
T res;
|
||||||
|
ctx.createDeserializer().archive(bitsery::maxSize(res, 100));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, CStyleArrayForValueTypesAsContainer) {
|
TEST(FlexibleSyntax, CStyleArrayForValueTypesAsContainer) {
|
||||||
const int t1[3]{8748,-484,45};
|
const int t1[3]{8748,-484,45};
|
||||||
int r1[3]{0,0,0};
|
int r1[3]{0,0,0};
|
||||||
@@ -181,6 +190,8 @@ TEST(FlexibleSyntax, StdString) {
|
|||||||
|
|
||||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||||
EXPECT_THAT(procArchive(t2), Eq(t2));
|
EXPECT_THAT(procArchive(t2), Eq(t2));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t1), Eq(t1));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t2), Eq(t2));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, StdArray) {
|
TEST(FlexibleSyntax, StdArray) {
|
||||||
@@ -189,6 +200,7 @@ TEST(FlexibleSyntax, StdArray) {
|
|||||||
|
|
||||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||||
EXPECT_THAT(procArchive(t2), Eq(t2));
|
EXPECT_THAT(procArchive(t2), Eq(t2));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, StdVector) {
|
TEST(FlexibleSyntax, StdVector) {
|
||||||
@@ -197,6 +209,9 @@ TEST(FlexibleSyntax, StdVector) {
|
|||||||
|
|
||||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||||
EXPECT_THAT(procArchive(t2), Eq(t2));
|
EXPECT_THAT(procArchive(t2), Eq(t2));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t1), Eq(t1));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t2), Eq(t2));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, StdList) {
|
TEST(FlexibleSyntax, StdList) {
|
||||||
@@ -205,6 +220,9 @@ TEST(FlexibleSyntax, StdList) {
|
|||||||
|
|
||||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||||
EXPECT_THAT(procArchive(t2), Eq(t2));
|
EXPECT_THAT(procArchive(t2), Eq(t2));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t1), Eq(t1));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t2), Eq(t2));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, StdForwardList) {
|
TEST(FlexibleSyntax, StdForwardList) {
|
||||||
@@ -213,6 +231,9 @@ TEST(FlexibleSyntax, StdForwardList) {
|
|||||||
|
|
||||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||||
EXPECT_THAT(procArchive(t2), Eq(t2));
|
EXPECT_THAT(procArchive(t2), Eq(t2));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t1), Eq(t1));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t2), Eq(t2));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, StdDeque) {
|
TEST(FlexibleSyntax, StdDeque) {
|
||||||
@@ -221,6 +242,9 @@ TEST(FlexibleSyntax, StdDeque) {
|
|||||||
|
|
||||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||||
EXPECT_THAT(procArchive(t2), Eq(t2));
|
EXPECT_THAT(procArchive(t2), Eq(t2));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t1), Eq(t1));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t2), Eq(t2));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, StdQueue) {
|
TEST(FlexibleSyntax, StdQueue) {
|
||||||
@@ -229,6 +253,8 @@ TEST(FlexibleSyntax, StdQueue) {
|
|||||||
t1.push("second string");
|
t1.push("second string");
|
||||||
|
|
||||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t1), Eq(t1));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, StdPriorityQueue) {
|
TEST(FlexibleSyntax, StdPriorityQueue) {
|
||||||
@@ -255,6 +281,8 @@ TEST(FlexibleSyntax, StdStack) {
|
|||||||
t1.push("second string");
|
t1.push("second string");
|
||||||
|
|
||||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t1), Eq(t1));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, StdUnorderedMap) {
|
TEST(FlexibleSyntax, StdUnorderedMap) {
|
||||||
@@ -263,6 +291,7 @@ TEST(FlexibleSyntax, StdUnorderedMap) {
|
|||||||
t1.emplace(-5484,-845);
|
t1.emplace(-5484,-845);
|
||||||
|
|
||||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t1), Eq(t1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, StdUnorderedMultiMap) {
|
TEST(FlexibleSyntax, StdUnorderedMultiMap) {
|
||||||
@@ -272,6 +301,7 @@ TEST(FlexibleSyntax, StdUnorderedMultiMap) {
|
|||||||
t1.emplace("one",897);
|
t1.emplace("one",897);
|
||||||
|
|
||||||
EXPECT_TRUE(procArchive(t1) == t1);
|
EXPECT_TRUE(procArchive(t1) == t1);
|
||||||
|
EXPECT_TRUE(procArchiveWithMaxSize(t1) == t1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, StdMap) {
|
TEST(FlexibleSyntax, StdMap) {
|
||||||
@@ -280,6 +310,7 @@ TEST(FlexibleSyntax, StdMap) {
|
|||||||
t1.emplace(-5484,-845);
|
t1.emplace(-5484,-845);
|
||||||
|
|
||||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t1), Eq(t1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, StdMultiMap) {
|
TEST(FlexibleSyntax, StdMultiMap) {
|
||||||
@@ -308,6 +339,7 @@ TEST(FlexibleSyntax, StdUnorderedSet) {
|
|||||||
t1.emplace("three");
|
t1.emplace("three");
|
||||||
|
|
||||||
EXPECT_TRUE(procArchive(t1) == t1);
|
EXPECT_TRUE(procArchive(t1) == t1);
|
||||||
|
EXPECT_TRUE(procArchiveWithMaxSize(t1) == t1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, StdUnorderedMultiSet) {
|
TEST(FlexibleSyntax, StdUnorderedMultiSet) {
|
||||||
@@ -318,6 +350,7 @@ TEST(FlexibleSyntax, StdUnorderedMultiSet) {
|
|||||||
t1.emplace("one");
|
t1.emplace("one");
|
||||||
|
|
||||||
EXPECT_TRUE(procArchive(t1) == t1);
|
EXPECT_TRUE(procArchive(t1) == t1);
|
||||||
|
EXPECT_TRUE(procArchiveWithMaxSize(t1) == t1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, StdSet) {
|
TEST(FlexibleSyntax, StdSet) {
|
||||||
@@ -327,7 +360,7 @@ TEST(FlexibleSyntax, StdSet) {
|
|||||||
t1.emplace("three");
|
t1.emplace("three");
|
||||||
|
|
||||||
EXPECT_TRUE(procArchive(t1) == t1);
|
EXPECT_TRUE(procArchive(t1) == t1);
|
||||||
|
EXPECT_TRUE(procArchiveWithMaxSize(t1) == t1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlexibleSyntax, StdMultiSet) {
|
TEST(FlexibleSyntax, StdMultiSet) {
|
||||||
@@ -339,6 +372,7 @@ TEST(FlexibleSyntax, StdMultiSet) {
|
|||||||
t1.emplace("two");
|
t1.emplace("two");
|
||||||
|
|
||||||
EXPECT_TRUE(procArchive(t1) == t1);
|
EXPECT_TRUE(procArchive(t1) == t1);
|
||||||
|
EXPECT_TRUE(procArchiveWithMaxSize(t1) == t1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -348,4 +382,5 @@ TEST(FlexibleSyntax, NestedTypes) {
|
|||||||
t1.emplace("other key", std::vector<std::string>{"just a string"});
|
t1.emplace("other key", std::vector<std::string>{"just a string"});
|
||||||
|
|
||||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||||
|
EXPECT_THAT(procArchiveWithMaxSize(t1), Eq(t1));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user