mirror of
https://github.com/fraillt/bitsery.git
synced 2026-06-08 00:03:54 +00:00
compile warnings, and usage improvements for VisualStudio
This commit is contained in:
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,3 +1,14 @@
|
||||
# [4.0.1](https://github.com/fraillt/bitsery/compare/v4.0.0...v4.0.1) (2017-10-18)
|
||||
|
||||
### Improvements
|
||||
|
||||
* improved usage with Visual Studio:
|
||||
* improved CMake.
|
||||
* Visual Studio doesn't properly support expression SFINAE using std::void_t, so it was rewritten.
|
||||
* refactorings to remove compiler warnings when using *-Wextra -Wno-missing-braces -Wpedantic -Weffc++*
|
||||
* added assertion when session is empty (sessions is created via *growable* extension).
|
||||
* stream adapter manually *setstate* to *std::ios_base::eofbit* when unable to read required bytes.
|
||||
|
||||
# [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.
|
||||
|
||||
@@ -2,7 +2,13 @@ cmake_minimum_required(VERSION 3.2)
|
||||
|
||||
project(bitsery)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(COMPILE_FLAGS "")
|
||||
else()
|
||||
set(COMPILE_FLAGS "-Wall -Wextra -Wno-missing-braces -Wpedantic -Weffc++")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS}")
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
|
||||
@@ -27,6 +27,12 @@ include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
|
||||
file(GLOB ExampleFiles ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
|
||||
|
||||
if (WIN32)
|
||||
message(WARNING "Removing example `flexible_assert_linux_x64` for Windows")
|
||||
list(REMOVE_ITEM ExampleFiles ${CMAKE_CURRENT_SOURCE_DIR}/flexible_assert_linux_x64.cpp)
|
||||
endif()
|
||||
|
||||
|
||||
FOREACH(ExampleFile ${ExampleFiles})
|
||||
get_filename_component(ExampleName ${ExampleFile} NAME_WE)
|
||||
add_executable(${ExampleName} ${ExampleFile})
|
||||
|
||||
@@ -20,7 +20,7 @@ void serialize(S& s, MyStruct& o) {
|
||||
s.value4b(o.i);//fundamental types (ints, floats, enums) of size 4b
|
||||
s.value2b(o.e);
|
||||
s.container4b(o.fs, 10);//resizable containers also requires maxSize, to make it safe from buffer-overflow attacks
|
||||
};
|
||||
}
|
||||
|
||||
using namespace bitsery;
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ int main() {
|
||||
Buffer buffer{};
|
||||
auto writtenSize = quickSerialization<OutputAdapter>(buffer, data);
|
||||
|
||||
MyTypes::Monster res;
|
||||
MyTypes::Monster res{};
|
||||
auto state = quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
|
||||
|
||||
assert(state.first == ReaderError::NoError && state.second);
|
||||
|
||||
@@ -15,9 +15,13 @@ struct GameMode {
|
||||
namespace MyTypes {
|
||||
|
||||
struct Monster {
|
||||
std::string name;
|
||||
uint32_t minDamage;
|
||||
uint32_t maxDamage;
|
||||
Monster() = default;
|
||||
Monster(std::string _name, uint32_t minDmg, uint32_t maxDmg)
|
||||
:name{_name}, minDamage{minDmg}, maxDamage{maxDmg} {}
|
||||
|
||||
std::string name{};
|
||||
uint32_t minDamage{};
|
||||
uint32_t maxDamage{};
|
||||
//...
|
||||
};
|
||||
|
||||
@@ -81,7 +85,7 @@ int main() {
|
||||
w.flush();
|
||||
auto writtenSize = w.writtenBytesCount();
|
||||
|
||||
MyTypes::GameState res;
|
||||
MyTypes::GameState res{};
|
||||
Deserializer <InputAdapter> des { InputAdapter{buffer.begin(), writtenSize}, &mode};
|
||||
des.object(res);
|
||||
auto& r = AdapterAccess::getReader(des);
|
||||
|
||||
@@ -17,7 +17,7 @@ void serialize(S& s, MyStruct& o) {
|
||||
s.value4b(o.i);
|
||||
s.value2b(o.e);
|
||||
s.value8b(o.f);
|
||||
};
|
||||
}
|
||||
|
||||
using namespace bitsery;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ struct MyStruct {
|
||||
//now we can use flexible syntax with
|
||||
//member function has same name as parameter
|
||||
s.archive(this->s, i, vl, ll);
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ struct MyStruct {
|
||||
void serialize(S& s) {
|
||||
//now we can use flexible syntax with
|
||||
s.archive(i, e, fs);
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -15,8 +15,10 @@ namespace MyTypes {
|
||||
struct Vec3 { float x, y, z; };
|
||||
|
||||
struct Weapon {
|
||||
std::string name;
|
||||
int16_t damage;
|
||||
std::string name{};
|
||||
int16_t damage{};
|
||||
Weapon() = default;
|
||||
Weapon(const std::string& _name, int16_t dmg):name{_name}, damage{dmg} {}
|
||||
private:
|
||||
//define serialize function as private, and give access to bitsery
|
||||
friend bitsery::Access;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
function(LinkTestLib TargetName)
|
||||
|
||||
add_dependencies(${TargetName} googletest)
|
||||
|
||||
if(NOT WIN32 OR MINGW)
|
||||
FOREACH(LibName ${GTestLinkLibNames})
|
||||
target_link_libraries(${TargetName} ${GTestLibsDir}/lib${LibName}.a )
|
||||
@@ -9,7 +8,7 @@ function(LinkTestLib TargetName)
|
||||
else()
|
||||
FOREACH(LibName ${GTestLinkLibNames})
|
||||
target_link_libraries(${TargetName}
|
||||
debug ${GTestLibsDir}/DebugLibs/${CMAKE_FIND_LIBRARY_PREFIXES}${LibName}${CMAKE_FIND_LIBRARY_SUFFIXES}
|
||||
debug ${GTestLibsDir}/DebugLibs/${CMAKE_FIND_LIBRARY_PREFIXES}${LibName}d${CMAKE_FIND_LIBRARY_SUFFIXES}
|
||||
optimized ${GTestLibsDir}/ReleaseLibs/${CMAKE_FIND_LIBRARY_PREFIXES}${LibName}${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
ENDFOREACH()
|
||||
endif()
|
||||
|
||||
@@ -135,8 +135,8 @@ namespace bitsery {
|
||||
using TResizable = std::integral_constant<bool, traits::ContainerTraits<Container>::isResizable>;
|
||||
|
||||
Container &_buffer;
|
||||
TIterator _outIt;
|
||||
TIterator _end;
|
||||
TIterator _outIt{};
|
||||
TIterator _end{};
|
||||
|
||||
/*
|
||||
* resizable buffer
|
||||
@@ -153,12 +153,23 @@ namespace bitsery {
|
||||
|
||||
void writeInternal(const TValue *data, const size_t size, std::true_type) {
|
||||
//optimization
|
||||
#if defined(_MSC_VER) && (_ITERATOR_DEBUG_LEVEL > 0)
|
||||
using TDistance = typename std::iterator_traits<TIterator>::difference_type;
|
||||
if (std::distance(_outIt , _end) >= static_cast<TDistance>(size)) {
|
||||
std::memcpy(std::addressof(*_outIt), data, size);
|
||||
_outIt += size;
|
||||
#else
|
||||
auto tmp = _outIt;
|
||||
_outIt += size;
|
||||
if (std::distance(_outIt , _end) >= 0) {
|
||||
std::memcpy(std::addressof(*tmp), data, size);
|
||||
#endif
|
||||
} else {
|
||||
#if defined(_MSC_VER) && (_ITERATOR_DEBUG_LEVEL > 0)
|
||||
|
||||
#else
|
||||
_outIt -= size;
|
||||
#endif
|
||||
//get current position before invalidating iterators
|
||||
const auto pos = std::distance(std::begin(_buffer), _outIt);
|
||||
//increase container size
|
||||
|
||||
@@ -41,8 +41,13 @@ namespace bitsery {
|
||||
:_ios{istream} {}
|
||||
|
||||
void read(TValue* data, size_t size) {
|
||||
if (static_cast<size_t>(_ios.rdbuf()->sgetn( data , size )) != size)
|
||||
if (static_cast<size_t>(_ios.rdbuf()->sgetn( data , size )) != size) {
|
||||
*data = {};
|
||||
//check state, if not set by stream, set it manually
|
||||
if (_ios.good())
|
||||
_ios.setstate(std::ios_base::eofbit);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ReaderError error() const {
|
||||
@@ -58,7 +63,7 @@ namespace bitsery {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void setError(ReaderError error) {
|
||||
void setError(ReaderError ) {
|
||||
//has no effect when using
|
||||
}
|
||||
|
||||
|
||||
@@ -142,14 +142,15 @@ namespace bitsery {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void _swapDataBits(T *v, size_t count, std::false_type) {
|
||||
void _swapDataBits(T *, size_t , std::false_type) {
|
||||
//empty function because no swap is required
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename TReader>
|
||||
struct AdapterReaderBitPackingWrapper {
|
||||
class AdapterReaderBitPackingWrapper {
|
||||
public:
|
||||
//this is required by deserializer
|
||||
static constexpr bool BitPackingEnabled = true;
|
||||
//make TValue unsigned for bitpacking
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#define BITSERY_MAJOR_VERSION 4
|
||||
#define BITSERY_MINOR_VERSION 0
|
||||
#define BITSERY_PATCH_VERSION 0
|
||||
#define BITSERY_PATCH_VERSION 1
|
||||
|
||||
#define BITSERY_QUOTE_MACRO(name) #name
|
||||
#define BITSERY_BUILD_VERSION_STR(major,minor, patch) \
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace bitsery {
|
||||
: _reader{std::forward<ReaderParam>(r)},
|
||||
_context{context}
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
//copying disabled
|
||||
BasicDeserializer(const BasicDeserializer&) = delete;
|
||||
@@ -76,7 +76,7 @@ namespace bitsery {
|
||||
template<typename T, typename Fnc>
|
||||
void object(T &&obj, Fnc &&fnc) {
|
||||
fnc(std::forward<T>(obj));
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* functionality, that enables simpler serialization syntax, by including additional header
|
||||
@@ -117,7 +117,7 @@ namespace bitsery {
|
||||
static_assert(traits::ExtensionTraits<Ext,T>::SupportLambdaOverload,
|
||||
"extension doesn't support overload with lambda");
|
||||
extension.deserialize(*this, _reader, obj, std::forward<Fnc>(fnc));
|
||||
};
|
||||
}
|
||||
|
||||
template<size_t VSIZE, typename T, typename Ext>
|
||||
void ext(T &obj, const Ext &extension) {
|
||||
@@ -127,7 +127,7 @@ namespace bitsery {
|
||||
using ExtVType = typename traits::ExtensionTraits<Ext, T>::TValue;
|
||||
using VType = typename std::conditional<std::is_void<ExtVType>::value, details::DummyType, ExtVType>::type;
|
||||
extension.deserialize(*this, _reader, obj, [this](VType &v) { value<VSIZE>(v);});
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, typename Ext>
|
||||
void ext(T &obj, const Ext &extension) {
|
||||
@@ -137,7 +137,7 @@ namespace bitsery {
|
||||
using ExtVType = typename traits::ExtensionTraits<Ext, T>::TValue;
|
||||
using VType = typename std::conditional<std::is_void<ExtVType>::value, details::DummyType, ExtVType>::type;
|
||||
extension.deserialize(*this, _reader, obj, [this](VType &v) { object(v); });
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* boolValue
|
||||
@@ -263,16 +263,16 @@ namespace bitsery {
|
||||
void value8b(T &&v) { value<8>(std::forward<T>(v)); }
|
||||
|
||||
template<typename T, typename Ext>
|
||||
void ext1b(T &v, Ext &&extension) { ext<1, T, Ext>(v, std::forward<Ext>(extension)); };
|
||||
void ext1b(T &v, Ext &&extension) { ext<1, T, Ext>(v, std::forward<Ext>(extension)); }
|
||||
|
||||
template<typename T, typename Ext>
|
||||
void ext2b(T &v, Ext &&extension) { ext<2, T, Ext>(v, std::forward<Ext>(extension)); };
|
||||
void ext2b(T &v, Ext &&extension) { ext<2, T, Ext>(v, std::forward<Ext>(extension)); }
|
||||
|
||||
template<typename T, typename Ext>
|
||||
void ext4b(T &v, Ext &&extension) { ext<4, T, Ext>(v, std::forward<Ext>(extension)); };
|
||||
void ext4b(T &v, Ext &&extension) { ext<4, T, Ext>(v, std::forward<Ext>(extension)); }
|
||||
|
||||
template<typename T, typename Ext>
|
||||
void ext8b(T &v, Ext &&extension) { ext<8, T, Ext>(v, std::forward<Ext>(extension)); };
|
||||
void ext8b(T &v, Ext &&extension) { ext<8, T, Ext>(v, std::forward<Ext>(extension)); }
|
||||
|
||||
template<typename T>
|
||||
void text1b(T &str, size_t maxSize) { text<1>(str, maxSize); }
|
||||
@@ -328,7 +328,7 @@ namespace bitsery {
|
||||
void procContainer(It first, It last, std::false_type) {
|
||||
for (; first != last; ++first)
|
||||
value<VSIZE>(*first);
|
||||
};
|
||||
}
|
||||
|
||||
//process value types
|
||||
//true_type means, that we can copy whole buffer
|
||||
@@ -338,21 +338,21 @@ namespace bitsery {
|
||||
using TIntegral = typename details::IntegralFromFundamental<TValue>::TValue;
|
||||
if (first != last)
|
||||
_reader.template readBuffer<VSIZE>(reinterpret_cast<TIntegral*>(&(*first)), std::distance(first, last));
|
||||
};
|
||||
}
|
||||
|
||||
//process by calling functions
|
||||
template<typename It, typename Fnc>
|
||||
void procContainer(It first, It last, Fnc fnc) {
|
||||
for (; first != last; ++first)
|
||||
fnc(*first);
|
||||
};
|
||||
}
|
||||
|
||||
//process object types
|
||||
template<typename It>
|
||||
void procContainer(It first, It last) {
|
||||
for (; first != last; ++first)
|
||||
object(*first);
|
||||
};
|
||||
}
|
||||
|
||||
template <size_t VSIZE, typename T>
|
||||
void procText(T& str, size_t length) {
|
||||
@@ -421,7 +421,7 @@ namespace bitsery {
|
||||
des.object(value);
|
||||
auto& r = AdapterAccess::getReader(des);
|
||||
return {r.error(), r.isCompletedSuccessfully()};
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -117,31 +117,31 @@ namespace bitsery {
|
||||
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>
|
||||
void serialize(S &s, const MaxSize<T> &ms) {
|
||||
processMaxSize(s, ms.data, ms.maxSize, details::IsContainerTraitsDefined<typename std::decay<T>::type>{});
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace bitsery {
|
||||
struct NotDefinedType {
|
||||
//just swallow anything that is passed during creating
|
||||
template <typename ... T>
|
||||
NotDefinedType(T&& ...){};
|
||||
NotDefinedType(T&& ...){}
|
||||
NotDefinedType() = default;
|
||||
//define operators so that we also swallow deeper errors, to reduce error stack
|
||||
//this time will be used as iterator, so define all operators nessesarry to work with iterators
|
||||
|
||||
@@ -70,38 +70,88 @@ namespace bitsery {
|
||||
struct IsExtensionTraitsDefined:public IsDefined<typename traits::ExtensionTraits<Ext, T>::TValue> {
|
||||
};
|
||||
|
||||
//helper metafunction, that is added to c++17
|
||||
template<typename... Ts>
|
||||
struct make_void {
|
||||
typedef void type;
|
||||
};
|
||||
template<typename... Ts>
|
||||
using void_t = typename make_void<Ts...>::type;
|
||||
#ifdef _MSC_VER
|
||||
//helper types for HasSerializeFunction
|
||||
template <typename S, typename T>
|
||||
using TrySerializeFunction = decltype(serialize(std::declval<S &>(), std::declval<T &>()));
|
||||
|
||||
template <typename, typename, typename = void>
|
||||
struct HasSerializeFunction:std::false_type {};
|
||||
template <typename S, typename T>
|
||||
struct HasSerializeFunctionHelper {
|
||||
template <typename Q, typename R, typename = TrySerializeFunction<Q, R>>
|
||||
static std::true_type tester(Q&&, R&&);
|
||||
static std::false_type tester(...);
|
||||
using type = decltype(tester(std::declval<S>(), std::declval<T>()));
|
||||
};
|
||||
template <typename S, typename T>
|
||||
struct HasSerializeFunction :HasSerializeFunctionHelper<S, T>::type {};
|
||||
|
||||
template <typename S, typename T>
|
||||
struct HasSerializeFunction<S,T,
|
||||
void_t<decltype(serialize(std::declval<S &>(), std::declval<T &>()))>
|
||||
> : std::true_type {};
|
||||
//helper types for HasSerializeMethod
|
||||
template <typename S, typename T>
|
||||
using TrySerializeMethod = decltype(Access::serialize(std::declval<S &>(), std::declval<T &>()));
|
||||
|
||||
template <typename S, typename T>
|
||||
struct HasSerializeMethodHelper {
|
||||
template <typename Q, typename R, typename = TrySerializeMethod<Q, R>>
|
||||
static std::true_type tester(Q&&, R&&);
|
||||
static std::false_type tester(...);
|
||||
using type = decltype(tester(std::declval<S>(), std::declval<T>()));
|
||||
};
|
||||
template <typename S, typename T>
|
||||
struct HasSerializeMethod :HasSerializeMethodHelper<S, T>::type {};
|
||||
|
||||
//helper types for IsFlexibleIncluded
|
||||
template <typename S, typename T>
|
||||
using TryArchiveProcess = decltype(archiveProcess(std::declval<S &>(), std::declval<T &&>()));
|
||||
|
||||
template <typename S, typename T>
|
||||
struct IsFlexibleIncludedHelper {
|
||||
template <typename Q, typename R, typename = TryArchiveProcess<Q, R>>
|
||||
static std::true_type tester(Q&&, R&&);
|
||||
static std::false_type tester(...);
|
||||
using type = decltype(tester(std::declval<S>(), std::declval<T>()));
|
||||
};
|
||||
|
||||
template <typename S, typename T>
|
||||
struct IsFlexibleIncluded :IsFlexibleIncludedHelper<S, T>::type {};
|
||||
#else
|
||||
//helper metafunction, that is added to c++17
|
||||
template<typename... Ts>
|
||||
struct make_void {
|
||||
typedef void type;
|
||||
};
|
||||
template<typename... Ts>
|
||||
using void_t = typename make_void<Ts...>::type;
|
||||
|
||||
template <typename, typename, typename = void>
|
||||
struct HasSerializeFunction :std::false_type {};
|
||||
|
||||
template <typename S, typename T>
|
||||
struct HasSerializeFunction<S, T,
|
||||
void_t<decltype(serialize(std::declval<S &>(), std::declval<T &>()))>
|
||||
> : std::true_type {};
|
||||
|
||||
|
||||
template <typename, typename, typename = void>
|
||||
struct HasSerializeMethod:std::false_type {};
|
||||
template <typename, typename, typename = void>
|
||||
struct HasSerializeMethod :std::false_type {};
|
||||
|
||||
template <typename S, typename T>
|
||||
struct HasSerializeMethod<S, T,
|
||||
void_t<decltype(Access::serialize(std::declval<S &>(), std::declval<T &>()))>
|
||||
> : std::true_type {};
|
||||
|
||||
//this solution doesn't work with visual studio, but is more elegant
|
||||
template <typename, typename, typename = void>
|
||||
struct IsFlexibleIncluded :std::false_type {};
|
||||
|
||||
template <typename S, typename T>
|
||||
struct IsFlexibleIncluded<S, T,
|
||||
void_t<decltype(archiveProcess(std::declval<S &>(), std::declval<T &&>()))>
|
||||
> : std::true_type {};
|
||||
#endif
|
||||
|
||||
|
||||
template <typename S, typename T>
|
||||
struct HasSerializeMethod<S,T,
|
||||
void_t<decltype(Access::serialize(std::declval<S &>(), std::declval<T &>()))>
|
||||
> : std::true_type {};
|
||||
|
||||
template <typename, typename, typename = void>
|
||||
struct IsFlexibleIncluded:std::false_type {};
|
||||
|
||||
template <typename S, typename T>
|
||||
struct IsFlexibleIncluded<S,T,
|
||||
void_t<decltype(archiveProcess(std::declval<S &>(), std::declval<T &&>()))>
|
||||
> : std::true_type {};
|
||||
|
||||
//used for extensions, when extension TValue = void
|
||||
struct DummyType {
|
||||
@@ -177,10 +227,8 @@ namespace bitsery {
|
||||
struct ArchiveFunction {
|
||||
|
||||
static void invoke(S &s, T&& obj) {
|
||||
static_assert(IsFlexibleIncluded<S,T>::value,
|
||||
static_assert(IsFlexibleIncluded<S, T>::value,
|
||||
"\nPlease include '<bitsery/flexible.h>' to use 'archive' function:\n");
|
||||
// static_assert(HasSerializeFunction<S,T>::value || HasSerializeMethod<S,T>::value,
|
||||
// "\nPlease define 'serialize' function or include '<bitsery/flexible/...>' to use with 'archive'\n");
|
||||
|
||||
archiveProcess(s, std::forward<T>(obj));
|
||||
}
|
||||
|
||||
@@ -54,6 +54,13 @@ namespace bitsery {
|
||||
class SessionsWriter {
|
||||
public:
|
||||
|
||||
SessionsWriter() = default;
|
||||
SessionsWriter(const SessionsWriter&) = delete;
|
||||
SessionsWriter& operator = (const SessionsWriter& ) = delete;
|
||||
|
||||
SessionsWriter(SessionsWriter&&) = default;
|
||||
SessionsWriter& operator = (SessionsWriter&& ) = default;
|
||||
|
||||
void begin(TWriter& ) {
|
||||
//write position
|
||||
_sessionIndex.push(_sessions.size());
|
||||
@@ -65,7 +72,9 @@ namespace bitsery {
|
||||
//change position to session end
|
||||
auto sessionIt = std::next(std::begin(_sessions), _sessionIndex.top());
|
||||
_sessionIndex.pop();
|
||||
*sessionIt = writer.writtenBytesCount();
|
||||
auto sessionSize = writer.writtenBytesCount();
|
||||
assert(sessionSize > 0);
|
||||
*sessionIt = sessionSize;
|
||||
}
|
||||
|
||||
void flushSessions(TWriter& writer) {
|
||||
@@ -85,7 +94,7 @@ namespace bitsery {
|
||||
}
|
||||
private:
|
||||
std::vector<size_t> _sessions{};
|
||||
std::stack<size_t> _sessionIndex;
|
||||
std::stack<size_t> _sessionIndex{};
|
||||
};
|
||||
|
||||
template <typename TReader>
|
||||
@@ -100,6 +109,13 @@ namespace bitsery {
|
||||
_endItRef{details::SessionAccess::endIteratorRef<InputAdapter, TIterator>(adapter)}
|
||||
{
|
||||
}
|
||||
|
||||
SessionsReader(const SessionsReader&) = delete;
|
||||
SessionsReader& operator = (const SessionsReader& ) = delete;
|
||||
|
||||
SessionsReader(SessionsReader&&) = default;
|
||||
SessionsReader& operator = (SessionsReader&& ) = default;
|
||||
|
||||
void begin() {
|
||||
if (_sessions.empty()) {
|
||||
if (!initializeSessions())
|
||||
@@ -125,7 +141,7 @@ namespace bitsery {
|
||||
} else {
|
||||
//there is no data to read anymore
|
||||
//pos == end or buffer overflow while session is active
|
||||
if (!(_posItRef == _endItRef || _reader.error() == ReaderError::NoError)) {
|
||||
if (!(_posItRef == _endItRef || _reader.error() == ReaderError::NoError) || !(_sessionsStack.size() > 1)) {
|
||||
_reader.setError(ReaderError::InvalidData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace bitsery {
|
||||
++index;
|
||||
}
|
||||
return 0u;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace ext {
|
||||
@@ -57,7 +57,7 @@ namespace bitsery {
|
||||
};
|
||||
|
||||
template<typename Ser, typename Writer, typename T, typename Fnc>
|
||||
void serialize(Ser &s, Writer &writer, const T &obj, Fnc &&fnc) const {
|
||||
void serialize(Ser &s, Writer &, const T &obj, Fnc &&fnc) const {
|
||||
assert(traits::ContainerTraits<TContainer>::size(_values) > 0);
|
||||
auto index = details::findEntropyIndex(obj, _values);
|
||||
s.ext(index, ext::ValueRange<size_t>{0u, traits::ContainerTraits<TContainer>::size(_values)});
|
||||
@@ -68,7 +68,7 @@ namespace bitsery {
|
||||
}
|
||||
|
||||
template<typename Des, typename Reader, typename T, typename Fnc>
|
||||
void deserialize(Des &d, Reader &reader, T &obj, Fnc &&fnc) const {
|
||||
void deserialize(Des &d, Reader &, T &obj, Fnc &&fnc) const {
|
||||
assert(traits::ContainerTraits<TContainer>::size(_values) > 0);
|
||||
size_t index{};
|
||||
d.ext(index, ext::ValueRange<size_t>{0u, traits::ContainerTraits<TContainer>::size(_values)});
|
||||
|
||||
@@ -34,14 +34,14 @@ namespace bitsery {
|
||||
public:
|
||||
|
||||
template<typename Ser, typename Writer, typename T, typename Fnc>
|
||||
void serialize(Ser &s, Writer &writer, const T &obj, Fnc &&fnc) const {
|
||||
void serialize(Ser &, Writer &writer, const T &obj, Fnc &&fnc) const {
|
||||
writer.beginSession();
|
||||
fnc(const_cast<T&>(obj));
|
||||
writer.endSession();
|
||||
}
|
||||
|
||||
template<typename Des, typename Reader, typename T, typename Fnc>
|
||||
void deserialize(Des &d, Reader &reader, T &obj, Fnc &&fnc) const {
|
||||
void deserialize(Des &, Reader &reader, T &obj, Fnc &&fnc) const {
|
||||
reader.beginSession();
|
||||
fnc(obj);
|
||||
reader.endSession();
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace bitsery {
|
||||
obj.reserve(size);
|
||||
}
|
||||
template <typename T>
|
||||
void reserve(T obj, size_t size) const {
|
||||
void reserve(T& , size_t ) const {
|
||||
//for ordered container do nothing
|
||||
}
|
||||
size_t _maxSize;
|
||||
|
||||
@@ -108,13 +108,13 @@ namespace bitsery {
|
||||
template<typename T, typename std::enable_if<std::is_integral<T>::value>::type * = nullptr>
|
||||
details::SameSizeUnsigned<T> getRangeValue(const T &v, const RangeSpec<T> &r) {
|
||||
return static_cast<details::SameSizeUnsigned<T>>(v - r.min);
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<std::is_enum<T>::value>::type * = nullptr>
|
||||
details::SameSizeUnsigned<T> getRangeValue(const T &v, const RangeSpec<T> &r) {
|
||||
using VT = details::SameSizeUnsigned<T>;
|
||||
return static_cast<VT>(static_cast<VT>(v) - static_cast<VT>(r.min));
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
|
||||
details::SameSizeUnsigned<T> getRangeValue(const T &v, const RangeSpec<T> &r) {
|
||||
@@ -122,18 +122,18 @@ namespace bitsery {
|
||||
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);
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<std::is_integral<T>::value>::type * = nullptr>
|
||||
void setRangeValue(T &v, const RangeSpec<T> &r) {
|
||||
v += r.min;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<std::is_enum<T>::value>::type * = nullptr>
|
||||
void setRangeValue(T &v, const RangeSpec<T> &r) {
|
||||
using VT = typename std::underlying_type<T>::type;
|
||||
reinterpret_cast<VT &>(v) += static_cast<VT>(r.min);
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
|
||||
void setRangeValue(T &v, const RangeSpec<T> &r) {
|
||||
@@ -141,7 +141,7 @@ namespace bitsery {
|
||||
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);
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
|
||||
bool isRangeValid(const T &v, const RangeSpec<T> &r) {
|
||||
@@ -163,7 +163,7 @@ namespace bitsery {
|
||||
public:
|
||||
|
||||
template<typename ... Args>
|
||||
explicit constexpr ValueRange(Args &&... args):_range{std::forward<Args>(args)...} {};
|
||||
explicit constexpr ValueRange(Args &&... args):_range{std::forward<Args>(args)...} {}
|
||||
|
||||
template<typename Ser, typename Writer, typename T, typename Fnc>
|
||||
void serialize(Ser &, Writer &writer, const T &v, Fnc &&) const {
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace bitsery {
|
||||
template<typename S, typename T>
|
||||
void archiveProcessImpl(S &s, T &&head, std::true_type) {
|
||||
s.object(std::forward<T>(head));
|
||||
};
|
||||
}
|
||||
|
||||
//overload when T is rvalue type, only allowable for behaviour modifying functions for deserializer
|
||||
template<typename S, typename T>
|
||||
@@ -43,7 +43,7 @@ namespace bitsery {
|
||||
static_assert(std::is_base_of<ArchiveWrapperFnc, T>::value,
|
||||
"\nOnly archive behaviour modifying functions can be passed by rvalue to deserializer\n");
|
||||
serialize(s, head);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -57,12 +57,12 @@ namespace bitsery {
|
||||
template<typename T, size_t N>
|
||||
flexible::CArray<T, N, true> asText(T (&str)[N]) {
|
||||
return {str};
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
flexible::CArray<T, N, false> asContainer(T (&obj)[N]) {
|
||||
return {obj};
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
flexible::MaxSize<T> maxSize(T& obj, size_t max) {
|
||||
@@ -78,21 +78,21 @@ namespace bitsery {
|
||||
template<typename S, typename T, typename std::enable_if<details::IsFundamentalType<T>::value>::type * = nullptr>
|
||||
void serialize(S &s, T &v) {
|
||||
s.template value<sizeof(T)>(v);
|
||||
};
|
||||
}
|
||||
|
||||
//define serialization for c-style container
|
||||
|
||||
//if array is integral type, specify explicitly how to process: as text or container
|
||||
template<typename S, typename T, size_t N, typename std::enable_if<std::is_integral<T>::value>::type * = nullptr>
|
||||
void serialize(S &s, T (&obj)[N]) {
|
||||
void serialize(S &, T (&)[N]) {
|
||||
static_assert(N == 0,
|
||||
"\nPlease use 'asText(obj)' or 'asContainer(obj)' when using c-style array with integral types\n");
|
||||
};
|
||||
}
|
||||
|
||||
template<typename S, typename T, size_t N, typename std::enable_if<!std::is_integral<T>::value>::type * = nullptr>
|
||||
void serialize(S &s, T (&obj)[N]) {
|
||||
flexible::processContainer(s, obj);
|
||||
};
|
||||
}
|
||||
|
||||
//this is a helper class that enforce fundamental type sizes, when used on multiple platforms
|
||||
template <size_t TShort, size_t TInt, size_t TLong, size_t TLongLong>
|
||||
@@ -103,7 +103,7 @@ namespace bitsery {
|
||||
static_assert(sizeof(long) == TLong, "");
|
||||
static_assert(sizeof(long long) == TLongLong, "");
|
||||
//for completion we also need pointer type size, but serializer doesn't support pointer serialization.
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace bitsery {
|
||||
: _writer{std::forward<WriterParam>(w)},
|
||||
_context{context}
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
//copying disabled
|
||||
BasicSerializer(const BasicSerializer&) = delete;
|
||||
@@ -73,7 +73,7 @@ namespace bitsery {
|
||||
template<typename T, typename Fnc>
|
||||
void object(const T &obj, Fnc &&fnc) {
|
||||
fnc(const_cast<T& >(obj));
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* functionality, that enables simpler serialization syntax, by including additional header
|
||||
@@ -114,7 +114,7 @@ namespace bitsery {
|
||||
static_assert(traits::ExtensionTraits<Ext,T>::SupportLambdaOverload,
|
||||
"extension doesn't support overload with lambda");
|
||||
extension.serialize(*this, _writer, obj, std::forward<Fnc>(fnc));
|
||||
};
|
||||
}
|
||||
|
||||
template<size_t VSIZE, typename T, typename Ext>
|
||||
void ext(const T &obj, const Ext &extension) {
|
||||
@@ -124,7 +124,7 @@ namespace bitsery {
|
||||
using ExtVType = typename traits::ExtensionTraits<Ext, T>::TValue;
|
||||
using VType = typename std::conditional<std::is_void<ExtVType>::value, details::DummyType, ExtVType>::type;
|
||||
extension.serialize(*this, _writer, obj, [this](VType &v) { value<VSIZE>(v); });
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, typename Ext>
|
||||
void ext(const T &obj, const Ext &extension) {
|
||||
@@ -134,7 +134,7 @@ namespace bitsery {
|
||||
using ExtVType = typename traits::ExtensionTraits<Ext, T>::TValue;
|
||||
using VType = typename std::conditional<std::is_void<ExtVType>::value, details::DummyType, ExtVType>::type;
|
||||
extension.serialize(*this, _writer, obj, [this](VType &v) { object(v); });
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* boolValue
|
||||
@@ -259,16 +259,16 @@ namespace bitsery {
|
||||
void value8b(T &&v) { value<8>(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)); };
|
||||
void ext1b(const T &v, Ext &&extension) { ext<1, T, Ext>(v, std::forward<Ext>(extension)); }
|
||||
|
||||
template<typename T, typename Ext>
|
||||
void ext2b(const T &v, Ext &&extension) { ext<2, T, Ext>(v, std::forward<Ext>(extension)); };
|
||||
void ext2b(const T &v, Ext &&extension) { ext<2, T, Ext>(v, std::forward<Ext>(extension)); }
|
||||
|
||||
template<typename T, typename Ext>
|
||||
void ext4b(const T &v, Ext &&extension) { ext<4, T, Ext>(v, std::forward<Ext>(extension)); };
|
||||
void ext4b(const T &v, Ext &&extension) { ext<4, T, Ext>(v, std::forward<Ext>(extension)); }
|
||||
|
||||
template<typename T, typename Ext>
|
||||
void ext8b(const T &v, Ext &&extension) { ext<8, T, Ext>(v, std::forward<Ext>(extension)); };
|
||||
void ext8b(const T &v, Ext &&extension) { ext<8, T, Ext>(v, std::forward<Ext>(extension)); }
|
||||
|
||||
template<typename T>
|
||||
void text1b(const T &str, size_t maxSize) { text<1>(str, maxSize); }
|
||||
@@ -324,7 +324,7 @@ namespace bitsery {
|
||||
void procContainer(It first, It last, std::false_type) {
|
||||
for (; first != last; ++first)
|
||||
value<VSIZE>(*first);
|
||||
};
|
||||
}
|
||||
|
||||
//process value types
|
||||
//true_type means, that we can copy whole buffer
|
||||
@@ -335,7 +335,7 @@ namespace bitsery {
|
||||
if (first != last)
|
||||
_writer.template writeBuffer<VSIZE>(reinterpret_cast<const TIntegral*>(&(*first)),
|
||||
static_cast<size_t>(std::distance(first, last)));
|
||||
};
|
||||
}
|
||||
|
||||
//process by calling functions
|
||||
template<typename It, typename Fnc>
|
||||
@@ -344,7 +344,7 @@ namespace bitsery {
|
||||
for (; first != last; ++first) {
|
||||
fnc(const_cast<TValue&>(*first));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//process text,
|
||||
template<size_t VSIZE, typename T>
|
||||
@@ -354,14 +354,14 @@ namespace bitsery {
|
||||
details::writeSize(_writer, length);
|
||||
auto begin = std::begin(str);
|
||||
procContainer<VSIZE>(begin, std::next(begin, length), std::integral_constant<bool, traits::ContainerTraits<T>::isContiguous>{});
|
||||
};
|
||||
}
|
||||
|
||||
//process object types
|
||||
template<typename It>
|
||||
void procContainer(It first, It last) {
|
||||
for (; first != last; ++first)
|
||||
object(*first);
|
||||
};
|
||||
}
|
||||
|
||||
//proc bool writing bit or byte, depending on if BitPackingEnabled or not
|
||||
void procBoolValue(bool v, std::true_type) {
|
||||
@@ -413,7 +413,7 @@ namespace bitsery {
|
||||
auto& w = AdapterAccess::getWriter(ser);
|
||||
w.flush();
|
||||
return w.writtenBytesCount();
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t quickMeasureSize(const T& value) {
|
||||
|
||||
@@ -62,12 +62,12 @@ namespace bitsery {
|
||||
//contiguous hopefully will be available in c++20
|
||||
static constexpr bool isContiguous = false;
|
||||
//resize function, called only if container is resizable
|
||||
static void resize(T& container, size_t size) {
|
||||
static void resize(T& , size_t ) {
|
||||
static_assert(std::is_void<T>::value,
|
||||
"Define ContainerTraits or include from <bitsery/traits/...> to use as container");
|
||||
}
|
||||
//get container size
|
||||
static size_t size(const T& container) {
|
||||
static size_t size(const T& ) {
|
||||
static_assert(std::is_void<T>::value,
|
||||
"Define ContainerTraits or include from <bitsery/traits/...> to use as container");
|
||||
return 0u;
|
||||
@@ -80,7 +80,7 @@ namespace bitsery {
|
||||
using TValue = T;
|
||||
static constexpr bool isResizable = false;
|
||||
static constexpr bool isContiguous = true;
|
||||
static size_t size(const T (&container)[N]) {
|
||||
static size_t size(const T (&)[N]) {
|
||||
return N;
|
||||
}
|
||||
};
|
||||
@@ -106,7 +106,7 @@ namespace bitsery {
|
||||
static constexpr bool addNUL = true;
|
||||
|
||||
//get length of null terminated container
|
||||
static size_t length(const T& container) {
|
||||
static size_t length(const T& ) {
|
||||
static_assert(std::is_void<T>::value,
|
||||
"Define TextTraits or include from <bitsery/traits/...> to use as text");
|
||||
return 0u;
|
||||
@@ -124,7 +124,7 @@ namespace bitsery {
|
||||
//instead of using back_insert_iterator to append each byte to buffer.
|
||||
//thats why Writer return range iterators
|
||||
|
||||
static void increaseBufferSize(T& container) {
|
||||
static void increaseBufferSize(T& ) {
|
||||
static_assert(std::is_void<T>::value,
|
||||
"Define BufferAdapterTraits or include from <bitsery/traits/...> to use as buffer adapter container");
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ TEST(AdapterIOStream, ReadingMoreThanAvailableReturnsZero) {
|
||||
}
|
||||
|
||||
//this is strange, but probably stringstream doesnt use any of the base methods that sets io_base::iostate flags
|
||||
TEST(AdapterIOStream, WhenReadingStringStreamThenErrorCodeAlwaysReturnsNoError) {
|
||||
TEST(AdapterIOStream, WhenReadingMoreThanAvailableThenDataOverflow) {
|
||||
//setup data
|
||||
uint8_t t1 = 111;
|
||||
|
||||
@@ -103,7 +103,9 @@ TEST(AdapterIOStream, WhenReadingStringStreamThenErrorCodeAlwaysReturnsNoError)
|
||||
EXPECT_THAT(r.error(), Eq(bitsery::ReaderError::NoError));
|
||||
EXPECT_THAT(r1, Eq(t1));
|
||||
r.readBytes<1>(r1);
|
||||
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));
|
||||
EXPECT_THAT(r.isCompletedSuccessfully(), Eq(false));
|
||||
EXPECT_THAT(r.error(), Eq(bitsery::ReaderError::DataOverflow));
|
||||
|
||||
}
|
||||
@@ -56,19 +56,19 @@ using InverseReader = bitsery::AdapterReader<InputAdapter, InverseEndiannessConf
|
||||
TEST(DataEndianness, WhenWriteBytesThenBytesAreSwapped) {
|
||||
//fill initial values
|
||||
IntegralTypes src{};
|
||||
src.a = 0x1122334455667788;
|
||||
src.a = static_cast<int64_t>(0x1122334455667788);
|
||||
src.b = 0xBBCCDDEE;
|
||||
src.c = 0xCCDD;
|
||||
src.d = 0xDD;
|
||||
src.e = 0xEE;
|
||||
src.c = static_cast<int16_t>(0xCCDD);
|
||||
src.d = static_cast<uint8_t>(0xDD);
|
||||
src.e = static_cast<int8_t>(0xEE);
|
||||
|
||||
//fill expected result after swap
|
||||
IntegralTypes resInv{};
|
||||
resInv.a = 0x8877665544332211;
|
||||
resInv.a = static_cast<int64_t>(0x8877665544332211);
|
||||
resInv.b = 0xEEDDCCBB;
|
||||
resInv.c = 0xDDCC;
|
||||
resInv.d = 0xDD;
|
||||
resInv.e = 0xEE;
|
||||
resInv.c = static_cast<int16_t>(0xDDCC);
|
||||
resInv.d = static_cast<uint8_t>(0xDD);
|
||||
resInv.e = static_cast<int8_t>(0xEE);
|
||||
|
||||
//create and write to buffer
|
||||
Buffer buf{};
|
||||
@@ -136,7 +136,7 @@ TEST(DataEndianness, WhenWriteMoreThan1ByteValuesThenValuesAreSwapped) {
|
||||
template <typename T>
|
||||
constexpr size_t getBits(T v) {
|
||||
return bitsery::details::calcRequiredBits<T>({}, v);
|
||||
};
|
||||
}
|
||||
|
||||
struct IntegralUnsignedTypes {
|
||||
uint64_t a;
|
||||
|
||||
@@ -43,7 +43,7 @@ struct IntegralUnsignedTypes {
|
||||
template <typename T>
|
||||
constexpr size_t getBits(T v) {
|
||||
return bitsery::details::calcRequiredBits<T>({}, v);
|
||||
};
|
||||
}
|
||||
|
||||
// *** bits operations
|
||||
|
||||
@@ -285,6 +285,53 @@ TEST(DataBitsAndBytesOperations, WriteAndReadBytes) {
|
||||
|
||||
}
|
||||
|
||||
TEST(DataBitsAndBytesOperations, WriteAndReadBytesWithBitPackingWrapper) {
|
||||
//setup data
|
||||
IntegralTypes data;
|
||||
data.a = -4894541654564;
|
||||
data.b = 94545646;
|
||||
data.c = -8778;
|
||||
data.d = 200;
|
||||
data.e = -98;
|
||||
data.f[0] = 43;
|
||||
data.f[1] = -45;
|
||||
|
||||
//create and write to buffer
|
||||
Buffer buf{};
|
||||
Writer bw{buf};
|
||||
AdapterBitPackingWriter bpw{bw};
|
||||
bpw.writeBytes<4>(data.b);
|
||||
bpw.writeBytes<2>(data.c);
|
||||
bpw.writeBytes<1>(data.d);
|
||||
bpw.writeBytes<8>(data.a);
|
||||
bpw.writeBytes<1>(data.e);
|
||||
bpw.writeBuffer<1>(data.f, 2);
|
||||
bpw.flush();
|
||||
auto writtenSize = bpw.writtenBytesCount();
|
||||
|
||||
EXPECT_THAT(writtenSize, Eq(18));
|
||||
//read from buffer
|
||||
Reader br{InputAdapter{buf.begin(), writtenSize}};
|
||||
AdapterBitPackingReader bpr{br};
|
||||
IntegralTypes res{};
|
||||
bpr.readBytes<4>(res.b);
|
||||
bpr.readBytes<2>(res.c);
|
||||
bpr.readBytes<1>(res.d);
|
||||
bpr.readBytes<8>(res.a);
|
||||
bpr.readBytes<1>(res.e);
|
||||
bpr.readBuffer<1>(res.f, 2);
|
||||
EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError));
|
||||
//assert results
|
||||
|
||||
EXPECT_THAT(data.a, Eq(res.a));
|
||||
EXPECT_THAT(data.b, Eq(res.b));
|
||||
EXPECT_THAT(data.c, Eq(res.c));
|
||||
EXPECT_THAT(data.d, Eq(res.d));
|
||||
EXPECT_THAT(data.e, Eq(res.e));
|
||||
EXPECT_THAT(data.f, ContainerEq(res.f));
|
||||
|
||||
}
|
||||
|
||||
TEST(DataBitsAndBytesOperations, ReadWriteFncCanAcceptSignedData) {
|
||||
//setup data
|
||||
constexpr size_t DATA_SIZE = 3;
|
||||
|
||||
@@ -114,8 +114,22 @@ TEST(DataReadingErrors, WhenInitializingSessionsWhereSessionsDataOffsetIsCorrupt
|
||||
SessionsEnabledWriter bw{buf};
|
||||
bw.writeBytes<1>(uint8_t{1});
|
||||
bw.writeBytes<1>(uint8_t{1});
|
||||
bw.writeBytes<2>(uint16_t{10});
|
||||
bw.writeBytes<4>(uint32_t{10});
|
||||
SessionsEnabledReader br{InputAdapter{buf.begin(), bw.writtenBytesCount()}};
|
||||
br.beginSession();
|
||||
EXPECT_THAT(br.error(), Eq(bitsery::ReaderError::InvalidData));
|
||||
}
|
||||
|
||||
TEST(DataReadingErrors, WhenReadingNewSessionOutsideSessionThenInvalidData) {
|
||||
Buffer buf{};
|
||||
SessionsEnabledWriter bw{buf};
|
||||
bw.beginSession();
|
||||
bw.writeBytes<1>(uint8_t{1});
|
||||
bw.endSession();
|
||||
bw.flush();
|
||||
SessionsEnabledReader br{InputAdapter{buf.begin(), bw.writtenBytesCount()}};
|
||||
br.beginSession();
|
||||
br.endSession();
|
||||
br.beginSession();
|
||||
EXPECT_THAT(br.error(), Eq(bitsery::ReaderError::InvalidData));
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ TEST(FlexibleSyntax, FundamentalTypesAndBool) {
|
||||
float tf = 485.042f;
|
||||
double_t td = -454184.48445;
|
||||
bool tb=true;
|
||||
SerializationContext ctx;
|
||||
SerializationContext ctx{};
|
||||
ctx.createSerializer().archive(ti,te,tf,td,tb);
|
||||
|
||||
//result
|
||||
|
||||
@@ -33,7 +33,7 @@ using Deserializer = bitsery::BasicDeserializer<bitsery::AdapterReaderBitPacking
|
||||
|
||||
TEST(SerializeBooleans, BoolAsBit) {
|
||||
|
||||
SerializationContext ctx;
|
||||
SerializationContext ctx{};
|
||||
bool t1{true};
|
||||
bool t2{false};
|
||||
bool res1;
|
||||
|
||||
@@ -163,7 +163,7 @@ TYPED_TEST(SerializeContainerDynamicSizeCompositeTypes, CustomFunctionThatDoNoth
|
||||
SerializationContext ctx{};
|
||||
using TValue = typename TestFixture::TValue;
|
||||
|
||||
auto emptyFnc = [](TValue &v) {};
|
||||
auto emptyFnc = [](TValue &) {};
|
||||
ctx.createSerializer().container(this->src, 1000, emptyFnc);
|
||||
ctx.createDeserializer().container(this->res, 1000, emptyFnc);
|
||||
|
||||
@@ -217,7 +217,7 @@ TYPED_TEST(SerializeContainerFixedSizeCompositeTypes, DefaultSerializationFuncti
|
||||
Container src{MyStruct1{0, 1}, MyStruct1{8, 9}, MyStruct1{11, 34}, MyStruct1{5134, 1532}};
|
||||
Container res{};
|
||||
|
||||
SerializationContext ctx;
|
||||
SerializationContext ctx{};
|
||||
ctx.createSerializer().container(src);
|
||||
ctx.createDeserializer().container(res);
|
||||
|
||||
@@ -232,7 +232,7 @@ TYPED_TEST(SerializeContainerFixedSizeCompositeTypes, CustomFunctionThatSerializ
|
||||
|
||||
using TValue = decltype(*std::begin(res));
|
||||
|
||||
SerializationContext ctx;
|
||||
SerializationContext ctx{};
|
||||
auto& ser = ctx.createSerializer();
|
||||
ser.container(src, [&ser](TValue &v) {
|
||||
char tmp{};
|
||||
|
||||
@@ -37,9 +37,8 @@ using BPDes = bitsery::BasicDeserializer<bitsery::AdapterReaderBitPackingWrapper
|
||||
TEST(SerializeExtensionEntropy, WhenEntropyEncodedThenOnlyWriteIndexUsingMinRequiredBits) {
|
||||
int32_t v = 4849;
|
||||
int32_t res;
|
||||
constexpr size_t N = 3;
|
||||
int32_t values[3] = {485,4849,89};
|
||||
SerializationContext ctx;
|
||||
SerializationContext ctx{};
|
||||
ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) {
|
||||
ser.ext4b(v, Entropy<int32_t[3]>{values});
|
||||
});
|
||||
@@ -50,12 +49,12 @@ TEST(SerializeExtensionEntropy, WhenEntropyEncodedThenOnlyWriteIndexUsingMinRequ
|
||||
EXPECT_THAT(res, Eq(v));
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
|
||||
|
||||
SerializationContext ctx1;
|
||||
SerializationContext ctx1{};
|
||||
ctx1.createSerializer().enableBitPacking([&v, &values](BPSer& ser) {
|
||||
ser.ext4b(v, Entropy<int32_t[3]>{values});
|
||||
});
|
||||
ctx1.createDeserializer().enableBitPacking([&res](BPDes& des) {
|
||||
des.ext(res, bitsery::ext::ValueRange<int32_t>{0, static_cast<int32_t>(N + 1)});
|
||||
des.ext(res, bitsery::ext::ValueRange<int32_t>{0, static_cast<int32_t>(3 + 1)});
|
||||
});
|
||||
EXPECT_THAT(res, Eq(2));
|
||||
}
|
||||
@@ -64,7 +63,7 @@ TEST(SerializeExtensionEntropy, WhenNoEntropyEncodedThenWriteZeroBitsAndValueOrO
|
||||
int16_t v = 8945;
|
||||
int16_t res;
|
||||
std::initializer_list<int> values{485,4849,89};
|
||||
SerializationContext ctx;
|
||||
SerializationContext ctx{};
|
||||
ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) {
|
||||
ser.ext2b(v, Entropy<std::initializer_list<int>>{values});
|
||||
});
|
||||
@@ -84,12 +83,12 @@ TEST(SerializeExtensionEntropy, CustomTypeEntropyEncoded) {
|
||||
MyStruct1 values[N]{
|
||||
MyStruct1{12, 10}, MyStruct1{485, 454},
|
||||
MyStruct1{4849, 89}, MyStruct1{0, 1}};
|
||||
SerializationContext ctx;
|
||||
SerializationContext ctx{};
|
||||
ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) {
|
||||
ser.ext(v, Entropy<MyStruct1[N]>{values});
|
||||
ser.ext(v, Entropy<MyStruct1[4]>{values});
|
||||
});
|
||||
ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) {
|
||||
des.ext(res, Entropy<MyStruct1[N]>{values});
|
||||
des.ext(res, Entropy<MyStruct1[4]>{values});
|
||||
});
|
||||
EXPECT_THAT(res, Eq(v));
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
|
||||
@@ -102,7 +101,7 @@ TEST(SerializeExtensionEntropy, CustomTypeNotEntropyEncoded) {
|
||||
std::initializer_list<MyStruct1> values {
|
||||
MyStruct1{12,10}, MyStruct1{485, 454},
|
||||
MyStruct1{4849,89}, MyStruct1{0,1}};
|
||||
SerializationContext ctx;
|
||||
SerializationContext ctx{};
|
||||
ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) {
|
||||
ser.ext(v, Entropy<std::initializer_list<MyStruct1>>{values});
|
||||
});
|
||||
|
||||
@@ -46,10 +46,15 @@ struct DataV3 {
|
||||
|
||||
TEST(SerializeExtensionGrowable, WriteSessionsDataAtBufferEndAfterFlush) {
|
||||
BasicSerializationContext<SessionsEnabledConfig> ctx;
|
||||
ctx.createSerializer().ext(int8_t{}, Growable{}, [] (int8_t& v) { });
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(0));
|
||||
auto& ser = ctx.createSerializer();
|
||||
//session cannot be empty
|
||||
ser.ext(int8_t{}, Growable{}, [&ser] (int8_t& v) {
|
||||
ser.value1b(v);
|
||||
});
|
||||
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
|
||||
ctx.bw->flush();
|
||||
EXPECT_THAT(ctx.getBufferSize(), Gt(0));
|
||||
EXPECT_THAT(ctx.getBufferSize(), Gt(1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ TEST(SerializeExtensionStdQueue, QueueDefaultContainer) {
|
||||
t1.push(-4854);
|
||||
std::queue<int32_t> r1{};
|
||||
|
||||
SerializationContext ctx1;
|
||||
SerializationContext ctx1{};
|
||||
test(ctx1,t1, r1);
|
||||
EXPECT_THAT(t1, Eq(r1));
|
||||
}
|
||||
@@ -67,7 +67,7 @@ TEST(SerializeExtensionStdQueue, QueueVectorContainer) {
|
||||
t1.push(-4854);
|
||||
std::queue<int32_t, std::vector<int32_t>> r1{};
|
||||
|
||||
SerializationContext ctx1;
|
||||
SerializationContext ctx1{};
|
||||
test(ctx1,t1, r1);
|
||||
EXPECT_THAT(t1, Eq(r1));
|
||||
}
|
||||
@@ -78,7 +78,7 @@ TEST(SerializeExtensionStdQueue, PriorityQueueDefaultContainer) {
|
||||
t1.push(-4854);
|
||||
std::priority_queue<int32_t> r1{};
|
||||
|
||||
SerializationContext ctx1;
|
||||
SerializationContext ctx1{};
|
||||
test(ctx1,t1, r1);
|
||||
auto & ct1 = PriorityQueueCnt<int32_t, std::vector<int32_t>>::getContainer(t1);
|
||||
auto & cr1 = PriorityQueueCnt<int32_t, std::vector<int32_t>>::getContainer(r1);
|
||||
@@ -91,7 +91,7 @@ TEST(SerializeExtensionStdQueue, PriorityQueueDequeContainer) {
|
||||
t1.push(-44);
|
||||
std::priority_queue<int32_t, std::deque<int32_t>> r1{};
|
||||
|
||||
SerializationContext ctx1;
|
||||
SerializationContext ctx1{};
|
||||
test(ctx1,t1, r1);
|
||||
auto & ct1 = PriorityQueueCnt<int32_t, std::deque<int32_t>>::getContainer(t1);
|
||||
auto & cr1 = PriorityQueueCnt<int32_t, std::deque<int32_t>>::getContainer(r1);
|
||||
|
||||
@@ -43,10 +43,10 @@ struct X {
|
||||
|
||||
struct Y {
|
||||
int y{};
|
||||
int carr[3];
|
||||
std::array<int, 3> arr;
|
||||
std::vector<X> vx;
|
||||
std::string s;
|
||||
int carr[3]{};
|
||||
std::array<int, 3> arr{};
|
||||
std::vector<X> vx{};
|
||||
std::string s{};
|
||||
};
|
||||
struct Z { X x{}; Y y{}; };
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ bool SerializeDeserializeContainerSize(SerializationContext& ctx, const size_t s
|
||||
}
|
||||
|
||||
TEST(SerializeSize, WhenLengthLessThan128Then1Byte) {
|
||||
SerializationContext ctx1;
|
||||
SerializationContext ctx1{};
|
||||
EXPECT_TRUE(SerializeDeserializeContainerSize(ctx1, 127));
|
||||
EXPECT_THAT(ctx1.getBufferSize(), Eq(1));
|
||||
SerializationContext ctx2;
|
||||
|
||||
@@ -100,13 +100,14 @@ using Reader = bitsery::AdapterReader<InputAdapter, bitsery::DefaultConfig>;
|
||||
template <typename Config = bitsery::DefaultConfig>
|
||||
class BasicSerializationContext {
|
||||
public:
|
||||
Buffer buf;
|
||||
using TWriter = bitsery::AdapterWriter<OutputAdapter, Config>;
|
||||
using TReader = bitsery::AdapterReader<InputAdapter, Config>;
|
||||
std::unique_ptr<bitsery::BasicSerializer<TWriter>> ser;
|
||||
std::unique_ptr<bitsery::BasicDeserializer<TReader>> des;
|
||||
TWriter* bw;
|
||||
TReader* br;
|
||||
|
||||
Buffer buf{};
|
||||
std::unique_ptr<bitsery::BasicSerializer<TWriter>> ser{};
|
||||
std::unique_ptr<bitsery::BasicDeserializer<TReader>> des{};
|
||||
TWriter* bw{};
|
||||
TReader* br{};
|
||||
|
||||
bitsery::BasicSerializer<TWriter>& createSerializer() {
|
||||
if (!ser) {
|
||||
|
||||
@@ -110,10 +110,12 @@ TEST(SerializeText, CArraySerializesTextLength) {
|
||||
EXPECT_THAT(r1, ContainerEq(t1));
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
TEST(SerializeText, WhenCArrayNotNullterminatedThenAssert) {
|
||||
SerializationContext ctx;
|
||||
char16_t t1[CARR_LENGTH]{u"some text"};
|
||||
//make last character not nullterminated
|
||||
t1[CARR_LENGTH-1] = 'x';
|
||||
EXPECT_DEATH(ctx.createSerializer().text<2>(t1), "");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user