11 Commits

Author SHA1 Message Date
Mindaugas Vinkelis
c0fc083c9d Additional improvements for v5.2.2 release
* migration to github actions
* additionally build tests/examples on windows and macos
2021-08-31 22:16:47 +03:00
michael-mueller-git
bcd03b4d68 Add Missing header (#82)
* add missing header to develop
* add test to check include files
* fix missing includes
* improve test target names

Co-authored-by: arch <arch@local>
2021-08-24 09:28:15 +03:00
Mindaugas Vinkelis
4ff80c6426 fix: std::variant access with get_if using index 2021-05-31 08:12:28 +03:00
Mindaugas Vinkelis
126a6c2971 Merge pull request #77 from robbert-vdh/feature/nontrivial-variant-deserialization
Avoid reinitializing nontrivial std::variant
2021-05-29 09:31:51 +03:00
Robbert van der Helm
d1830a263b Avoid reinitializing nontrivial std::variant #76
When deserializing into an `std::variant<Ts...>` and the object we're
deserializing into already holds the requested variant, then we should
try to deserialize into the existing object instead of recreating it if
the variant is a nontrivial type. This is important when the object has
a default constructor that performs a nontrivial amount of work, or when
the object contains heap data that would need to be reallocated when
recreating the object.
2021-05-28 14:55:59 +02:00
Mindaugas Vinkelis
47f6f9248a Merge pull request #75 from victorstewart/16b
add 16 byte value (aka uint128_t) usage
2021-05-28 14:23:30 +03:00
Victor Stewart
9688cb03d2 add 16 byte value (aka uint128_t) usage 2021-05-15 21:03:56 +00:00
Mindaugas Vinkelis
db884a0656 release v5.2.1
BufferAdapter statically assert on underlying type size

bugfix in StdBitset
2020-11-14 11:36:22 +02:00
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
36 changed files with 584 additions and 63 deletions

62
.github/workflows/on_linux.yml vendored Normal file
View File

@@ -0,0 +1,62 @@
name: On Linux
on:
push:
branches: [ develop, master ]
pull_request:
branches: [ develop, master ]
jobs:
build:
name: ${{ matrix.config.name }}
runs-on: ubuntu-18.04
strategy:
fail-fast: false
matrix:
config:
- name: "Ubuntu 18.04 with Clang 3.9"
cxx_ver: 11
compiler: clang
compiler_ver: 3.9
- name: "Ubuntu 18.04 with GCC 5.0"
cxx_ver: 11
compiler: gcc
compiler_ver: 5
- name: "Ubuntu 18.04 with GCC 11.0"
cxx_ver: 17
compiler: gcc
compiler_ver: 11
- name: "Ubuntu 18.04 with Clang 13"
cxx_ver: 17
compiler: clang
compiler_ver: 13
steps:
- name: Prepare specific Clang version
if: ${{ matrix.config.compiler == 'clang' }}
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-add-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-13 main"
sudo apt update
sudo apt install clang-${{ matrix.config.compiler_ver}}
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-${{ matrix.config.compiler_ver}} 100
sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang-${{ matrix.config.compiler_ver}} 100
- name: Prepare specific GCC version
if: ${{ matrix.config.compiler == 'gcc' }}
run: |
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt update
sudo apt install g++-${{ matrix.config.compiler_ver}}
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++-${{ matrix.config.compiler_ver}} 100
sudo update-alternatives --install /usr/bin/cc cc /usr/bin/gcc-${{ matrix.config.compiler_ver}} 100
- name: Installing GTest
run: |
sudo add-apt-repository ppa:team-xbmc/ppa
sudo apt-get update
sudo apt-get install libgmock-dev
- uses: actions/checkout@v2
- name: Configure
run: cmake -S . -B build -DBITSERY_BUILD_TESTS=ON -DBITSERY_BUILD_EXAMPLES=ON -DCMAKE_CXX_STANDARD=${{ matrix.config.cxx_ver }}
- name: Build
run: cmake --build build
- name: Run tests
run: ctest --test-dir build/tests

26
.github/workflows/on_mac.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: On Mac
on:
push:
branches: [ develop, master ]
pull_request:
branches: [ develop, master ]
jobs:
build:
name: macOS Latest
runs-on: macos-latest
steps:
- name: Installing GTest
run: |
git clone https://github.com/google/googletest.git
cd googletest
git checkout release-1.11.0
cmake -S . -B build
cmake --build build --target install
- uses: actions/checkout@v2
- name: Configure
run: cmake -S . -B build -DBITSERY_BUILD_TESTS=ON -DBITSERY_BUILD_EXAMPLES=ON -DCMAKE_CXX_STANDARD=17
- name: Build
run: cmake --build build
- name: Run tests
run: ctest --test-dir build/tests

29
.github/workflows/on_windows.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: On Windows
on:
push:
branches: [ develop, master ]
pull_request:
branches: [ develop, master ]
jobs:
build:
name: Windows MSVC Latest
runs-on: windows-latest
steps:
- name: Installing GTest
run: |
git clone https://github.com/google/googletest.git
cd googletest
git checkout release-1.11.0
cmake -S . -B build -Dgtest_force_shared_crt=ON
cmake --build build --config Release --target install
- uses: actions/checkout@v2
- name: Configure
run: cmake -S . -B build -DBITSERY_BUILD_TESTS=ON -DBITSERY_BUILD_EXAMPLES=ON -DCMAKE_CXX_STANDARD=17 -DCMAKE_CXX_FLAGS="/Zc:__cplusplus /permissive- /EHsc"
env:
CMAKE_PREFIX_PATH: "C:/Program Files (x86)/googletest-distribution/"
- name: Build
run: cmake --build build --config Release
- name: Run tests
run: ctest --test-dir build/tests

View File

@@ -1,3 +1,37 @@
# [5.2.2](https://github.com/fraillt/bitsery/compare/v5.2.1...v5.2.2) (2021-08-31)
### Improvements
* add 16 byte value support #75 (thanks to [Victor Stewart](https://github.com/victorstewart))
* avoid reinitializing nontrivial std::variant #77 (thanks to [Robbert van der Helm](https://github.com/robbert-vdh))
* avoid reinitializing nontrivial std::optional.
### Bug fixes
* fix missing headers for GCC11, also added test to check includes #82 (thanks to [michael-mueller-git](https://github.com/michael-mueller-git))
* fixed **StdBitset** to build on macOS (proxy type, returned by `[]` operator wasn't correctly converted to unsigned integral type).
### Other notes
* migrated to [Github actions](https://docs.github.com/en/actions) for running tests.
* fixes few warnings on MSVC compiler.
* now tests are also run on macOS and Windows.
# [5.2.1](https://github.com/fraillt/bitsery/compare/v5.2.0...v5.2.1) (2020-11-14)
### Improvements
* `Input/OutputBufferAdapter` now statically asserts that underlying type is 1byte in size.
### Bug fixes
* fixed serialization in `StdBitset` when it's size is less then `unsigned long long`.
# [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
@@ -11,7 +45,7 @@
* 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).
* 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)

View File

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

View File

@@ -6,7 +6,7 @@ However, to make sure the process of accepting patches goes smoothly, you should
you contribute:
1. Fork the repository.
2. Create new branch based on the *master* branch (`git checkout -b your_branch master`). If your contribution is a bug fix, you should name your branch `bugfix/xxx`; for a feature, it should be `feature/xxx`. Otherwise, just use your good judgment. Consistent naming of branches is appreciated since it makes the output of `git branch` easier to understand with a single glance.
2. Create new branch based on the *develop* branch (`git checkout -b your_branch develop`). If your contribution is a bug fix, you should name your branch `bugfix/xxx`; for a feature, it should be `feature/xxx`. Otherwise, just use your good judgment. Consistent naming of branches is appreciated since it makes the output of `git branch` easier to understand with a single glance.
3. Do your modifications on that branch. Except for special cases, your contribution should include proper unit tests and documentation.
4. Make sure your modifications did not break anything by building, running tests:
```shell
@@ -23,7 +23,7 @@ you contribute:
./show_coverage.sh build
```
5. Commit your changes, and push to your fork (`git push origin your_branch`). Commit message should be one line short description. When applicable, please squash adjacent *wip* commits into a single *logical* commit.
6. Open a pull request against Bitsery *master* branch. Currently ongoing development is on *master*. At some point an integration branch will be set-up, and pull-requests should target that, but for now its all against master. You may see feature branches come and go, too.
6. Open a pull request against Bitsery *develop* branch.
If you're working with visual studio, there is how to build and run all tests from command line

View File

@@ -1,6 +1,8 @@
# Bitsery
[![Build Status](https://travis-ci.org/fraillt/bitsery.svg?branch=master)](https://travis-ci.org/fraillt/bitsery)
[![Build On Windows](https://github.com/fraillt/bitsery/actions/workflows/on_windows.yml/badge.svg)](https://github.com/fraillt/bitsery/actions/workflows/on_windows.yml)
[![Build On Mac](https://github.com/fraillt/bitsery/actions/workflows/on_mac.yml/badge.svg)](https://github.com/fraillt/bitsery/actions/workflows/on_mac.yml)
[![Build On Linux](https://github.com/fraillt/bitsery/actions/workflows/on_linux.yml/badge.svg)](https://github.com/fraillt/bitsery/actions/workflows/on_linux.yml)
[![Join the chat at https://gitter.im/bitsery/Lobby](https://badges.gitter.im/bitsery/Lobby.svg)](https://gitter.im/bitsery/Lobby)
Header only C++ binary serialization library.
@@ -30,17 +32,17 @@ All cross-platform requirements are enforced at compile time, so serialized data
Look at the numbers and features list, and decide yourself.
| library | data size | serialize | deserialize |
| ---------------- | --------- | --------- | ----------- |
| bitsery | 6913B | 959ms | 927ms |
| bitsery_compress | 4213B | 1282ms | 1115ms |
| boost | 11037B | 9826ms | 8313ms |
| cereal | 10413B | 6324ms | 5698ms |
| flatbuffers | 14924B | 5129ms | 2142ms |
| protobuf | 10018B | 11966ms | 13919ms |
| yas | 10463B | 1908ms | 1217ms |
| library | data size | ser time | des time |
| ----------- | --------- | -------- | -------- |
| bitsery | 6913B | 1119ms | 1166ms |
| boost | 11037B | 15391ms | 12912ms |
| cereal | 10413B | 10518ms | 10245ms |
| flatbuffers | 14924B | 9075ms | 3701ms |
| msgpack | 8857B | 3340ms | 13842ms |
| protobuf | 10018B | 21229ms | 22077ms |
| yas | 10463B | 2107ms | 1554ms |
*benchmarked on Ubuntu with GCC 8.3.0, more details can be found [here](https://github.com/fraillt/cpp_serializers_benchmark.git)*
*benchmarked on Ubuntu with GCC 10.3.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.
@@ -98,10 +100,7 @@ Works with C++11 compiler, no additional dependencies, include `<bitsery/bitsery
## Platforms
This library was tested on
* Windows: Visual Studio 2015, MinGW (GCC 5.2)
* Linux: GCC 5.4, Clang 3.9
* OS X Mavericks: AppleClang 8
Library is tested on all major compilers on Windows, Linux and macOS.
There is a patch that allows using bitsery with non-fully compatible C++11 compilers.
* CentOS 7 with gcc 4.8.2.

View File

@@ -41,7 +41,7 @@ void serialize(S& s, MyVariant& o) {
s.ext(o, bitsery::ext::StdTuple{
// this is convenient callable object to specify integral value size
// it is different equivalent to lambda [](auto& s, float&o) { s.value4b(o);}
bitsery::ext::OverloadValue<float, 4>{},
bitsery::ext::OverloadValue<float, 4>{},
// it is not required to provide MyStruct overload, because it we have defined 'serialize' function for it
});
},
@@ -66,7 +66,7 @@ void serialize(S& s, MyVariant& o) {
// also note, that first parameter (serializer) is also "auto", this is required, so that it would be least specialized case
// otherwise it will not compile if you any ext::Overload* helper defined, because it will have ambiguous definitions
// (ext::OverLoad* defines (templated_type& s, concrete_type& o) and lambda would be (concrete_type& s, templated_type& o))
[](auto& , auto& ) {
[](auto& , auto&) {
assert(false);
}
});
@@ -81,8 +81,7 @@ using InputAdapter = bitsery::InputBufferAdapter<Buffer>;
int main() {
//set some random data
MyVariant data{MyTuple{-7549, {{-451, 2, 968, 75, 4, 156, 49}, 874.4f}}};
// MyVariant data{MyStruct{{-451, 2, 968, 75, 4, 156, 49}, 874.4f}};
MyVariant data{ MyTuple{-7549, {{-451, 2, 968, 75, 4, 156, 49}, 874.4f}} };
MyVariant res{};
//create buffer to store data
@@ -94,19 +93,18 @@ 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 = bitsery::quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
auto state = bitsery::quickDeserialization<InputAdapter>({ buffer.begin(), writtenSize }, res);
assert(state.first == bitsery::ReaderError::NoError && state.second);
assert(data == res);
}
#else
#if defined(_MSC_VER)
#pragma message("example works only on c++17")
#pragma message("C++17 and /Zc:__cplusplus option is required to enable this example")
#else
#warning "example works only on c++17"
#pragma message("C++17 is required to enable this example")
#endif
int main() {
return 0;
}
#endif

View File

@@ -39,6 +39,7 @@ namespace bitsery {
"Please define BufferAdapterTraits or include from <bitsery/traits/...>");
static_assert(traits::ContainerTraits<typename std::remove_const<Buffer>::type>::isContiguous,
"BufferAdapter only works with contiguous containers");
static_assert(sizeof(TValue) == 1, "BufferAdapter underlying type must be 1byte.");
InputBufferAdapter(TIterator beginIt, size_t size)
: _beginIt{beginIt},
@@ -196,6 +197,7 @@ namespace bitsery {
"Please define BufferAdapterTraits or include from <bitsery/traits/...>");
static_assert(traits::ContainerTraits<Buffer>::isContiguous,
"BufferAdapter only works with contiguous containers");
static_assert(sizeof(TValue) == 1, "BufferAdapter underlying type must be 1byte.");
OutputBufferAdapter(Buffer &buffer)
: _buffer{std::addressof(buffer)},

View File

@@ -23,6 +23,10 @@
#ifndef BITSERY_ADAPTER_MEASURE_SIZE_H
#define BITSERY_ADAPTER_MEASURE_SIZE_H
#include <cstddef>
#include <type_traits>
#include "../details/adapter_common.h"
namespace bitsery {

View File

@@ -26,6 +26,7 @@
#include "../details/adapter_common.h"
#include "../traits/array.h"
#include <ios>
#include <limits>
namespace bitsery {

View File

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

View File

@@ -25,6 +25,7 @@
#define BITSERY_BRIEF_SYNTAX_TYPE_STD_MAP_H
#include <map>
#include <limits>
#include "../ext/std_map.h"
namespace bitsery {

View File

@@ -25,6 +25,7 @@
#define BITSERY_BRIEF_SYNTAX_TYPE_STD_QUEUE_H
#include "../ext/std_queue.h"
#include <limits>
namespace bitsery {
template<typename S, typename T, typename C>

View File

@@ -25,6 +25,7 @@
#define BITSERY_BRIEF_SYNTAX_TYPE_STD_SET_H
#include <set>
#include <limits>
#include "../ext/std_set.h"
namespace bitsery {

View File

@@ -24,6 +24,7 @@
#ifndef BITSERY_BRIEF_SYNTAX_TYPE_STD_STACK_H
#define BITSERY_BRIEF_SYNTAX_TYPE_STD_STACK_H
#include <limits>
#include "../ext/std_stack.h"
namespace bitsery {

View File

@@ -25,6 +25,7 @@
#define BITSERY_BRIEF_SYNTAX_TYPE_STD_UNORDERED_MAP_H
#include <unordered_map>
#include <limits>
#include "../ext/std_map.h"
namespace bitsery {

View File

@@ -24,6 +24,7 @@
#ifndef BITSERY_BRIEF_SYNTAX_TYPE_STD_UNORDERED_SET_H
#define BITSERY_BRIEF_SYNTAX_TYPE_STD_UNORDERED_SET_H
#include <limits>
#include <unordered_set>
#include "../ext/std_set.h"

View File

@@ -369,6 +369,9 @@ namespace bitsery {
template<typename T>
void value8b(T &&v) { value<8>(std::forward<T>(v)); }
template<typename T>
void value16b(T &&v) { value<16>(std::forward<T>(v)); }
template<typename T, typename Ext>
void ext1b(T &v, Ext &&extension) { ext<1, T, Ext>(v, std::forward<Ext>(extension)); }
@@ -381,6 +384,9 @@ namespace bitsery {
template<typename T, typename Ext>
void ext8b(T &v, Ext &&extension) { ext<8, T, Ext>(v, std::forward<Ext>(extension)); }
template<typename T, typename Ext>
void ext16b(T &v, Ext &&extension) { ext<16, T, Ext>(v, std::forward<Ext>(extension)); }
template<typename T>
void text1b(T &str, size_t maxSize) { text<1>(str, maxSize); }
@@ -411,6 +417,9 @@ namespace bitsery {
template<typename T>
void container8b(T &&obj, size_t maxSize) { container<8>(std::forward<T>(obj), maxSize); }
template<typename T>
void container16b(T &&obj, size_t maxSize) { container<16>(std::forward<T>(obj), maxSize); }
template<typename T>
void container1b(T &&obj) { container<1>(std::forward<T>(obj)); }
@@ -423,6 +432,9 @@ namespace bitsery {
template<typename T>
void container8b(T &&obj) { container<8>(std::forward<T>(obj)); }
template<typename T>
void container16b(T &&obj) { container<16>(std::forward<T>(obj)); }
private:
void readSize(size_t& size, size_t maxSize) {

View File

@@ -146,12 +146,16 @@ namespace bitsery {
*/
// 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,

View File

@@ -24,6 +24,7 @@
#define BITSERY_DETAILS_BRIEF_SYNTAX_COMMON_H
#include "../traits/core/traits.h"
#include "serialization_common.h"
#include <limits>
namespace bitsery {

View File

@@ -75,6 +75,8 @@ namespace bitsery {
struct FtorExtValue4b: FtorExtValue<4, Ext> {};
template <typename Ext>
struct FtorExtValue8b: FtorExtValue<8, Ext> {};
template <typename Ext>
struct FtorExtValue16b: FtorExtValue<16, Ext> {};
template<typename Ext>
struct FtorExtObject : public Ext {

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 >>= 8;
}
}
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] ? 1u : 0u, 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 == 1;
}
}
};
}
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

@@ -56,13 +56,26 @@ namespace bitsery {
if (_alignBeforeData)
des.adapter().align();
if (exists) {
obj = ::bitsery::Access::create<T>();
fnc(des, *obj);
deserialize_impl(des, obj, fnc, std::is_trivial<T>{});
} else {
obj = std::nullopt;
}
}
private:
template<typename Des, typename T, typename Fnc>
void deserialize_impl(Des &des, std::optional<T> &obj, Fnc &&fnc, std::true_type) const {
obj = ::bitsery::Access::create<T>();
fnc(des, *obj);
}
template<typename Des, typename T, typename Fnc>
void deserialize_impl(Des &des, std::optional<T> &obj, Fnc &&fnc, std::false_type) const {
if (!obj) {
obj = ::bitsery::Access::create<T>();
}
fnc(des, *obj);
}
bool _alignBeforeData;
};
}

View File

@@ -54,6 +54,17 @@ namespace bitsery {
this->execIndex(index, obj, [this, &des](auto& data, auto index) {
constexpr size_t Index = decltype(index)::value;
using TElem = typename std::variant_alternative<Index, std::variant<Ts...>>::type;
// Reinitializing nontrivial types may be expensive especially when they
// reference heap data, so if `data` is already holding the requested
// variant then we'll deserialize into the existing object
if constexpr (!std::is_trivial_v<TElem>) {
if (auto item = std::get_if<Index>(&data)) {
this->serializeType(des, *item);
return;
}
}
TElem item = ::bitsery::Access::create<TElem>();
this->serializeType(des, item);
data = std::variant<Ts...>(std::in_place_index_t<Index>{}, std::move(item));

View File

@@ -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

@@ -27,6 +27,7 @@
#include "details/serialization_common.h"
#include "details/adapter_common.h"
#include <cassert>
#include <limits>
namespace bitsery {
@@ -289,6 +290,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 +304,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 +318,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));
@@ -364,6 +368,9 @@ namespace bitsery {
template<typename T>
void value8b(T &&v) { value<8>(std::forward<T>(v)); }
template<typename T>
void value16b(T &&v) { value<16>(std::forward<T>(v)); }
template<typename T, typename Ext>
void ext1b(const T &v, Ext &&extension) { ext<1, T, Ext>(v, std::forward<Ext>(extension)); }
@@ -376,6 +383,9 @@ namespace bitsery {
template<typename T, typename Ext>
void ext8b(const T &v, Ext &&extension) { ext<8, T, Ext>(v, std::forward<Ext>(extension)); }
template<typename T, typename Ext>
void ext16b(const T &v, Ext &&extension) { ext<16, T, Ext>(v, std::forward<Ext>(extension)); }
template<typename T>
void text1b(const T &str, size_t maxSize) { text<1>(str, maxSize); }
@@ -406,6 +416,9 @@ namespace bitsery {
template<typename T>
void container8b(T &&obj, size_t maxSize) { container<8>(std::forward<T>(obj), maxSize); }
template<typename T>
void container16b(T &&obj, size_t maxSize) { container<16>(std::forward<T>(obj), maxSize); }
template<typename T>
void container1b(T &&obj) { container<1>(std::forward<T>(obj)); }
@@ -418,6 +431,9 @@ namespace bitsery {
template<typename T>
void container8b(T &&obj) { container<8>(std::forward<T>(obj)); }
template<typename T>
void container16b(T &&obj) { container<16>(std::forward<T>(obj)); }
private:
@@ -453,6 +469,7 @@ namespace bitsery {
template<size_t VSIZE, typename T>
void procText(const T& str, size_t maxSize) {
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);

0
scripts/show_coverage.sh Executable file → Normal file
View File

View File

@@ -20,8 +20,9 @@
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
#SOFTWARE.
cmake_minimum_required(VERSION 3.10)
project(bitsery_tests CXX)
cmake_minimum_required(VERSION 3.11)
project(bitsery_tests
LANGUAGES CXX)
find_package(GTest 1.10 REQUIRED)
@@ -62,4 +63,40 @@ if (ParentDir)
# add headers so IDE correctly show them
target_sources(bitsery.dummy_for_ide PRIVATE ${HeadersForIDE} serialization_test_utils.h)
target_link_libraries(bitsery.dummy_for_ide PRIVATE GTest::Main Bitsery::bitsery)
# creates a "check_includes" target to verify if all headers has required includes
# to simplify things a little bit, it only works with modern compiler (C++17)
# as some bitsery extensions require C++17 compliant compiler.
if("cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
add_library(check_includes OBJECT)
target_compile_features(check_includes PRIVATE cxx_std_17)
file(WRITE ${CMAKE_BINARY_DIR}/check_includes.in "
// generated by CMake to verify header includes.
// we need exactly 201703L, because some compilers with experimental C++17 support
// provides bigger number than 201402L (C++14) but doesn't actually has enough
// functionality to build these files
#if __cplusplus >= 201703L
#include \"@HeaderFile@\"
#elif defined(_MSC_VER)
#pragma message(\"/Zc:__cplusplus option is required to enable check_includes\")
#else
#define XSTR(x) STR(x)
#define STR(x) #x
#pragma message (\"`__cplusplus` macro value should be 201703L or greater, actual value is: \" XSTR(__cplusplus))
#endif
")
file(GLOB_RECURSE HeaderFiles "${ParentDir}/include/bitsery/*.h")
foreach (HeaderFile ${HeaderFiles})
SET(CHK_TARGET_NAME "chk_inc_${HeaderFile}")
STRING(REPLACE "${ParentDir}/include/bitsery/" "" CHK_TARGET_NAME ${CHK_TARGET_NAME})
STRING(REGEX REPLACE "/" "_" CHK_TARGET_NAME ${CHK_TARGET_NAME})
STRING(REGEX REPLACE "\\\\" "_" CHK_TARGET_NAME ${CHK_TARGET_NAME})
configure_file(${CMAKE_BINARY_DIR}/check_includes.in "${CHK_TARGET_NAME}.cpp")
target_sources(check_includes PRIVATE "${CHK_TARGET_NAME}.cpp")
endforeach ()
else()
message(WARNING "`check_includes` target will be disabled, as it require compiler with C++17 support.")
endif()
endif()

View File

@@ -39,12 +39,10 @@
#if __cplusplus > 201402L
#include <bitsery/brief_syntax/tuple.h>
#include <bitsery/brief_syntax/variant.h>
#elif defined(_MSC_VER)
#pragma message("C++17 and /Zc:__cplusplus option is required to enable std::tuple and std::variant brief syntax tests")
#else
/*#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*/
#pragma message("C++17 is required to enable std::tuple and std::variant brief syntax tests")
#endif
#include <gmock/gmock.h>

View File

@@ -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{});

View File

@@ -41,7 +41,7 @@ TEST(SerializationContext, WhenContextIsNotTupleThenReturnThisContext) {
TEST(SerializationContext, WhenContextIsTupleThenReturnsTupleElements) {
MultipleTypesContext ctx{5, 798.654, 'F'};
MultipleTypesContext ctx{5, 798.654f, 'F'};
BasicSerializationContext<MultipleTypesContext> c1;
auto& ser1 = c1.createSerializer(ctx);
@@ -59,7 +59,7 @@ TEST(SerializationContext, WhenContextDoesntExistsThenContextOrNullReturnsNull)
*ser.contextOrNull<int>() = 2;
EXPECT_THAT(ctx1, Eq(2));
MultipleTypesContext ctx2{5, 798.654, 'F'};
MultipleTypesContext ctx2{5, 798.654f, 'F'};
BasicSerializationContext<MultipleTypesContext> c2;
auto& des = c2.createDeserializer(ctx2);
EXPECT_THAT(des.contextOrNull<double>(), ::testing::IsNull());
@@ -105,4 +105,4 @@ TEST(SerializationContext, WhenMultipleConvertibleTypesExistsThenFirstMatchIsTak
//Base will not be accessable in this case, because Derived is first valid match
EXPECT_THAT(des.context<Base>().value, Eq(std::get<1>(ctx2).value));
}
}
}

View File

@@ -0,0 +1,124 @@
//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<31> data;
data[2] = true;
data[8] = true;
data[15] = true;
data[25] = true;
data[30] = true;
std::bitset<31> res;
ctx.createSerializer().ext(data, StdBitset{});
ctx.createDeserializer().ext(res, StdBitset{});
EXPECT_THAT(res, Eq(data));
}
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[31] = true;
data[63] = true;
data[100] = true;
data[191] = true;
std::bitset<200> res;
ctx.createSerializer().ext(data, StdBitset{});
ctx.createDeserializer().ext(res, StdBitset{});
EXPECT_THAT(res, Eq(data));
}
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

@@ -120,10 +120,8 @@ TEST(SerializeExtensionStdOptional, NoAlignAfterStateWriteRead) {
EXPECT_THAT(t1.value(), Eq(r1.value()));
}
#elif defined(_MSC_VER)
#pragma message("C++17 and /Zc:__cplusplus option is required to enable std::optional tests")
#else
/*#if defined(_MSC_VER)
#pragma message("Tests for StdOptional requires C++17")
#else
#warning "Tests for StdOptional requires C++17"
#endif*/
#pragma message("C++17 is required to enable std::optional tests")
#endif

View File

@@ -102,8 +102,8 @@ private:
};
TEST(SerializeExtensionStdTuple, NonDefaultConstructable) {
std::tuple<NonDefaultConstructable> t1{34};
std::tuple<NonDefaultConstructable> r1{8};
std::tuple<NonDefaultConstructable> t1{34.0f};
std::tuple<NonDefaultConstructable> r1{8.0f};
SerializationContext ctx;
ctx.createSerializer().ext(t1, bitsery::ext::StdTuple{
[](auto& s, NonDefaultConstructable& v) {
@@ -118,10 +118,8 @@ TEST(SerializeExtensionStdTuple, NonDefaultConstructable) {
EXPECT_THAT(t1, Eq(r1));
}
#elif defined(_MSC_VER)
#pragma message("C++17 and /Zc:__cplusplus option is required to enable std::tuple tests")
#else
/*#if defined(_MSC_VER)
#pragma message("Tests for StdTuple requires C++17")
#else
#warning "Tests for StdTuple requires C++17"
#endif*/
#endif
#pragma message("C++17 is required to enable std::tuple tests")
#endif

View File

@@ -167,10 +167,8 @@ TEST(SerializeExtensionStdVariant, CorrectlyHandleMonoState) {
}
#elif defined(_MSC_VER)
#pragma message("C++17 and /Zc:__cplusplus option is required to enable std::variant tests")
#else
/*#if defined(_MSC_VER)
#pragma message("Tests for StdVariant requires C++17")
#else
#warning "Tests for StdVariant requires C++17"
#endif*/
#pragma message("C++17 is required to enable std::variant tests")
#endif