mirror of
https://github.com/fraillt/bitsery.git
synced 2026-08-21 02:28:36 +00:00
added more std containers
This commit is contained in:
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,4 +1,4 @@
|
||||
# [3.0.0](https://github.com/fraillt/bitsery/compare/v2.0.1...v3.0.0) (2017-09-21)
|
||||
# [4.0.0](https://github.com/fraillt/bitsery/compare/v3.0.0...v4.0.0) (2017-10-02)
|
||||
|
||||
new flexible syntax
|
||||
traits changed,
|
||||
@@ -6,6 +6,14 @@ traits changed,
|
||||
text is separate from container, only has length, and addNUL
|
||||
buffer traits removed difference type
|
||||
improved reading, writing performance (because of isContiguous and difference_type)
|
||||
BasicBufferWriter/Reader no longer has bit-packing operations by default
|
||||
Bit-packing is enabled via template parameter in Serializer/Deserializer, additionally added new method enableBitPacking.
|
||||
Additionally Serializer/Deserializer is no longer copyable, because it stores bit-packer state.
|
||||
ExtensionTraits gain additional patameter BitPackingRequired, static_asserts if bit-packing is not enabled.
|
||||
Removed boolByte, boolBit, and added boolValue and it writes bit or byte, depeding on if bit-packing is enabled or not.
|
||||
added missing std containers support: forward_list, deque, stack, queue, priority_queue, set, multiset, unordered_set, unordered_multiset
|
||||
Renamed ContainerMap to StdMap, Optional to StdOptional
|
||||
|
||||
|
||||
todo write tests:
|
||||
bufferreader accepts const data
|
||||
|
||||
@@ -82,7 +82,7 @@ int main() {
|
||||
//2) create buffer writer that is able to write bytes or bits to buffer
|
||||
BasicBufferWriter<NonDefaultConfig> bw{buffer};
|
||||
//3) create serializer
|
||||
BasicSerializer<NonDefaultConfig> ser{bw};
|
||||
BasicSerializer<NonDefaultConfig, false> ser{bw};
|
||||
|
||||
//serialize object, can also be invoked like this: serialize(ser, data)
|
||||
ser.object(data);
|
||||
@@ -94,7 +94,7 @@ int main() {
|
||||
//1) create buffer reader
|
||||
BasicBufferReader<NonDefaultConfig> br{bw.getWrittenRange()};
|
||||
//2) create deserializer
|
||||
BasicDeserializer<NonDefaultConfig> des{br};
|
||||
BasicDeserializer<NonDefaultConfig, false> des{br};
|
||||
|
||||
//deserialize same object, can also be invoked like this: serialize(des, data)
|
||||
MyTypes::Monster res{};
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
|
||||
namespace bitsery {
|
||||
|
||||
template <typename Config>
|
||||
class BitPackingReader;
|
||||
|
||||
template<typename Config>
|
||||
struct BasicBufferReader {
|
||||
|
||||
@@ -50,12 +53,12 @@ namespace bitsery {
|
||||
static_assert(sizeof(ValueType) == 1, "currently only supported BufferValueType is 1 byte");
|
||||
}
|
||||
|
||||
BasicBufferReader(BufferRange<BufferIteratorType> range)
|
||||
explicit BasicBufferReader(BufferRange<BufferIteratorType> range)
|
||||
:BasicBufferReader(range.begin(), range.end()) {
|
||||
static_assert(std::is_same<
|
||||
typename std::iterator_traits<BufferIteratorType>::iterator_category,
|
||||
std::random_access_iterator_tag>::value,
|
||||
"BufferReader only accepts random access iterators");
|
||||
"BufferReader only accepts random access iterators");
|
||||
}
|
||||
|
||||
BasicBufferReader(const BasicBufferReader &) = delete;
|
||||
@@ -69,13 +72,112 @@ namespace bitsery {
|
||||
~BasicBufferReader() noexcept = default;
|
||||
|
||||
|
||||
template<size_t SIZE, typename T>
|
||||
void readBytes(T &v) {
|
||||
static_assert(std::is_integral<T>(), "");
|
||||
static_assert(sizeof(T) == SIZE, "");
|
||||
directRead(&v, 1);
|
||||
}
|
||||
|
||||
template<size_t SIZE, typename T>
|
||||
void readBuffer(T *buf, size_t count) {
|
||||
static_assert(std::is_integral<T>(), "");
|
||||
static_assert(sizeof(T) == SIZE, "");
|
||||
directRead(buf, count);
|
||||
}
|
||||
|
||||
void align() {
|
||||
}
|
||||
|
||||
bool isCompletedSuccessfully() const {
|
||||
return _bufferContext.isCompletedSuccessfully() && !_session.hasActiveSessions();
|
||||
}
|
||||
|
||||
BufferReaderError getError() const {
|
||||
auto err = _bufferContext.getError();
|
||||
if (_session.hasActiveSessions() && err == BufferReaderError::BUFFER_OVERFLOW)
|
||||
return BufferReaderError::NO_ERROR;
|
||||
return err;
|
||||
}
|
||||
|
||||
void setError(BufferReaderError error) {
|
||||
return _bufferContext.setError(error);
|
||||
}
|
||||
|
||||
void beginSession() {
|
||||
if (getError() != BufferReaderError::INVALID_BUFFER_DATA) {
|
||||
_session.begin();
|
||||
}
|
||||
}
|
||||
|
||||
void endSession() {
|
||||
if (getError() != BufferReaderError::INVALID_BUFFER_DATA) {
|
||||
_session.end();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
friend class BitPackingReader<Config>;
|
||||
|
||||
details::ReadBufferContext<BufferType> _bufferContext;
|
||||
typename std::conditional<Config::BufferSessionsEnabled,
|
||||
details::BufferSessionsReader<BasicBufferReader<Config>, details::ReadBufferContext<BufferType>>,
|
||||
details::DisabledBufferSessionsReader<Config>>::type
|
||||
_session;
|
||||
|
||||
template<typename T>
|
||||
void directRead(T *v, size_t count) {
|
||||
static_assert(!std::is_const<T>::value, "");
|
||||
_bufferContext.read(reinterpret_cast<ValueType *>(v), sizeof(T) * count);
|
||||
//swap each byte if nessesarry
|
||||
_swapDataBits(v, count, std::integral_constant<bool,
|
||||
Config::NetworkEndianness != details::getSystemEndianness()>{});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void _swapDataBits(T *v, size_t count, std::true_type) {
|
||||
std::for_each(v, std::next(v, count), [this](T &x) { x = details::swap(x); });
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void _swapDataBits(T *v, size_t count, std::false_type) {
|
||||
//empty function because no swap is required
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename Config>
|
||||
struct BitPackingReader {
|
||||
|
||||
using ValueType = typename details::ContainerTraits<typename Config::BufferType>::TValue;
|
||||
using ScratchType = typename details::SCRATCH_TYPE<ValueType>::type;
|
||||
|
||||
explicit BitPackingReader(BasicBufferReader<Config>& reader):_reader{reader}
|
||||
{
|
||||
static_assert(std::is_unsigned<ValueType>(), "Config::BufferValueType must be unsigned");
|
||||
static_assert(std::is_unsigned<ScratchType>(), "Config::BufferScrathType must be unsigned");
|
||||
static_assert(sizeof(ValueType) * 2 == sizeof(ScratchType),
|
||||
"ScratchType must be 2x bigger than value type");
|
||||
static_assert(sizeof(ValueType) == 1, "currently only supported BufferValueType is 1 byte");
|
||||
}
|
||||
|
||||
BitPackingReader(const BitPackingReader&) = delete;
|
||||
BitPackingReader& operator = (const BitPackingReader&) = delete;
|
||||
|
||||
BitPackingReader(BitPackingReader&& ) noexcept = default;
|
||||
BitPackingReader& operator = (BitPackingReader&& ) noexcept = default;
|
||||
|
||||
~BitPackingReader() {
|
||||
align();
|
||||
}
|
||||
|
||||
template<size_t SIZE, typename T>
|
||||
void readBytes(T &v) {
|
||||
static_assert(std::is_integral<T>(), "");
|
||||
static_assert(sizeof(T) == SIZE, "");
|
||||
using UT = typename std::make_unsigned<T>::type;
|
||||
if (!m_scratchBits)
|
||||
directRead(&v, 1);
|
||||
_reader.template readBytes<SIZE,T>(v);
|
||||
else
|
||||
readBits(reinterpret_cast<UT &>(v), details::BITS_SIZE<T>::value);
|
||||
}
|
||||
@@ -86,7 +188,7 @@ namespace bitsery {
|
||||
static_assert(sizeof(T) == SIZE, "");
|
||||
|
||||
if (!m_scratchBits) {
|
||||
directRead(buf, count);
|
||||
_reader.template readBuffer<SIZE,T>(buf, count);
|
||||
} else {
|
||||
using UT = typename std::make_unsigned<T>::type;
|
||||
//todo improve implementation
|
||||
@@ -113,61 +215,31 @@ namespace bitsery {
|
||||
}
|
||||
|
||||
bool isCompletedSuccessfully() const {
|
||||
return _bufferContext.isCompletedSuccessfully() && !_session.hasActiveSessions();
|
||||
return _reader.isCompletedSuccessfully();
|
||||
}
|
||||
|
||||
BufferReaderError getError() const {
|
||||
auto err = _bufferContext.getError();
|
||||
if (_session.hasActiveSessions() && err == BufferReaderError::BUFFER_OVERFLOW)
|
||||
return BufferReaderError::NO_ERROR;
|
||||
return err;
|
||||
return _reader.getError();
|
||||
}
|
||||
|
||||
void setError(BufferReaderError error) {
|
||||
return _bufferContext.setError(error);
|
||||
_reader.setError(error);
|
||||
}
|
||||
|
||||
void beginSession() {
|
||||
align();
|
||||
if (getError() != BufferReaderError::INVALID_BUFFER_DATA) {
|
||||
_session.begin();
|
||||
}
|
||||
_reader.beginSession();
|
||||
}
|
||||
|
||||
void endSession() {
|
||||
align();
|
||||
if (getError() != BufferReaderError::INVALID_BUFFER_DATA) {
|
||||
_session.end();
|
||||
}
|
||||
_reader.endSession();
|
||||
}
|
||||
|
||||
private:
|
||||
details::ReadBufferContext<BufferType> _bufferContext;
|
||||
BasicBufferReader<Config>& _reader;
|
||||
ScratchType m_scratch{};
|
||||
size_t m_scratchBits{};
|
||||
typename std::conditional<Config::BufferSessionsEnabled,
|
||||
details::BufferSessionsReader<BasicBufferReader<Config>, details::ReadBufferContext<BufferType>>,
|
||||
details::DisabledBufferSessionsReader<Config>>::type
|
||||
_session;
|
||||
|
||||
template<typename T>
|
||||
void directRead(T *v, size_t count) {
|
||||
static_assert(!std::is_const<T>::value, "");
|
||||
_bufferContext.read(reinterpret_cast<ValueType *>(v), sizeof(T) * count);
|
||||
//swap each byte if nessesarry
|
||||
_swapDataBits(v, count, std::integral_constant<bool,
|
||||
Config::NetworkEndianness != details::getSystemEndianness()>{});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void _swapDataBits(T *v, size_t count, std::true_type) {
|
||||
std::for_each(v, std::next(v, count), [this](T &x) { x = details::swap(x); });
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void _swapDataBits(T *v, size_t count, std::false_type) {
|
||||
//empty function because no swap is required
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void readBitsInternal(T &v, size_t size) {
|
||||
@@ -177,7 +249,7 @@ namespace bitsery {
|
||||
auto bits = std::min(bitsLeft, details::BITS_SIZE<ValueType>::value);
|
||||
if (m_scratchBits < bits) {
|
||||
ValueType tmp;
|
||||
directRead(&tmp, 1);
|
||||
_reader.template readBytes<sizeof(ValueType), ValueType>(tmp);
|
||||
m_scratch |= static_cast<ScratchType>(tmp) << m_scratchBits;
|
||||
m_scratchBits += details::BITS_SIZE<ValueType>::value;
|
||||
}
|
||||
|
||||
@@ -92,6 +92,10 @@ namespace bitsery {
|
||||
size_t _sessionsBytesCount{};
|
||||
};
|
||||
|
||||
|
||||
template <typename Config>
|
||||
class BitPackingWriter;
|
||||
|
||||
template<typename Config>
|
||||
struct BasicBufferWriter {
|
||||
using BufferType = typename Config::BufferType;
|
||||
@@ -122,46 +126,23 @@ namespace bitsery {
|
||||
void writeBytes(const T &v) {
|
||||
static_assert(std::is_integral<T>(), "");
|
||||
static_assert(sizeof(T) == SIZE, "");
|
||||
directWrite(&v, 1);
|
||||
|
||||
if (!_scratchBits) {
|
||||
directWrite(&v, 1);
|
||||
} else {
|
||||
using UT = typename std::make_unsigned<T>::type;
|
||||
writeBits(reinterpret_cast<const UT &>(v), details::BITS_SIZE<T>::value);
|
||||
}
|
||||
}
|
||||
|
||||
template<size_t SIZE, typename T>
|
||||
void writeBuffer(const T *buf, size_t count) {
|
||||
static_assert(std::is_integral<T>(), "");
|
||||
static_assert(sizeof(T) == SIZE, "");
|
||||
if (!_scratchBits) {
|
||||
directWrite(buf, count);
|
||||
} else {
|
||||
using UT = typename std::make_unsigned<T>::type;
|
||||
//todo improve implementation
|
||||
const auto end = buf + count;
|
||||
for (auto it = buf; it != end; ++it)
|
||||
writeBits(reinterpret_cast<const UT &>(*it), details::BITS_SIZE<T>::value);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void writeBits(const T &v, size_t bitsCount) {
|
||||
static_assert(std::is_integral<T>() && std::is_unsigned<T>(), "");
|
||||
assert(0 < bitsCount && bitsCount <= details::BITS_SIZE<T>::value);
|
||||
assert(v <= (bitsCount < 64
|
||||
? (1ULL << bitsCount) - 1
|
||||
: (1ULL << (bitsCount-1)) + ((1ULL << (bitsCount-1)) -1)));
|
||||
writeBitsInternal(v, bitsCount);
|
||||
directWrite(buf, count);
|
||||
}
|
||||
|
||||
//to have the same interface as bitpackingwriter
|
||||
void align() {
|
||||
writeBitsInternal(ValueType{}, (details::BITS_SIZE<ValueType>::value - _scratchBits) % 8);
|
||||
|
||||
}
|
||||
|
||||
void flush() {
|
||||
align();
|
||||
_session.flushSessions(*this);
|
||||
}
|
||||
|
||||
@@ -170,17 +151,15 @@ namespace bitsery {
|
||||
}
|
||||
|
||||
void beginSession() {
|
||||
align();
|
||||
_session.begin(*this);
|
||||
}
|
||||
|
||||
void endSession() {
|
||||
align();
|
||||
_session.end(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class BitPackingWriter<Config>;
|
||||
template<typename T>
|
||||
void directWrite(T &&v, size_t count) {
|
||||
_directWriteSwapTag(std::forward<T>(v), count, std::integral_constant<bool,
|
||||
@@ -200,6 +179,100 @@ namespace bitsery {
|
||||
_bufferContext.write(reinterpret_cast<const ValueType *>(v), count * sizeof(T));
|
||||
}
|
||||
|
||||
BufferContext _bufferContext;
|
||||
typename std::conditional<Config::BufferSessionsEnabled,
|
||||
details::BufferSessionsWriter<BasicBufferWriter<Config>>,
|
||||
details::DisabledBufferSessionsWriter<Config>>::type
|
||||
_session{};
|
||||
};
|
||||
|
||||
template<typename Config>
|
||||
struct BitPackingWriter {
|
||||
using ValueType = typename details::ContainerTraits<typename Config::BufferType>::TValue;
|
||||
using ScratchType = typename details::SCRATCH_TYPE<ValueType>::type;
|
||||
|
||||
explicit BitPackingWriter(BasicBufferWriter<Config> &writer)
|
||||
: _writer{writer}
|
||||
{
|
||||
static_assert(std::is_unsigned<ValueType>(), "Config::BufferType value type must be unsigned");
|
||||
static_assert(sizeof(ValueType) * 2 == sizeof(ScratchType),
|
||||
"ScratchType must be 2x bigger than value type");
|
||||
static_assert(sizeof(ValueType) == 1, "currently only supported BufferValueType is 1 byte");
|
||||
}
|
||||
|
||||
BitPackingWriter(const BitPackingWriter&) = delete;
|
||||
BitPackingWriter& operator = (const BitPackingWriter&) = delete;
|
||||
|
||||
BitPackingWriter(BitPackingWriter&& ) noexcept = default;
|
||||
BitPackingWriter& operator = (BitPackingWriter&& ) noexcept = default;
|
||||
|
||||
~BitPackingWriter() {
|
||||
align();
|
||||
}
|
||||
|
||||
template<size_t SIZE, typename T>
|
||||
void writeBytes(const T &v) {
|
||||
static_assert(std::is_integral<T>(), "");
|
||||
static_assert(sizeof(T) == SIZE, "");
|
||||
|
||||
if (!_scratchBits) {
|
||||
_writer.template writeBytes<SIZE,T>(v);
|
||||
} else {
|
||||
using UT = typename std::make_unsigned<T>::type;
|
||||
writeBitsInternal(reinterpret_cast<const UT &>(v), details::BITS_SIZE<T>::value);
|
||||
}
|
||||
}
|
||||
|
||||
template<size_t SIZE, typename T>
|
||||
void writeBuffer(const T *buf, size_t count) {
|
||||
static_assert(std::is_integral<T>(), "");
|
||||
static_assert(sizeof(T) == SIZE, "");
|
||||
if (!_scratchBits) {
|
||||
_writer.template writeBuffer<SIZE,T>(buf, count);
|
||||
} else {
|
||||
using UT = typename std::make_unsigned<T>::type;
|
||||
//todo improve implementation
|
||||
const auto end = buf + count;
|
||||
for (auto it = buf; it != end; ++it)
|
||||
writeBitsInternal(reinterpret_cast<const UT &>(*it), details::BITS_SIZE<T>::value);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void writeBits(const T &v, size_t bitsCount) {
|
||||
static_assert(std::is_integral<T>() && std::is_unsigned<T>(), "");
|
||||
assert(0 < bitsCount && bitsCount <= details::BITS_SIZE<T>::value);
|
||||
assert(v <= (bitsCount < 64
|
||||
? (1ULL << bitsCount) - 1
|
||||
: (1ULL << (bitsCount-1)) + ((1ULL << (bitsCount-1)) -1)));
|
||||
writeBitsInternal(v, bitsCount);
|
||||
}
|
||||
|
||||
void align() {
|
||||
writeBitsInternal(ValueType{}, (details::BITS_SIZE<ValueType>::value - _scratchBits) % 8);
|
||||
}
|
||||
|
||||
void flush() {
|
||||
align();
|
||||
_writer._session.flushSessions(_writer);
|
||||
}
|
||||
|
||||
BufferRange<typename details::BufferContainerTraits<typename Config::BufferType>::TIterator> getWrittenRange() const {
|
||||
return _writer.getWrittenRange();
|
||||
}
|
||||
|
||||
void beginSession() {
|
||||
align();
|
||||
_writer._session.begin(_writer);
|
||||
}
|
||||
|
||||
void endSession() {
|
||||
align();
|
||||
_writer._session.end(_writer);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<typename T>
|
||||
void writeBitsInternal(const T &v, size_t size) {
|
||||
constexpr size_t valueSize = details::BITS_SIZE<ValueType>::value;
|
||||
@@ -211,7 +284,7 @@ namespace bitsery {
|
||||
_scratchBits += bits;
|
||||
if (_scratchBits >= valueSize) {
|
||||
auto tmp = static_cast<ValueType>(_scratch & _MASK);
|
||||
directWrite(&tmp, 1);
|
||||
_writer.template writeBytes<sizeof(ValueType), ValueType >(tmp);
|
||||
_scratch >>= valueSize;
|
||||
_scratchBits -= valueSize;
|
||||
|
||||
@@ -228,22 +301,18 @@ namespace bitsery {
|
||||
_scratchBits += size;
|
||||
if (_scratchBits >= details::BITS_SIZE<ValueType>::value) {
|
||||
auto tmp = static_cast<ValueType>(_scratch & _MASK);
|
||||
directWrite(&tmp, 1);
|
||||
_writer.template writeBytes<sizeof(ValueType), ValueType>(tmp);
|
||||
_scratch >>= details::BITS_SIZE<ValueType>::value;
|
||||
_scratchBits -= details::BITS_SIZE<ValueType>::value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const ValueType _MASK = std::numeric_limits<ValueType>::max();
|
||||
BufferContext _bufferContext;
|
||||
ScratchType _scratch{};
|
||||
size_t _scratchBits{};
|
||||
typename std::conditional<Config::BufferSessionsEnabled,
|
||||
details::BufferSessionsWriter<BasicBufferWriter<Config>>,
|
||||
details::DisabledBufferSessionsWriter<Config>>::type
|
||||
_session{};
|
||||
BasicBufferWriter<Config>& _writer;
|
||||
|
||||
};
|
||||
|
||||
//helper type
|
||||
|
||||
@@ -31,10 +31,23 @@
|
||||
namespace bitsery {
|
||||
|
||||
|
||||
template<typename Config>
|
||||
template<typename Config, bool BitPackingEnabled>
|
||||
class BasicDeserializer {
|
||||
public:
|
||||
explicit BasicDeserializer(BasicBufferReader<Config> &r, void* context = nullptr) : _reader{r}, _context{context} {};
|
||||
using BPEnabledType = BasicDeserializer<Config, true>;
|
||||
|
||||
explicit BasicDeserializer(BasicBufferReader<Config> &r, void* context = nullptr)
|
||||
: _reader{r},
|
||||
_context{context}
|
||||
{};
|
||||
|
||||
//copying disabled
|
||||
BasicDeserializer(const BasicDeserializer&) = delete;
|
||||
BasicDeserializer& operator = (const BasicDeserializer&) = delete;
|
||||
|
||||
//move enabled
|
||||
BasicDeserializer(BasicDeserializer&& ) noexcept = default;
|
||||
BasicDeserializer& operator = (BasicDeserializer&& ) noexcept = default;
|
||||
|
||||
/*
|
||||
* get serialization context.
|
||||
@@ -50,8 +63,7 @@ namespace bitsery {
|
||||
|
||||
template<typename T>
|
||||
void object(T &&obj) {
|
||||
using TValue = typename std::decay<T>::type;
|
||||
details::SerializeFunction<BasicDeserializer, TValue>::invoke(*this, std::forward<T>(obj));
|
||||
details::SerializeFunction<BasicDeserializer, T>::invoke(*this, std::forward<T>(obj));
|
||||
}
|
||||
|
||||
template<typename T, typename Fnc>
|
||||
@@ -71,7 +83,7 @@ namespace bitsery {
|
||||
}
|
||||
|
||||
/*
|
||||
* value overloads
|
||||
* value
|
||||
*/
|
||||
|
||||
template<size_t VSIZE, typename T, typename std::enable_if<details::IsFundamentalType<T>::value>::type * = nullptr>
|
||||
@@ -80,6 +92,14 @@ namespace bitsery {
|
||||
_reader.template readBytes<VSIZE>(reinterpret_cast<TValue &>(v));
|
||||
}
|
||||
|
||||
/*
|
||||
* enable bit-packing
|
||||
*/
|
||||
template <typename Fnc>
|
||||
void enableBitPacking(Fnc&& fnc) {
|
||||
procEnableBitPacking(std::forward<Fnc>(fnc), std::integral_constant<bool, !BitPackingEnabled>{});
|
||||
}
|
||||
|
||||
/*
|
||||
* extension functions
|
||||
*/
|
||||
@@ -88,6 +108,8 @@ namespace bitsery {
|
||||
void ext(T &obj, const Ext &extension, Fnc &&fnc) {
|
||||
static_assert(details::ExtensionTraits<Ext,T>::SupportLambdaOverload,
|
||||
"extension doesn't support overload with lambda");
|
||||
static_assert(BitPackingEnabled || !details::ExtensionTraits<Ext,T>::BitPackingRequired,
|
||||
"Extension requires bit-packing to be enabled, (call `enableBitPacking`)");
|
||||
extension.deserialize(*this, _reader, obj, std::forward<Fnc>(fnc));
|
||||
};
|
||||
|
||||
@@ -97,7 +119,9 @@ namespace bitsery {
|
||||
"extension doesn't support overload with `value<N>`");
|
||||
using ExtVType = typename details::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); });
|
||||
static_assert(BitPackingEnabled || !details::ExtensionTraits<Ext,T>::BitPackingRequired,
|
||||
"Extension requires bit-packing to be enabled, (call `enableBitPacking`)");
|
||||
extension.deserialize(*this, _reader, obj, [this](VType &v) { value<VSIZE>(v);});
|
||||
};
|
||||
|
||||
template<typename T, typename Ext>
|
||||
@@ -106,25 +130,16 @@ namespace bitsery {
|
||||
"extension doesn't support overload with `object`");
|
||||
using ExtVType = typename details::ExtensionTraits<Ext, T>::TValue;
|
||||
using VType = typename std::conditional<std::is_void<ExtVType>::value, details::DummyType, ExtVType>::type;
|
||||
static_assert(BitPackingEnabled || !details::ExtensionTraits<Ext,T>::BitPackingRequired,
|
||||
"Extension requires bit-packing to be enabled, (call `enableBitPacking`)");
|
||||
extension.deserialize(*this, _reader, obj, [this](VType &v) { object(v); });
|
||||
};
|
||||
|
||||
/*
|
||||
* bool
|
||||
* boolValue
|
||||
*/
|
||||
|
||||
void boolBit(bool &v) {
|
||||
uint8_t tmp{};
|
||||
_reader.readBits(tmp, 1);
|
||||
v = tmp == 1;
|
||||
}
|
||||
|
||||
void boolByte(bool &v) {
|
||||
unsigned char tmp;
|
||||
_reader.template readBytes<1>(tmp);
|
||||
if (tmp > 1)
|
||||
_reader.setError(BufferReaderError::INVALID_BUFFER_DATA);
|
||||
v = tmp == 1;
|
||||
void boolValue(bool &v) {
|
||||
procBoolValue(v, std::integral_constant<bool, BitPackingEnabled>{});
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -283,7 +298,11 @@ namespace bitsery {
|
||||
void container8b(T &&obj) { container<8>(std::forward<T>(obj)); }
|
||||
|
||||
private:
|
||||
BasicBufferReader<Config> &_reader;
|
||||
|
||||
typename std::conditional<BitPackingEnabled,
|
||||
BitPackingReader<Config>,//by value
|
||||
BasicBufferReader<Config>&//by reference
|
||||
>::type _reader;
|
||||
void* _context;
|
||||
|
||||
//process value types
|
||||
@@ -329,6 +348,34 @@ namespace bitsery {
|
||||
*end = {};
|
||||
}
|
||||
|
||||
//proc bool writing bit or byte, depending on if BitPackingEnabled or not
|
||||
void procBoolValue(bool &v, std::true_type) {
|
||||
uint8_t tmp{};
|
||||
_reader.readBits(tmp, 1);
|
||||
v = tmp == 1;
|
||||
}
|
||||
|
||||
void procBoolValue(bool &v, std::false_type) {
|
||||
unsigned char tmp;
|
||||
_reader.template readBytes<1>(tmp);
|
||||
if (tmp > 1)
|
||||
_reader.setError(BufferReaderError::INVALID_BUFFER_DATA);
|
||||
v = tmp == 1;
|
||||
}
|
||||
|
||||
|
||||
//enable bit-packing or do nothing if it is already enabled
|
||||
template <typename Fnc>
|
||||
void procEnableBitPacking(const Fnc& fnc, std::true_type) {
|
||||
BPEnabledType tmp{_reader, _context};
|
||||
fnc(tmp);
|
||||
}
|
||||
|
||||
template <typename Fnc>
|
||||
void procEnableBitPacking(const Fnc& fnc, std::false_type) {
|
||||
fnc(*this);
|
||||
}
|
||||
|
||||
//these are dummy functions for extensions that have TValue = void
|
||||
void object(details::DummyType&) {
|
||||
|
||||
@@ -346,7 +393,7 @@ namespace bitsery {
|
||||
};
|
||||
|
||||
//helper type
|
||||
using Deserializer = BasicDeserializer<DefaultConfig>;
|
||||
using Deserializer = BasicDeserializer<DefaultConfig, false>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define BITSERY_DETAILS_FLEXIBLE_COMMON_H
|
||||
|
||||
#include "traits.h"
|
||||
#include <limits>
|
||||
|
||||
namespace bitsery {
|
||||
namespace flexible {
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace bitsery {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace details {
|
||||
|
||||
//used for extensions, when extension TValue = void
|
||||
|
||||
@@ -41,6 +41,12 @@ namespace bitsery {
|
||||
//when this is void, it will compile, but value and object overloads will do nothing.
|
||||
using TValue = void;
|
||||
|
||||
|
||||
//specify if extension required bitpacking operations
|
||||
//if current serialization instance is not bit-packing enabled,
|
||||
//then new instance will be created with bit-packing enabled,
|
||||
//and bits will be flushed automaticaly after extension finish executing.
|
||||
static constexpr bool BitPackingRequired = false;
|
||||
//does extension support ext<N>(...) syntax, by calling value<N> with TValue
|
||||
static constexpr bool SupportValueOverload = true;
|
||||
//does extension support ext(...) syntax, by calling object with TValue
|
||||
|
||||
@@ -46,8 +46,14 @@ namespace bitsery {
|
||||
class Entropy {
|
||||
public:
|
||||
|
||||
constexpr explicit Entropy(TContainer& values) : _values{values} {
|
||||
|
||||
/**
|
||||
* Allows entropy-encoding technique, by writing few bits for most common values
|
||||
* @param values list of most common values
|
||||
* @param alignBeforeData only makes sense when bit-packing enabled, by default aligns after writing bits for index
|
||||
*/
|
||||
constexpr Entropy(TContainer& values, bool alignBeforeData=true)
|
||||
: _values{values},
|
||||
_alignBeforeData{alignBeforeData} {
|
||||
};
|
||||
|
||||
template<typename Ser, typename Writer, typename T, typename Fnc>
|
||||
@@ -55,6 +61,8 @@ namespace bitsery {
|
||||
assert(details::ContainerTraits<TContainer>::size(_values) > 0);
|
||||
auto index = details::findEntropyIndex(obj, _values);
|
||||
s.ext(index, ext::ValueRange<size_t>{0u, details::ContainerTraits<TContainer>::size(_values)});
|
||||
if (_alignBeforeData)
|
||||
s.align();
|
||||
if (!index)
|
||||
fnc(const_cast<T &>(obj));
|
||||
}
|
||||
@@ -64,6 +72,8 @@ namespace bitsery {
|
||||
assert(details::ContainerTraits<TContainer>::size(_values) > 0);
|
||||
size_t index{};
|
||||
d.ext(index, ext::ValueRange<size_t>{0u, details::ContainerTraits<TContainer>::size(_values)});
|
||||
if (_alignBeforeData)
|
||||
d.align();
|
||||
if (index)
|
||||
obj = *std::next(std::begin(_values), index-1);
|
||||
else
|
||||
@@ -72,6 +82,7 @@ namespace bitsery {
|
||||
|
||||
private:
|
||||
TContainer& _values;
|
||||
bool _alignBeforeData;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -79,6 +90,7 @@ namespace bitsery {
|
||||
template<typename TContainer, typename T>
|
||||
struct ExtensionTraits<ext::Entropy<TContainer>, T> {
|
||||
using TValue = T;
|
||||
static constexpr bool BitPackingRequired = true;
|
||||
static constexpr bool SupportValueOverload = true;
|
||||
static constexpr bool SupportObjectOverload = true;
|
||||
static constexpr bool SupportLambdaOverload = true;
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace bitsery {
|
||||
template<typename T>
|
||||
struct ExtensionTraits<ext::Growable, T> {
|
||||
using TValue = T;
|
||||
static constexpr bool BitPackingRequired = false;
|
||||
static constexpr bool SupportValueOverload = false;
|
||||
static constexpr bool SupportObjectOverload = true;
|
||||
static constexpr bool SupportLambdaOverload = true;
|
||||
|
||||
@@ -20,16 +20,18 @@
|
||||
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
//SOFTWARE.
|
||||
|
||||
#ifndef BITSERY_EXT_CONTAINER_MAP_H
|
||||
#define BITSERY_EXT_CONTAINER_MAP_H
|
||||
#ifndef BITSERY_EXT_STD_MAP_H
|
||||
#define BITSERY_EXT_STD_MAP_H
|
||||
|
||||
#include "../details/both_common.h"
|
||||
|
||||
namespace bitsery {
|
||||
namespace ext {
|
||||
|
||||
class ContainerMap {
|
||||
class StdMap {
|
||||
public:
|
||||
|
||||
constexpr explicit ContainerMap(size_t maxSize):_maxSize{maxSize} {}
|
||||
constexpr explicit StdMap(size_t maxSize):_maxSize{maxSize} {}
|
||||
|
||||
template<typename Ser, typename Writer, typename T, typename Fnc>
|
||||
void serialize(Ser &, Writer &writer, const T &obj, Fnc &&fnc) const {
|
||||
@@ -67,8 +69,9 @@ namespace bitsery {
|
||||
|
||||
namespace details {
|
||||
template<typename T>
|
||||
struct ExtensionTraits<ext::ContainerMap, T> {
|
||||
struct ExtensionTraits<ext::StdMap, T> {
|
||||
using TValue = void;
|
||||
static constexpr bool BitPackingRequired = false;
|
||||
static constexpr bool SupportValueOverload = false;
|
||||
static constexpr bool SupportObjectOverload = false;
|
||||
static constexpr bool SupportLambdaOverload = true;
|
||||
@@ -78,4 +81,4 @@ namespace bitsery {
|
||||
}
|
||||
|
||||
|
||||
#endif //BITSERY_EXT_CONTAINER_MAP_H
|
||||
#endif //BITSERY_EXT_STD_MAP_H
|
||||
@@ -21,8 +21,8 @@
|
||||
//SOFTWARE.
|
||||
|
||||
|
||||
#ifndef BITSERY_EXT_OPTIONAL_H
|
||||
#define BITSERY_EXT_OPTIONAL_H
|
||||
#ifndef BITSERY_EXT_STD_OPTIONAL_H
|
||||
#define BITSERY_EXT_STD_OPTIONAL_H
|
||||
|
||||
|
||||
//this module do not include optional, but expects it to be declared in std::optional
|
||||
@@ -40,9 +40,14 @@ namespace bitsery {
|
||||
template<typename T>
|
||||
using std_optional = ::std::optional<T>;
|
||||
|
||||
class Optional {
|
||||
class StdOptional {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Works with std::optional types
|
||||
* @param alignBeforeData only makes sense when bit-packing enabled, by default aligns after writing/reading bool state of optional
|
||||
*/
|
||||
explicit StdOptional(bool alignBeforeData=true):_alignBeforeData{alignBeforeData} {}
|
||||
template<typename T>
|
||||
constexpr void assertType() const {
|
||||
using TOpt = typename std::remove_cv<T>::type;
|
||||
@@ -54,7 +59,9 @@ namespace bitsery {
|
||||
template<typename Ser, typename Writer, typename T, typename Fnc>
|
||||
void serialize(Ser &ser, Writer &, const T &obj, Fnc &&fnc) const {
|
||||
assertType<T>();
|
||||
ser.boolByte(static_cast<bool>(obj));
|
||||
ser.boolValue(static_cast<bool>(obj));
|
||||
if (_alignBeforeData)
|
||||
ser.align();
|
||||
if (obj)
|
||||
fnc(const_cast<typename T::value_type & >(*obj));
|
||||
}
|
||||
@@ -63,7 +70,9 @@ namespace bitsery {
|
||||
void deserialize(Des &des, Reader &, T &obj, Fnc &&fnc) const {
|
||||
assertType<T>();
|
||||
bool exists{};
|
||||
des.boolByte(exists);
|
||||
des.boolValue(exists);
|
||||
if (_alignBeforeData)
|
||||
des.align();
|
||||
if (exists) {
|
||||
typename T::value_type tmp{};
|
||||
fnc(tmp);
|
||||
@@ -73,13 +82,16 @@ namespace bitsery {
|
||||
obj = T{};
|
||||
}
|
||||
}
|
||||
private:
|
||||
bool _alignBeforeData;
|
||||
};
|
||||
}
|
||||
|
||||
namespace details {
|
||||
template<typename T>
|
||||
struct ExtensionTraits<ext::Optional, T> {
|
||||
struct ExtensionTraits<ext::StdOptional, T> {
|
||||
using TValue = typename T::value_type;
|
||||
static constexpr bool BitPackingRequired = false;
|
||||
static constexpr bool SupportValueOverload = true;
|
||||
static constexpr bool SupportObjectOverload = true;
|
||||
static constexpr bool SupportLambdaOverload = true;
|
||||
@@ -89,4 +101,4 @@ namespace bitsery {
|
||||
}
|
||||
|
||||
|
||||
#endif //BITSERY_EXT_OPTIONAL_H
|
||||
#endif //BITSERY_EXT_STD_OPTIONAL_H
|
||||
112
include/bitsery/ext/std_queue.h
Normal file
112
include/bitsery/ext/std_queue.h
Normal file
@@ -0,0 +1,112 @@
|
||||
//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.
|
||||
|
||||
|
||||
#ifndef BITSERY_EXT_STD_QUEUE_H
|
||||
#define BITSERY_EXT_STD_QUEUE_H
|
||||
|
||||
#include <type_traits>
|
||||
#include <queue>
|
||||
//include type traits for deque and vector, because they are defaults for queue and priority_queue
|
||||
#include "../traits/deque.h"
|
||||
#include "../traits/vector.h"
|
||||
|
||||
namespace bitsery {
|
||||
namespace ext {
|
||||
|
||||
class StdQueue {
|
||||
private:
|
||||
//inherit from queue so we could take underlying container
|
||||
template <typename T, typename C>
|
||||
struct QueueCnt : public std::queue<T, C>
|
||||
{
|
||||
static const C& getContainer(const std::queue<T, C>& s )
|
||||
{
|
||||
//get address of underlying container
|
||||
return s.*(&QueueCnt::c);
|
||||
}
|
||||
static C& getContainer(std::queue<T, C>& s )
|
||||
{
|
||||
//get address of underlying container
|
||||
return s.*(&QueueCnt::c);
|
||||
}
|
||||
};
|
||||
//inherit from queue so we could take underlying container
|
||||
template <typename T, typename C>
|
||||
struct PriorityQueueCnt : public std::priority_queue<T, C>
|
||||
{
|
||||
static const C& getContainer(const std::priority_queue<T, C>& s )
|
||||
{
|
||||
//get address of underlying container
|
||||
return s.*(&PriorityQueueCnt::c);
|
||||
}
|
||||
static C& getContainer(std::priority_queue<T, C>& s )
|
||||
{
|
||||
//get address of underlying container
|
||||
return s.*(&PriorityQueueCnt::c);
|
||||
}
|
||||
};
|
||||
|
||||
size_t _maxSize;
|
||||
public:
|
||||
explicit StdQueue(size_t maxSize):_maxSize{maxSize} {};
|
||||
|
||||
//for queue
|
||||
template<typename Ser, typename Writer, typename T, typename C, typename Fnc>
|
||||
void serialize(Ser &ser, Writer &, const std::queue<T,C> &obj, Fnc &&fnc) const {
|
||||
ser.container(QueueCnt<T,C>::getContainer(obj), _maxSize, std::forward<Fnc>(fnc));
|
||||
}
|
||||
|
||||
template<typename Des, typename Reader, typename T, typename C, typename Fnc>
|
||||
void deserialize(Des &des, Reader &, std::queue<T,C> &obj, Fnc &&fnc) const {
|
||||
des.container(QueueCnt<T,C>::getContainer(obj), _maxSize, std::forward<Fnc>(fnc));
|
||||
}
|
||||
|
||||
//for priority_queue
|
||||
template<typename Ser, typename Writer, typename T, typename C, typename Fnc>
|
||||
void serialize(Ser &ser, Writer &, const std::priority_queue<T,C> &obj, Fnc &&fnc) const {
|
||||
ser.container(PriorityQueueCnt<T,C>::getContainer(obj), _maxSize, std::forward<Fnc>(fnc));
|
||||
}
|
||||
|
||||
template<typename Des, typename Reader, typename T, typename C, typename Fnc>
|
||||
void deserialize(Des &des, Reader &, std::priority_queue<T,C> &obj, Fnc &&fnc) const {
|
||||
des.container(PriorityQueueCnt<T,C>::getContainer(obj), _maxSize, std::forward<Fnc>(fnc));
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
namespace details {
|
||||
template<typename T>
|
||||
struct ExtensionTraits<ext::StdQueue, T> {
|
||||
using TValue = typename T::value_type;
|
||||
static constexpr bool BitPackingRequired = false;
|
||||
static constexpr bool SupportValueOverload = true;
|
||||
static constexpr bool SupportObjectOverload = true;
|
||||
static constexpr bool SupportLambdaOverload = true;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //BITSERY_EXT_STD_QUEUE_H
|
||||
98
include/bitsery/ext/std_set.h
Normal file
98
include/bitsery/ext/std_set.h
Normal file
@@ -0,0 +1,98 @@
|
||||
//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.
|
||||
|
||||
#ifndef BITSERY_EXT_STD_SET_H
|
||||
#define BITSERY_EXT_STD_SET_H
|
||||
|
||||
#include <cassert>
|
||||
#include "../details/both_common.h"
|
||||
//we need this, so we could
|
||||
#include <unordered_set>
|
||||
|
||||
namespace bitsery {
|
||||
namespace ext {
|
||||
|
||||
class StdSet {
|
||||
public:
|
||||
|
||||
constexpr explicit StdSet(size_t maxSize):_maxSize{maxSize} {}
|
||||
|
||||
template<typename Ser, typename Writer, typename T, typename Fnc>
|
||||
void serialize(Ser &, Writer &writer, const T &obj, Fnc &&fnc) const {
|
||||
using TKey = typename T::key_type;
|
||||
auto size = obj.size();
|
||||
assert(size <= _maxSize);
|
||||
details::writeSize(writer, size);
|
||||
|
||||
for (auto &v:obj)
|
||||
fnc(const_cast<TKey &>(v));
|
||||
}
|
||||
|
||||
template<typename Des, typename Reader, typename T, typename Fnc>
|
||||
void deserialize(Des &, Reader &reader, T &obj, Fnc &&fnc) const {
|
||||
using TKey = typename T::key_type;
|
||||
|
||||
size_t size{};
|
||||
details::readSize(reader, size, _maxSize);
|
||||
auto hint = obj.begin();
|
||||
obj.clear();
|
||||
reserve(obj, size);
|
||||
|
||||
for (auto i = 0u; i < size; ++i) {
|
||||
TKey key;
|
||||
fnc(key);
|
||||
hint = obj.emplace_hint(hint, std::move(key));
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
||||
template <typename T>
|
||||
void reserve(std::unordered_set<T>& obj, size_t size) const {
|
||||
obj.reserve(size);
|
||||
}
|
||||
template <typename T>
|
||||
void reserve(std::unordered_multiset<T>& obj, size_t size) const {
|
||||
obj.reserve(size);
|
||||
}
|
||||
template <typename T>
|
||||
void reserve(T obj, size_t size) const {
|
||||
//for ordered container do nothing
|
||||
}
|
||||
size_t _maxSize;
|
||||
};
|
||||
}
|
||||
|
||||
namespace details {
|
||||
template<typename T>
|
||||
struct ExtensionTraits<ext::StdSet, T> {
|
||||
using TValue = typename T::key_type;
|
||||
static constexpr bool BitPackingRequired = false;
|
||||
static constexpr bool SupportValueOverload = true;
|
||||
static constexpr bool SupportObjectOverload = true;
|
||||
static constexpr bool SupportLambdaOverload = true;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //BITSERY_EXT_STD_SET_H
|
||||
83
include/bitsery/ext/std_stack.h
Normal file
83
include/bitsery/ext/std_stack.h
Normal file
@@ -0,0 +1,83 @@
|
||||
//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.
|
||||
|
||||
|
||||
#ifndef BITSERY_EXT_STD_STACK_H
|
||||
#define BITSERY_EXT_STD_STACK_H
|
||||
|
||||
#include <type_traits>
|
||||
#include <stack>
|
||||
//include type traits for deque, because stack default underlying container is deque
|
||||
#include "../traits/deque.h"
|
||||
|
||||
namespace bitsery {
|
||||
namespace ext {
|
||||
|
||||
class StdStack {
|
||||
private:
|
||||
//inherit from stack so we could take underlying container
|
||||
template <typename T, typename C>
|
||||
struct StackCnt : public std::stack<T, C>
|
||||
{
|
||||
static const C& getContainer(const std::stack<T, C>& s )
|
||||
{
|
||||
//get address of underlying container
|
||||
return s.*(&StackCnt::c);
|
||||
}
|
||||
static C& getContainer(std::stack<T, C>& s )
|
||||
{
|
||||
//get address of underlying container
|
||||
return s.*(&StackCnt::c);
|
||||
}
|
||||
};
|
||||
size_t _maxSize;
|
||||
public:
|
||||
explicit StdStack(size_t maxSize):_maxSize{maxSize} {};
|
||||
|
||||
template<typename Ser, typename Writer, typename T, typename C, typename Fnc>
|
||||
void serialize(Ser &ser, Writer &, const std::stack<T,C> &obj, Fnc &&fnc) const {
|
||||
ser.container(StackCnt<T,C>::getContainer(obj), _maxSize, std::forward<Fnc>(fnc));
|
||||
}
|
||||
|
||||
template<typename Des, typename Reader, typename T, typename C, typename Fnc>
|
||||
void deserialize(Des &des, Reader &, std::stack<T,C> &obj, Fnc &&fnc) const {
|
||||
des.container(StackCnt<T,C>::getContainer(obj), _maxSize, std::forward<Fnc>(fnc));
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
namespace details {
|
||||
template<typename T>
|
||||
struct ExtensionTraits<ext::StdStack, T> {
|
||||
using TValue = typename T::value_type;
|
||||
static constexpr bool BitPackingRequired = false;
|
||||
static constexpr bool SupportValueOverload = true;
|
||||
static constexpr bool SupportObjectOverload = true;
|
||||
static constexpr bool SupportLambdaOverload = true;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //BITSERY_EXT_STD_STACK_H
|
||||
@@ -194,6 +194,7 @@ namespace bitsery {
|
||||
template<typename T>
|
||||
struct ExtensionTraits<ext::ValueRange<T>, T> {
|
||||
using TValue = void;
|
||||
static constexpr bool BitPackingRequired = true;
|
||||
static constexpr bool SupportValueOverload = false;
|
||||
static constexpr bool SupportObjectOverload = true;
|
||||
static constexpr bool SupportLambdaOverload = false;
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace bitsery {
|
||||
//define serialize function for fundamental types
|
||||
template<typename S>
|
||||
void serialize(S &s, bool &v) {
|
||||
s.boolByte(v);
|
||||
s.boolValue(v);
|
||||
}
|
||||
|
||||
template<typename S, typename T, typename std::enable_if<details::IsFundamentalType<T>::value>::type * = nullptr>
|
||||
@@ -85,14 +85,14 @@ namespace bitsery {
|
||||
|
||||
//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 (&v)[N]) {
|
||||
void serialize(S &s, T (&obj)[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]) {
|
||||
s.container(obj);
|
||||
flexible::processContainer(s, obj);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
//SOFTWARE.
|
||||
|
||||
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_ARRAY_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_ARRAY_H
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_STD_ARRAY_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_STD_ARRAY_H
|
||||
|
||||
#include "../traits/array.h"
|
||||
#include "../details/flexible_common.h"
|
||||
@@ -34,4 +34,4 @@ namespace bitsery {
|
||||
}
|
||||
}
|
||||
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_ARRAY_H
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_STD_ARRAY_H
|
||||
|
||||
37
include/bitsery/flexible/deque.h
Normal file
37
include/bitsery/flexible/deque.h
Normal file
@@ -0,0 +1,37 @@
|
||||
//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.
|
||||
|
||||
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_STD_DEQUE_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_STD_DEQUE_H
|
||||
|
||||
#include "../traits/deque.h"
|
||||
#include "../details/flexible_common.h"
|
||||
|
||||
namespace bitsery {
|
||||
template<typename S, typename ... TArgs>
|
||||
void serialize(S &s, std::deque<TArgs... > &obj) {
|
||||
flexible::processContainer(s, obj);
|
||||
}
|
||||
}
|
||||
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_STD_DEQUE_H
|
||||
37
include/bitsery/flexible/forward_list.h
Normal file
37
include/bitsery/flexible/forward_list.h
Normal file
@@ -0,0 +1,37 @@
|
||||
//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.
|
||||
|
||||
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_STD_FORWARD_LIST_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_STD_FORWARD_LIST_H
|
||||
|
||||
#include "../traits/forward_list.h"
|
||||
#include "../details/flexible_common.h"
|
||||
|
||||
namespace bitsery {
|
||||
template<typename S, typename ... TArgs>
|
||||
void serialize(S &s, std::forward_list<TArgs... > &obj) {
|
||||
flexible::processContainer(s, obj);
|
||||
}
|
||||
}
|
||||
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_STD_FORWARD_LIST_H
|
||||
@@ -21,8 +21,8 @@
|
||||
//SOFTWARE.
|
||||
|
||||
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_LIST_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_LIST_H
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_STD_LIST_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_STD_LIST_H
|
||||
|
||||
#include "../traits/list.h"
|
||||
#include "../details/flexible_common.h"
|
||||
@@ -34,4 +34,4 @@ namespace bitsery {
|
||||
}
|
||||
}
|
||||
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_LIST_H
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_STD_LIST_H
|
||||
|
||||
@@ -21,18 +21,29 @@
|
||||
//SOFTWARE.
|
||||
|
||||
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_MAP_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_MAP_H
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_STD_MAP_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_STD_MAP_H
|
||||
|
||||
#include <map>
|
||||
#include "../ext/container_map.h"
|
||||
#include "bitsery/ext/std_map.h"
|
||||
|
||||
namespace bitsery {
|
||||
template<typename S, typename ... TArgs>
|
||||
void serialize(S &s, std::map<TArgs ... > &obj) {
|
||||
using TKey = typename std::map<TArgs...>::key_type;
|
||||
using TValue = typename std::map<TArgs...>::mapped_type;
|
||||
s.ext(obj, ext::ContainerMap{std::numeric_limits<size_t>::max()},
|
||||
s.ext(obj, ext::StdMap{std::numeric_limits<size_t>::max()},
|
||||
[&s](TKey& key, TValue& value) {
|
||||
s.object(key);
|
||||
s.object(value);
|
||||
});
|
||||
}
|
||||
|
||||
template<typename S, typename ... TArgs>
|
||||
void serialize(S &s, std::multimap<TArgs ... > &obj) {
|
||||
using TKey = typename std::multimap<TArgs...>::key_type;
|
||||
using TValue = typename std::multimap<TArgs...>::mapped_type;
|
||||
s.ext(obj, ext::StdMap{std::numeric_limits<size_t>::max()},
|
||||
[&s](TKey& key, TValue& value) {
|
||||
s.object(key);
|
||||
s.object(value);
|
||||
@@ -40,4 +51,4 @@ namespace bitsery {
|
||||
}
|
||||
}
|
||||
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_MAP_H
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_STD_MAP_H
|
||||
|
||||
42
include/bitsery/flexible/queue.h
Normal file
42
include/bitsery/flexible/queue.h
Normal file
@@ -0,0 +1,42 @@
|
||||
//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.
|
||||
|
||||
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_STD_QUEUE_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_STD_QUEUE_H
|
||||
|
||||
#include "../ext/std_queue.h"
|
||||
|
||||
namespace bitsery {
|
||||
template<typename S, typename T, typename C>
|
||||
void serialize(S &s, std::queue<T, C> &obj) {
|
||||
s.ext(obj, ext::StdQueue{std::numeric_limits<size_t>::max()});
|
||||
}
|
||||
|
||||
template<typename S, typename T, typename C, typename Comp>
|
||||
void serialize(S &s, std::priority_queue<T, C, Comp> &obj) {
|
||||
s.ext(obj, ext::StdQueue{std::numeric_limits<size_t>::max()});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_STD_QUEUE_H
|
||||
43
include/bitsery/flexible/set.h
Normal file
43
include/bitsery/flexible/set.h
Normal file
@@ -0,0 +1,43 @@
|
||||
//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.
|
||||
|
||||
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_STD_SET_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_STD_SET_H
|
||||
|
||||
#include <set>
|
||||
#include "../ext/std_set.h"
|
||||
|
||||
namespace bitsery {
|
||||
template<typename S, typename ... TArgs>
|
||||
void serialize(S &s, std::set<TArgs...> &obj) {
|
||||
s.ext(obj, ext::StdSet{std::numeric_limits<size_t>::max()});
|
||||
}
|
||||
|
||||
template<typename S, typename ... TArgs>
|
||||
void serialize(S &s, std::multiset<TArgs...> &obj) {
|
||||
s.ext(obj, ext::StdSet{std::numeric_limits<size_t>::max()});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_STD_SET_H
|
||||
36
include/bitsery/flexible/stack.h
Normal file
36
include/bitsery/flexible/stack.h
Normal file
@@ -0,0 +1,36 @@
|
||||
//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.
|
||||
|
||||
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_STD_STACK_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_STD_STACK_H
|
||||
|
||||
#include "../ext/std_stack.h"
|
||||
|
||||
namespace bitsery {
|
||||
template<typename S, typename T, typename C>
|
||||
void serialize(S &s, std::stack<T, C> &obj) {
|
||||
s.ext(obj, ext::StdStack{std::numeric_limits<size_t>::max()});
|
||||
}
|
||||
}
|
||||
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_STD_STACK_H
|
||||
@@ -21,8 +21,8 @@
|
||||
//SOFTWARE.
|
||||
|
||||
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_STRING_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_STRING_H
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_STD_STRING_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_STD_STRING_H
|
||||
|
||||
#include "../traits/string.h"
|
||||
#include "../details/flexible_common.h"
|
||||
@@ -34,4 +34,4 @@ namespace bitsery {
|
||||
}
|
||||
}
|
||||
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_STRING_H
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_STD_STRING_H
|
||||
|
||||
@@ -21,23 +21,35 @@
|
||||
//SOFTWARE.
|
||||
|
||||
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_UNORDERED_MAP_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_UNORDERED_MAP_H
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_STD_UNORDERED_MAP_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_STD_UNORDERED_MAP_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include "../ext/container_map.h"
|
||||
#include "bitsery/ext/std_map.h"
|
||||
|
||||
namespace bitsery {
|
||||
template<typename S, typename ... TArgs>
|
||||
void serialize(S &s, std::unordered_map<TArgs ... > &obj) {
|
||||
using TKey = typename std::unordered_map<TArgs...>::key_type;
|
||||
using TValue = typename std::unordered_map<TArgs...>::mapped_type;
|
||||
s.ext(obj, ext::ContainerMap{std::numeric_limits<size_t>::max()},
|
||||
s.ext(obj, ext::StdMap{std::numeric_limits<size_t>::max()},
|
||||
[&s](TKey& key, TValue& value) {
|
||||
s.object(key);
|
||||
s.object(value);
|
||||
});
|
||||
}
|
||||
|
||||
template<typename S, typename ... TArgs>
|
||||
void serialize(S &s, std::unordered_multimap<TArgs ... > &obj) {
|
||||
using TKey = typename std::unordered_multimap<TArgs...>::key_type;
|
||||
using TValue = typename std::unordered_multimap<TArgs...>::mapped_type;
|
||||
s.ext(obj, ext::StdMap{std::numeric_limits<size_t>::max()},
|
||||
[&s](TKey& key, TValue& value) {
|
||||
s.object(key);
|
||||
s.object(value);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_UNORDERED_MAP_H
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_STD_UNORDERED_MAP_H
|
||||
|
||||
43
include/bitsery/flexible/unordered_set.h
Normal file
43
include/bitsery/flexible/unordered_set.h
Normal file
@@ -0,0 +1,43 @@
|
||||
//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.
|
||||
|
||||
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_STD_UNORDERED_SET_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_STD_UNORDERED_SET_H
|
||||
|
||||
#include <unordered_set>
|
||||
#include "../ext/std_set.h"
|
||||
|
||||
namespace bitsery {
|
||||
template<typename S, typename ... TArgs>
|
||||
void serialize(S &s, std::unordered_set<TArgs...> &obj) {
|
||||
s.ext(obj, ext::StdSet{std::numeric_limits<size_t>::max()});
|
||||
}
|
||||
|
||||
template<typename S, typename ... TArgs>
|
||||
void serialize(S &s, std::unordered_multiset<TArgs...> &obj) {
|
||||
s.ext(obj, ext::StdSet{std::numeric_limits<size_t>::max()});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_STD_UNORDERED_SET_H
|
||||
@@ -21,8 +21,8 @@
|
||||
//SOFTWARE.
|
||||
|
||||
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_VECTOR_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_VECTOR_H
|
||||
#ifndef BITSERY_FLEXIBLE_TYPE_STD_VECTOR_H
|
||||
#define BITSERY_FLEXIBLE_TYPE_STD_VECTOR_H
|
||||
|
||||
#include "../traits/vector.h"
|
||||
#include "../details/flexible_common.h"
|
||||
@@ -34,4 +34,4 @@ namespace bitsery {
|
||||
}
|
||||
}
|
||||
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_VECTOR_H
|
||||
#endif //BITSERY_FLEXIBLE_TYPE_STD_VECTOR_H
|
||||
|
||||
@@ -30,10 +30,23 @@
|
||||
|
||||
namespace bitsery {
|
||||
|
||||
template<typename Config>
|
||||
template<typename Config, bool BitPackingEnabled>
|
||||
class BasicSerializer {
|
||||
public:
|
||||
explicit BasicSerializer(BasicBufferWriter<Config> &w, void* context = nullptr) : _writter{w}, _context{context} {};
|
||||
using BPEnabledType = BasicSerializer<Config, true>;
|
||||
|
||||
explicit BasicSerializer(BasicBufferWriter<Config> &w, void* context = nullptr)
|
||||
: _writer{w},
|
||||
_context{context}
|
||||
{};
|
||||
|
||||
//copying disabled
|
||||
BasicSerializer(const BasicSerializer&) = delete;
|
||||
BasicSerializer& operator = (const BasicSerializer&) = delete;
|
||||
|
||||
//move enabled
|
||||
BasicSerializer(BasicSerializer&& ) noexcept = default;
|
||||
BasicSerializer& operator = (BasicSerializer&& ) noexcept = default;
|
||||
|
||||
/*
|
||||
* get serialization context.
|
||||
@@ -74,7 +87,15 @@ namespace bitsery {
|
||||
template<size_t VSIZE, typename T, typename std::enable_if<details::IsFundamentalType<T>::value>::type * = nullptr>
|
||||
void value(const T &v) {
|
||||
using TValue = typename details::IntegralFromFundamental<T>::TValue;
|
||||
_writter.template writeBytes<VSIZE>(reinterpret_cast<const TValue &>(v));
|
||||
_writer.template writeBytes<VSIZE>(reinterpret_cast<const TValue &>(v));
|
||||
}
|
||||
|
||||
/*
|
||||
* enable bit-packing
|
||||
*/
|
||||
template <typename Fnc>
|
||||
void enableBitPacking(Fnc&& fnc) {
|
||||
procEnableBitPacking(std::forward<Fnc>(fnc), std::integral_constant<bool, !BitPackingEnabled>{});
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -85,7 +106,9 @@ namespace bitsery {
|
||||
void ext(const T &obj, const Ext &extension, Fnc &&fnc) {
|
||||
static_assert(details::ExtensionTraits<Ext,T>::SupportLambdaOverload,
|
||||
"extension doesn't support overload with lambda");
|
||||
extension.serialize(*this, _writter, obj, std::forward<Fnc>(fnc));
|
||||
static_assert(BitPackingEnabled || !details::ExtensionTraits<Ext,T>::BitPackingRequired,
|
||||
"Extension requires bit-packing to be enabled, (call `enableBitPacking`)");
|
||||
extension.serialize(*this, _writer, obj, std::forward<Fnc>(fnc));
|
||||
};
|
||||
|
||||
template<size_t VSIZE, typename T, typename Ext>
|
||||
@@ -94,7 +117,9 @@ namespace bitsery {
|
||||
"extension doesn't support overload with `value<N>`");
|
||||
using ExtVType = typename details::ExtensionTraits<Ext, T>::TValue;
|
||||
using VType = typename std::conditional<std::is_void<ExtVType>::value, details::DummyType, ExtVType>::type;
|
||||
extension.serialize(*this, _writter, obj, [this](VType &v) { value<VSIZE>(v); });
|
||||
static_assert(BitPackingEnabled || !details::ExtensionTraits<Ext,T>::BitPackingRequired,
|
||||
"Extension requires bit-packing to be enabled, (call `enableBitPacking`)");
|
||||
extension.serialize(*this, _writer, obj, [this](VType &v) { value<VSIZE>(v); });
|
||||
};
|
||||
|
||||
template<typename T, typename Ext>
|
||||
@@ -103,19 +128,17 @@ namespace bitsery {
|
||||
"extension doesn't support overload with `object`");
|
||||
using ExtVType = typename details::ExtensionTraits<Ext, T>::TValue;
|
||||
using VType = typename std::conditional<std::is_void<ExtVType>::value, details::DummyType, ExtVType>::type;
|
||||
extension.serialize(*this, _writter, obj, [this](VType &v) { object(v); });
|
||||
static_assert(BitPackingEnabled || !details::ExtensionTraits<Ext,T>::BitPackingRequired,
|
||||
"Extension requires bit-packing to be enabled, (call `enableBitPacking`)");
|
||||
extension.serialize(*this, _writer, obj, [this](VType &v) { object(v); });
|
||||
};
|
||||
|
||||
/*
|
||||
* bool
|
||||
* boolValue
|
||||
*/
|
||||
|
||||
void boolBit(bool v) {
|
||||
_writter.writeBits(static_cast<unsigned char>(v ? 1 : 0), 1);
|
||||
}
|
||||
|
||||
void boolByte(bool v) {
|
||||
_writter.template writeBytes<1>(static_cast<unsigned char>(v ? 1 : 0));
|
||||
void boolValue(bool v) {
|
||||
procBoolValue(v, std::integral_constant<bool, BitPackingEnabled>{});
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -149,7 +172,7 @@ namespace bitsery {
|
||||
"use container(const T&, Fnc) overload without `maxSize` for static containers");
|
||||
auto size = details::ContainerTraits<T>::size(obj);
|
||||
assert(size <= maxSize);
|
||||
details::writeSize(_writter, size);
|
||||
details::writeSize(_writer, size);
|
||||
procContainer(std::begin(obj), std::end(obj), std::forward<Fnc>(fnc));
|
||||
}
|
||||
|
||||
@@ -160,7 +183,7 @@ namespace bitsery {
|
||||
static_assert(VSIZE > 0, "");
|
||||
auto size = details::ContainerTraits<T>::size(obj);
|
||||
assert(size <= maxSize);
|
||||
details::writeSize(_writter, size);
|
||||
details::writeSize(_writer, size);
|
||||
|
||||
procContainer<VSIZE>(std::begin(obj), std::end(obj), std::integral_constant<bool, details::ContainerTraits<T>::isContiguous>{});
|
||||
}
|
||||
@@ -171,7 +194,7 @@ namespace bitsery {
|
||||
"use container(const T&) overload without `maxSize` for static containers");
|
||||
auto size = details::ContainerTraits<T>::size(obj);
|
||||
assert(size <= maxSize);
|
||||
details::writeSize(_writter, size);
|
||||
details::writeSize(_writer, size);
|
||||
procContainer(std::begin(obj), std::end(obj));
|
||||
}
|
||||
|
||||
@@ -200,7 +223,7 @@ namespace bitsery {
|
||||
}
|
||||
|
||||
void align() {
|
||||
_writter.align();
|
||||
_writer.align();
|
||||
}
|
||||
|
||||
//overloads for functions with explicit type size
|
||||
@@ -272,7 +295,11 @@ namespace bitsery {
|
||||
void container8b(T &&obj) { container<8>(std::forward<T>(obj)); }
|
||||
|
||||
private:
|
||||
BasicBufferWriter<Config> &_writter;
|
||||
|
||||
typename std::conditional<BitPackingEnabled,
|
||||
BitPackingWriter<Config>,//by value
|
||||
BasicBufferWriter<Config>&//by reference
|
||||
>::type _writer;
|
||||
void* _context;
|
||||
|
||||
//process value types
|
||||
@@ -290,7 +317,8 @@ namespace bitsery {
|
||||
using TValue = typename std::decay<decltype(*first)>::type;
|
||||
using TIntegral = typename details::IntegralFromFundamental<TValue>::TValue;
|
||||
if (first != last)
|
||||
_writter.template writeBuffer<VSIZE>(reinterpret_cast<const TIntegral*>(&(*first)), std::distance(first, last));
|
||||
_writer.template writeBuffer<VSIZE>(reinterpret_cast<const TIntegral*>(&(*first)),
|
||||
static_cast<size_t>(std::distance(first, last)));
|
||||
};
|
||||
|
||||
//process by calling functions
|
||||
@@ -307,7 +335,7 @@ namespace bitsery {
|
||||
void procText(const T& str, size_t maxSize) {
|
||||
auto length = details::TextTraits<T>::length(str);
|
||||
assert((length + (details::TextTraits<T>::addNUL ? 1u : 0u)) <= maxSize);
|
||||
details::writeSize(_writter, length);
|
||||
details::writeSize(_writer, length);
|
||||
auto begin = std::begin(str);
|
||||
procContainer<VSIZE>(begin, std::next(begin, length), std::integral_constant<bool, details::ContainerTraits<T>::isContiguous>{});
|
||||
};
|
||||
@@ -319,6 +347,27 @@ namespace bitsery {
|
||||
object(*first);
|
||||
};
|
||||
|
||||
//proc bool writing bit or byte, depending on if BitPackingEnabled or not
|
||||
void procBoolValue(bool v, std::true_type) {
|
||||
_writer.writeBits(static_cast<unsigned char>(v ? 1 : 0), 1);
|
||||
}
|
||||
|
||||
void procBoolValue(bool v, std::false_type) {
|
||||
_writer.template writeBytes<1>(static_cast<unsigned char>(v ? 1 : 0));
|
||||
}
|
||||
|
||||
//enable bit-packing or do nothing if it is already enabled
|
||||
template <typename Fnc>
|
||||
void procEnableBitPacking(const Fnc& fnc, std::true_type) {
|
||||
BPEnabledType tmp{_writer, _context};
|
||||
fnc(tmp);
|
||||
}
|
||||
|
||||
template <typename Fnc>
|
||||
void procEnableBitPacking(const Fnc& fnc, std::false_type) {
|
||||
fnc(*this);
|
||||
}
|
||||
|
||||
//these are dummy functions for extensions that have TValue = void
|
||||
void object(const details::DummyType&) {
|
||||
|
||||
@@ -336,7 +385,7 @@ namespace bitsery {
|
||||
};
|
||||
|
||||
//helper type
|
||||
using Serializer = BasicSerializer<DefaultConfig>;
|
||||
using Serializer = BasicSerializer<DefaultConfig, false>;
|
||||
|
||||
}
|
||||
#endif //BITSERY_SERIALIZER_H
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
//SOFTWARE.
|
||||
|
||||
|
||||
#ifndef BITSERY_TRAITS_ARRAY_H
|
||||
#define BITSERY_TRAITS_ARRAY_H
|
||||
#ifndef BITSERY_TRAITS_STD_ARRAY_H
|
||||
#define BITSERY_TRAITS_STD_ARRAY_H
|
||||
|
||||
#include "helper/std_defaults.h"
|
||||
#include <array>
|
||||
@@ -41,4 +41,4 @@ namespace bitsery {
|
||||
|
||||
}
|
||||
|
||||
#endif //BITSERY_TYPE_TRAITS_ARRAY_H
|
||||
#endif //BITSERY_TYPE_TRAITS_STD_ARRAY_H
|
||||
|
||||
42
include/bitsery/traits/deque.h
Normal file
42
include/bitsery/traits/deque.h
Normal file
@@ -0,0 +1,42 @@
|
||||
//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.
|
||||
|
||||
|
||||
#ifndef BITSERY_TRAITS_STD_DEQUE_H
|
||||
#define BITSERY_TRAITS_STD_DEQUE_H
|
||||
|
||||
#include "helper/std_defaults.h"
|
||||
#include <deque>
|
||||
|
||||
namespace bitsery {
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename ... TArgs>
|
||||
struct ContainerTraits<std::deque<TArgs...>>
|
||||
: public StdContainer<std::deque<TArgs...>, true, false> {};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //BITSERY_TRAITS_STD_DEQUE_H
|
||||
49
include/bitsery/traits/forward_list.h
Normal file
49
include/bitsery/traits/forward_list.h
Normal file
@@ -0,0 +1,49 @@
|
||||
//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.
|
||||
|
||||
|
||||
#ifndef BITSERY_TRAITS_STD_FORWARD_LIST_H
|
||||
#define BITSERY_TRAITS_STD_FORWARD_LIST_H
|
||||
|
||||
#include <forward_list>
|
||||
|
||||
namespace bitsery {
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename ... TArgs>
|
||||
struct ContainerTraits<std::forward_list<TArgs...>> {
|
||||
using TValue = typename std::forward_list<TArgs...>::value_type;
|
||||
static constexpr bool isResizable = true;
|
||||
static constexpr bool isContiguous = false;
|
||||
static size_t size(const std::forward_list<TArgs...>& container) {
|
||||
return static_cast<size_t>(std::distance(container.begin(), container.end()));
|
||||
}
|
||||
static void resize(std::forward_list<TArgs...>& container, size_t size) {
|
||||
container.resize(size);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //BITSERY_TRAITS_STD_FORWARD_LIST_H
|
||||
78
include/bitsery/traits/helper/std_defaults.h
Normal file
78
include/bitsery/traits/helper/std_defaults.h
Normal file
@@ -0,0 +1,78 @@
|
||||
//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.
|
||||
|
||||
#ifndef BITSERY_TRAITS_HELPER_STD_DEFAULTS_H
|
||||
#define BITSERY_TRAITS_HELPER_STD_DEFAULTS_H
|
||||
|
||||
namespace bitsery {
|
||||
namespace details {
|
||||
|
||||
/*
|
||||
* these are helper types, to easier write specializations for std types
|
||||
*/
|
||||
|
||||
template<typename T, bool Resizable, bool Contiguous>
|
||||
struct StdContainer {
|
||||
using TValue = typename T::value_type;
|
||||
static constexpr bool isResizable = Resizable;
|
||||
static constexpr bool isContiguous = Contiguous;
|
||||
static size_t size(const T& container) {
|
||||
return container.size();
|
||||
}
|
||||
};
|
||||
|
||||
//specialization for resizable
|
||||
template<typename T, bool Contiguous>
|
||||
struct StdContainer<T, true, Contiguous> {
|
||||
using TValue = typename T::value_type;
|
||||
static constexpr bool isResizable = true;
|
||||
static constexpr bool isContiguous = Contiguous;
|
||||
static size_t size(const T& container) {
|
||||
return container.size();
|
||||
}
|
||||
static void resize(T& container, size_t size) {
|
||||
container.resize(size);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, bool Resizable = ContainerTraits<T>::isResizable>
|
||||
struct StdContainerForBuffer {
|
||||
using TIterator = typename T::iterator;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct StdContainerForBuffer<T, true> {
|
||||
|
||||
static void increaseBufferSize(T& container) {
|
||||
//use default implementation behaviour;
|
||||
//call push_back to use default resize strategy
|
||||
container.push_back({});
|
||||
//after allocation resize to take all capacity
|
||||
container.resize(container.capacity());
|
||||
}
|
||||
using TIterator = typename T::iterator;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //BITSERY_TRAITS_HELPER_STD_DEFAULTS_H
|
||||
42
include/bitsery/traits/list.h
Normal file
42
include/bitsery/traits/list.h
Normal file
@@ -0,0 +1,42 @@
|
||||
//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.
|
||||
|
||||
|
||||
#ifndef BITSERY_TRAITS_STD_LIST_H
|
||||
#define BITSERY_TRAITS_STD_LIST_H
|
||||
|
||||
#include "helper/std_defaults.h"
|
||||
#include <list>
|
||||
|
||||
namespace bitsery {
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename ... TArgs>
|
||||
struct ContainerTraits<std::list<TArgs...>>
|
||||
: public StdContainer<std::list<TArgs...>, true, false> {};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //BITSERY_TRAITS_STD_LIST_H
|
||||
71
include/bitsery/traits/string.h
Normal file
71
include/bitsery/traits/string.h
Normal file
@@ -0,0 +1,71 @@
|
||||
//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.
|
||||
|
||||
|
||||
#ifndef BITSERY_TRAITS_STD_STRING_H
|
||||
#define BITSERY_TRAITS_STD_STRING_H
|
||||
|
||||
#include "helper/std_defaults.h"
|
||||
#include <string>
|
||||
|
||||
namespace bitsery {
|
||||
|
||||
namespace details {
|
||||
|
||||
// specialization for string, because string is already included for std::char_traits
|
||||
|
||||
template<typename ... TArgs>
|
||||
struct ContainerTraits<std::basic_string<TArgs...>>
|
||||
:public StdContainer<std::basic_string<TArgs...>, true, true> {};
|
||||
|
||||
template <typename ... TArgs>
|
||||
struct TextTraits<std::basic_string<TArgs...>> {
|
||||
|
||||
//string is automatically null-terminated
|
||||
static constexpr bool addNUL = false;
|
||||
|
||||
//is is not 100% accurate, but for performance reasons assume that string stores text, not binary data
|
||||
static size_t length(const std::basic_string<TArgs...>& str) {
|
||||
return str.size();
|
||||
}
|
||||
};
|
||||
|
||||
//specialization for c-array
|
||||
template <typename T, size_t N>
|
||||
struct TextTraits<T[N]> {
|
||||
|
||||
static constexpr bool addNUL = true;
|
||||
|
||||
static size_t length(const T (&container)[N]) {
|
||||
return std::char_traits<T>::length(container);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ... TArgs>
|
||||
struct BufferContainerTraits<std::basic_string<TArgs...>>
|
||||
:public StdContainerForBuffer<std::basic_string<TArgs...>> {};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //BITSERY_TRAITS_VECTOR_H
|
||||
@@ -21,8 +21,8 @@
|
||||
//SOFTWARE.
|
||||
|
||||
|
||||
#ifndef BITSERY_TRAITS_VECTOR_H
|
||||
#define BITSERY_TRAITS_VECTOR_H
|
||||
#ifndef BITSERY_TRAITS_STD_VECTOR_H
|
||||
#define BITSERY_TRAITS_STD_VECTOR_H
|
||||
|
||||
#include "helper/std_defaults.h"
|
||||
#include <vector>
|
||||
@@ -47,4 +47,4 @@ namespace bitsery {
|
||||
|
||||
}
|
||||
|
||||
#endif //BITSERY_TRAITS_VECTOR_H
|
||||
#endif //BITSERY_TRAITS_STD_VECTOR_H
|
||||
|
||||
@@ -44,7 +44,7 @@ file(GLOB TestSourceFiles ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
message(WARNING "extension tests for optional is disable for VS, because VS currenty doesn't have <optional>")
|
||||
list(REMOVE_ITEM TestSourceFiles ${CMAKE_CURRENT_SOURCE_DIR}/serialization_ext_optional.cpp)
|
||||
list(REMOVE_ITEM TestSourceFiles ${CMAKE_CURRENT_SOURCE_DIR}/serialization_ext_std_optional.cpp)
|
||||
endif()
|
||||
|
||||
include(${ExtCMakeFilesDir}/LinkTestLib.cmake)
|
||||
|
||||
@@ -161,18 +161,20 @@ TEST(BufferEndianness, WhenBufferValueTypeIs1ByteThenBitOperationsIsNotAffectedB
|
||||
//create and write to buffer
|
||||
Buffer buf{};
|
||||
bitsery::BasicBufferWriter<DefaultConfig> bw{buf};
|
||||
bw.writeBits(src.a, aBITS);
|
||||
bw.writeBits(src.b, bBITS);
|
||||
bw.writeBits(src.c, cBITS);
|
||||
bw.writeBits(src.d, dBITS);
|
||||
bw.flush();
|
||||
bitsery::BitPackingWriter<DefaultConfig> bpw{bw};
|
||||
bpw.writeBits(src.a, aBITS);
|
||||
bpw.writeBits(src.b, bBITS);
|
||||
bpw.writeBits(src.c, cBITS);
|
||||
bpw.writeBits(src.d, dBITS);
|
||||
bpw.flush();
|
||||
//read from buffer using inverse endianness config
|
||||
bitsery::BasicBufferReader<InverseEndiannessConfig> br{bw.getWrittenRange()};
|
||||
bitsery::BasicBufferReader<InverseEndiannessConfig> br{bpw.getWrittenRange()};
|
||||
bitsery::BitPackingReader<InverseEndiannessConfig> bpr{br};
|
||||
IntegralUnsignedTypes res{};
|
||||
br.readBits(res.a, aBITS);
|
||||
br.readBits(res.b, bBITS);
|
||||
br.readBits(res.c, cBITS);
|
||||
br.readBits(res.d, dBITS);
|
||||
bpr.readBits(res.a, aBITS);
|
||||
bpr.readBits(res.b, bBITS);
|
||||
bpr.readBits(res.c, cBITS);
|
||||
bpr.readBits(res.d, dBITS);
|
||||
//check results
|
||||
EXPECT_THAT(res.a, Eq(src.a));
|
||||
EXPECT_THAT(res.b, Eq(src.b));
|
||||
|
||||
@@ -30,6 +30,9 @@ using testing::Eq;
|
||||
using testing::ContainerEq;
|
||||
using bitsery::BufferWriter;
|
||||
using bitsery::BufferReader;
|
||||
|
||||
using BitPackingWriter = bitsery::BitPackingWriter<bitsery::DefaultConfig>;
|
||||
using BitPackingReader = bitsery::BitPackingReader<bitsery::DefaultConfig>;
|
||||
using Buffer = bitsery::DefaultConfig::BufferType;
|
||||
|
||||
struct IntegralUnsignedTypes {
|
||||
@@ -50,21 +53,23 @@ constexpr size_t getBits(T v) {
|
||||
TEST(BufferBitsAndBytesOperations, WriteAndReadBitsMaxTypeValues) {
|
||||
Buffer buf;
|
||||
BufferWriter bw{buf};
|
||||
bw.writeBits(std::numeric_limits<uint64_t>::max(), 64);
|
||||
bw.writeBits(std::numeric_limits<uint32_t>::max(), 32);
|
||||
bw.writeBits(std::numeric_limits<uint16_t>::max(), 16);
|
||||
bw.writeBits(std::numeric_limits<uint8_t>::max(), 8);
|
||||
bw.flush();
|
||||
BitPackingWriter bpw{bw};
|
||||
bpw.writeBits(std::numeric_limits<uint64_t>::max(), 64);
|
||||
bpw.writeBits(std::numeric_limits<uint32_t>::max(), 32);
|
||||
bpw.writeBits(std::numeric_limits<uint16_t>::max(), 16);
|
||||
bpw.writeBits(std::numeric_limits<uint8_t>::max(), 8);
|
||||
bpw.flush();
|
||||
|
||||
BufferReader br{bw.getWrittenRange()};
|
||||
BufferReader br{bpw.getWrittenRange()};
|
||||
BitPackingReader bpr{br};
|
||||
uint64_t v64{};
|
||||
uint32_t v32{};
|
||||
uint16_t v16{};
|
||||
uint8_t v8{};
|
||||
br.readBits(v64, 64);
|
||||
br.readBits(v32, 32);
|
||||
br.readBits(v16, 16);
|
||||
br.readBits(v8, 8);
|
||||
bpr.readBits(v64, 64);
|
||||
bpr.readBits(v32, 32);
|
||||
bpr.readBits(v16, 16);
|
||||
bpr.readBits(v8, 8);
|
||||
|
||||
EXPECT_THAT(v64, Eq(std::numeric_limits<uint64_t>::max()));
|
||||
EXPECT_THAT(v32, Eq(std::numeric_limits<uint32_t>::max()));
|
||||
@@ -91,25 +96,28 @@ TEST(BufferBitsAndBytesOperations, WriteAndReadBits) {
|
||||
//create and write to buffer
|
||||
Buffer buf;
|
||||
BufferWriter bw{buf};
|
||||
BitPackingWriter bpw{bw};
|
||||
|
||||
bw.writeBits(data.a, aBITS);
|
||||
bw.writeBits(data.b, bBITS);
|
||||
bw.writeBits(data.c, cBITS);
|
||||
bw.writeBits(data.d, dBITS);
|
||||
bw.writeBits(data.e, eBITS);
|
||||
bw.flush();
|
||||
auto range = bw.getWrittenRange();
|
||||
bpw.writeBits(data.a, aBITS);
|
||||
bpw.writeBits(data.b, bBITS);
|
||||
bpw.writeBits(data.c, cBITS);
|
||||
bpw.writeBits(data.d, dBITS);
|
||||
bpw.writeBits(data.e, eBITS);
|
||||
bpw.flush();
|
||||
auto range = bpw.getWrittenRange();
|
||||
auto bytesCount = ((aBITS + bBITS + cBITS + dBITS + eBITS) / 8) +1 ;
|
||||
EXPECT_THAT(std::distance(range.begin(), range.end()), Eq(bytesCount));
|
||||
//read from buffer
|
||||
BufferReader br{range};
|
||||
IntegralUnsignedTypes res;
|
||||
BitPackingReader bpr{br};
|
||||
|
||||
br.readBits(res.a, aBITS);
|
||||
br.readBits(res.b, bBITS);
|
||||
br.readBits(res.c, cBITS);
|
||||
br.readBits(res.d, dBITS);
|
||||
br.readBits(res.e, eBITS);
|
||||
IntegralUnsignedTypes res{};
|
||||
|
||||
bpr.readBits(res.a, aBITS);
|
||||
bpr.readBits(res.b, bBITS);
|
||||
bpr.readBits(res.c, cBITS);
|
||||
bpr.readBits(res.d, dBITS);
|
||||
bpr.readBits(res.e, eBITS);
|
||||
|
||||
EXPECT_THAT(res.a, Eq(data.a));
|
||||
EXPECT_THAT(res.b, Eq(data.b));
|
||||
@@ -125,66 +133,72 @@ TEST(BufferBitsAndBytesOperations, BufferSizeIsCountedPerByteNotPerBit) {
|
||||
//create and write to buffer
|
||||
Buffer buf;
|
||||
BufferWriter bw{buf};
|
||||
BitPackingWriter bpw{bw};
|
||||
|
||||
bw.writeBits(7u,3);
|
||||
bw.flush();
|
||||
auto range = bw.getWrittenRange();
|
||||
bpw.writeBits(7u,3);
|
||||
bpw.flush();
|
||||
auto range = bpw.getWrittenRange();
|
||||
EXPECT_THAT(std::distance(range.begin(), range.end()), Eq(1));
|
||||
|
||||
//read from buffer
|
||||
BufferReader br{range};
|
||||
BitPackingReader bpr{br};
|
||||
uint16_t tmp;
|
||||
br.readBits(tmp,4);
|
||||
br.readBits(tmp,2);
|
||||
br.readBits(tmp,2);
|
||||
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
|
||||
br.readBits(tmp,2);
|
||||
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));//false
|
||||
bpr.readBits(tmp,4);
|
||||
bpr.readBits(tmp,2);
|
||||
bpr.readBits(tmp,2);
|
||||
EXPECT_THAT(bpr.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
|
||||
bpr.readBits(tmp,2);
|
||||
EXPECT_THAT(bpr.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));//false
|
||||
|
||||
//part of next byte
|
||||
BufferReader br1{range};
|
||||
br1.readBits(tmp,2);
|
||||
EXPECT_THAT(br1.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
|
||||
br1.readBits(tmp,7);
|
||||
EXPECT_THAT(br1.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));//false
|
||||
BitPackingReader bpr1{br1};
|
||||
bpr1.readBits(tmp,2);
|
||||
EXPECT_THAT(bpr1.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
|
||||
bpr1.readBits(tmp,7);
|
||||
EXPECT_THAT(bpr1.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));//false
|
||||
|
||||
//bigger than byte
|
||||
BufferReader br2{range};
|
||||
br2.readBits(tmp,9);
|
||||
EXPECT_THAT(br2.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));//false
|
||||
BitPackingReader bpr2{br2};
|
||||
bpr2.readBits(tmp,9);
|
||||
EXPECT_THAT(bpr2.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));//false
|
||||
}
|
||||
|
||||
TEST(BufferBitsAndBytesOperations, ConsecutiveCallsToAlignHasNoEffect) {
|
||||
Buffer buf;
|
||||
BufferWriter bw{buf};
|
||||
BitPackingWriter bpw{bw};
|
||||
|
||||
bw.writeBits(3u, 2);
|
||||
bpw.writeBits(3u, 2);
|
||||
//3 calls to align after 1st data
|
||||
bw.align();
|
||||
bw.align();
|
||||
bw.align();
|
||||
bw.writeBits(7u, 3);
|
||||
bpw.align();
|
||||
bpw.align();
|
||||
bpw.align();
|
||||
bpw.writeBits(7u, 3);
|
||||
//1 call to align after 2nd data
|
||||
bw.align();
|
||||
bw.writeBits(15u, 4);
|
||||
bw.flush();
|
||||
bpw.align();
|
||||
bpw.writeBits(15u, 4);
|
||||
bpw.flush();
|
||||
|
||||
unsigned char tmp;
|
||||
BufferReader br{bw.getWrittenRange()};
|
||||
br.readBits(tmp,2);
|
||||
BufferReader br{bpw.getWrittenRange()};
|
||||
BitPackingReader bpr{br};
|
||||
bpr.readBits(tmp,2);
|
||||
EXPECT_THAT(tmp, Eq(3u));
|
||||
br.align();
|
||||
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
|
||||
br.readBits(tmp,3);
|
||||
br.align();
|
||||
br.align();
|
||||
br.align();
|
||||
bpr.align();
|
||||
EXPECT_THAT(bpr.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
|
||||
bpr.readBits(tmp,3);
|
||||
bpr.align();
|
||||
bpr.align();
|
||||
bpr.align();
|
||||
EXPECT_THAT(tmp, Eq(7u));
|
||||
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
|
||||
EXPECT_THAT(bpr.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
|
||||
|
||||
br.readBits(tmp,4);
|
||||
bpr.readBits(tmp,4);
|
||||
EXPECT_THAT(tmp, Eq(15u));
|
||||
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
|
||||
EXPECT_THAT(bpr.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
|
||||
}
|
||||
|
||||
TEST(BufferBitsAndBytesOperations, AlignWritesZerosBits) {
|
||||
@@ -193,25 +207,28 @@ TEST(BufferBitsAndBytesOperations, AlignWritesZerosBits) {
|
||||
//create and write to buffer
|
||||
Buffer buf;
|
||||
BufferWriter bw{buf};
|
||||
BitPackingWriter bpw{bw};
|
||||
|
||||
//write 2 bits and align
|
||||
bw.writeBits(3u, 2);
|
||||
bw.align();
|
||||
bw.flush();
|
||||
auto range = bw.getWrittenRange();
|
||||
bpw.writeBits(3u, 2);
|
||||
bpw.align();
|
||||
bpw.flush();
|
||||
auto range = bpw.getWrittenRange();
|
||||
EXPECT_THAT(std::distance(range.begin(), range.end()), Eq(1));
|
||||
unsigned char tmp;
|
||||
BufferReader br1{range};
|
||||
br1.readBits(tmp,2);
|
||||
BitPackingReader bpr1{br1};
|
||||
bpr1.readBits(tmp,2);
|
||||
//read aligned bits
|
||||
br1.readBits(tmp,6);
|
||||
bpr1.readBits(tmp,6);
|
||||
EXPECT_THAT(tmp, Eq(0));
|
||||
|
||||
BufferReader br2{range};
|
||||
BitPackingReader bpr2{br2};
|
||||
//read 2 bits
|
||||
br2.readBits(tmp,2);
|
||||
br2.align();
|
||||
EXPECT_THAT(br2.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
|
||||
bpr2.readBits(tmp,2);
|
||||
bpr2.align();
|
||||
EXPECT_THAT(bpr2.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
|
||||
}
|
||||
|
||||
|
||||
@@ -295,23 +312,25 @@ TEST(BufferBitsAndBytesOperations, ReadWriteBufferCanWorkOnUnalignedData) {
|
||||
//create and write to buffer
|
||||
Buffer buf{};
|
||||
BufferWriter bw{buf};
|
||||
bw.writeBits(15u, 4);
|
||||
bw.writeBuffer<2>(src, DATA_SIZE);
|
||||
bw.writeBits(12u, 4);
|
||||
bw.flush();
|
||||
auto range = bw.getWrittenRange();
|
||||
BitPackingWriter bpw{bw};
|
||||
bpw.writeBits(15u, 4);
|
||||
bpw.writeBuffer<2>(src, DATA_SIZE);
|
||||
bpw.writeBits(12u, 4);
|
||||
bpw.flush();
|
||||
auto range = bpw.getWrittenRange();
|
||||
EXPECT_THAT(std::distance(range.begin(), range.end()), Eq(sizeof(src) + 1));
|
||||
|
||||
//read from buffer
|
||||
BufferReader br1{range};
|
||||
BitPackingReader bpr1{br1};
|
||||
int16_t dst[DATA_SIZE]{};
|
||||
uint8_t tmp{};
|
||||
br1.readBits(tmp, 4);
|
||||
bpr1.readBits(tmp, 4);
|
||||
EXPECT_THAT(tmp, Eq(15));
|
||||
br1.readBuffer<2>(dst, DATA_SIZE);
|
||||
EXPECT_THAT(br1.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
|
||||
bpr1.readBuffer<2>(dst, DATA_SIZE);
|
||||
EXPECT_THAT(bpr1.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
|
||||
EXPECT_THAT(dst, ContainerEq(src));
|
||||
br1.readBits(tmp, 4);
|
||||
bpr1.readBits(tmp, 4);
|
||||
EXPECT_THAT(tmp, Eq(12));
|
||||
}
|
||||
|
||||
@@ -322,21 +341,23 @@ TEST(BufferBitsAndBytesOperations, RegressionTestReadBytesAfterReadBitsWithLotsO
|
||||
//create and write to buffer
|
||||
Buffer buf{};
|
||||
BufferWriter bw{buf};
|
||||
bw.writeBits(2u, 2);
|
||||
bw.writeBytes<2>(data[0]);
|
||||
bw.writeBytes<2>(data[1]);
|
||||
bw.align();
|
||||
bw.flush();
|
||||
auto range = bw.getWrittenRange();
|
||||
BitPackingWriter bpw{bw};
|
||||
bpw.writeBits(2u, 2);
|
||||
bpw.writeBytes<2>(data[0]);
|
||||
bpw.writeBytes<2>(data[1]);
|
||||
bpw.align();
|
||||
bpw.flush();
|
||||
auto range = bpw.getWrittenRange();
|
||||
|
||||
//read from buffer
|
||||
BufferReader br{range};
|
||||
BitPackingReader bpr{br};
|
||||
uint8_t tmp{};
|
||||
br.readBits(tmp, 2);
|
||||
bpr.readBits(tmp, 2);
|
||||
EXPECT_THAT(tmp, Eq(2));
|
||||
br.readBytes<2>(res[0]);
|
||||
br.readBytes<2>(res[1]);
|
||||
br.align();
|
||||
bpr.readBytes<2>(res[0]);
|
||||
bpr.readBytes<2>(res[1]);
|
||||
bpr.align();
|
||||
EXPECT_THAT(res[0], Eq(data[0]));
|
||||
EXPECT_THAT(res[1], Eq(data[1]));
|
||||
}
|
||||
|
||||
@@ -140,17 +140,18 @@ TEST(BufferReading, WhenReaderHasErrorsAllOperationsReadsReturnZero) {
|
||||
bw.flush();
|
||||
//read from buffer
|
||||
BufferReader br{bw.getWrittenRange()};
|
||||
bitsery::BitPackingReader<bitsery::DefaultConfig> bpr{br};
|
||||
int32_t c;
|
||||
br.readBytes<4>(c);
|
||||
bpr.readBytes<4>(c);
|
||||
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));
|
||||
|
||||
int16_t r1= {-645};
|
||||
uint32_t r2[2] = {54898,87854};
|
||||
uint8_t r3 = 0xFF;
|
||||
|
||||
br.readBytes<2>(r1);
|
||||
br.readBuffer<4>(r2, 2);
|
||||
br.readBits(r3, 7);
|
||||
bpr.readBytes<2>(r1);
|
||||
bpr.readBuffer<4>(r2, 2);
|
||||
bpr.readBits(r3, 7);
|
||||
EXPECT_THAT(r1, Eq(0));
|
||||
EXPECT_THAT(r2[0], Eq(0u));
|
||||
EXPECT_THAT(r2[1], Eq(0u));
|
||||
|
||||
@@ -44,9 +44,9 @@ TEST(BufferReadingErrors, WhenReadingBoolByteReadsMoreThanOneThenInvalidBufferDa
|
||||
ser.value1b(uint8_t{2});
|
||||
bool res{};
|
||||
auto des = ctx.createDeserializer();
|
||||
des.boolByte(res);
|
||||
des.boolValue(res);
|
||||
EXPECT_THAT(res, Eq(true));
|
||||
des.boolByte(res);
|
||||
des.boolValue(res);
|
||||
EXPECT_THAT(res, Eq(false));
|
||||
EXPECT_THAT(ctx.br->getError(), Eq(bitsery::BufferReaderError::INVALID_BUFFER_DATA));
|
||||
}
|
||||
@@ -57,11 +57,13 @@ TEST(BufferReadingErrors, WhenReadingAlignHasNonZerosThenInvalidBufferDataError)
|
||||
uint8_t tmp{0xFF};
|
||||
bw.writeBytes<1>(tmp);
|
||||
bw.flush();
|
||||
BufferReader br{bw.getWrittenRange()};
|
||||
|
||||
br.readBits(tmp,3);
|
||||
br.align();
|
||||
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::INVALID_BUFFER_DATA));
|
||||
BufferReader br{bw.getWrittenRange()};
|
||||
bitsery::BitPackingReader<bitsery::DefaultConfig> bpr{br};
|
||||
|
||||
bpr.readBits(tmp,3);
|
||||
bpr.align();
|
||||
EXPECT_THAT(bpr.getError(), Eq(bitsery::BufferReaderError::INVALID_BUFFER_DATA));
|
||||
}
|
||||
|
||||
TEST(BufferReadingErrors, WhenReadingNewSessionInMiddleOfOldDataThenInvalidBufferError) {
|
||||
|
||||
@@ -83,10 +83,11 @@ TYPED_TEST(BufferWriting, WhenWritingBitsThenMustFlushWriter) {
|
||||
using Buffer = typename Config::BufferType;
|
||||
Buffer buf{};
|
||||
bitsery::BasicBufferWriter<Config> bw{buf};
|
||||
bw.writeBits(3u, 2);
|
||||
auto range1 = bw.getWrittenRange();
|
||||
bw.flush();
|
||||
auto range2 = bw.getWrittenRange();
|
||||
bitsery::BitPackingWriter<Config> bpw{bw};
|
||||
bpw.writeBits(3u, 2);
|
||||
auto range1 = bpw.getWrittenRange();
|
||||
bpw.flush();
|
||||
auto range2 = bpw.getWrittenRange();
|
||||
EXPECT_THAT(std::distance(range1.begin(), range1.end()), Eq(0));
|
||||
EXPECT_THAT(std::distance(range2.begin(), range2.end()), Eq(1));
|
||||
}
|
||||
@@ -96,12 +97,12 @@ TYPED_TEST(BufferWriting, WhenDataAlignedThenFlushHasNoEffect) {
|
||||
using Buffer = typename Config::BufferType;
|
||||
Buffer buf{};
|
||||
bitsery::BasicBufferWriter<Config> bw{buf};
|
||||
|
||||
bw.writeBits(3u, 2);
|
||||
bw.align();
|
||||
auto range1 = bw.getWrittenRange();
|
||||
bw.flush();
|
||||
auto range2 = bw.getWrittenRange();
|
||||
bitsery::BitPackingWriter<Config> bpw{bw};
|
||||
bpw.writeBits(3u, 2);
|
||||
bpw.align();
|
||||
auto range1 = bpw.getWrittenRange();
|
||||
bpw.flush();
|
||||
auto range2 = bpw.getWrittenRange();
|
||||
EXPECT_THAT(std::distance(range1.begin(), range1.end()), Eq(1));
|
||||
EXPECT_THAT(std::distance(range2.begin(), range2.end()), Eq(1));
|
||||
}
|
||||
|
||||
351
tests/flexible_syntax.cpp
Normal file
351
tests/flexible_syntax.cpp
Normal file
@@ -0,0 +1,351 @@
|
||||
//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 "serialization_test_utils.h"
|
||||
#include <bitsery/flexible.h>
|
||||
|
||||
#include <bitsery/flexible/string.h>
|
||||
#include <bitsery/flexible/array.h>
|
||||
#include <bitsery/flexible/vector.h>
|
||||
#include <bitsery/flexible/list.h>
|
||||
#include <bitsery/flexible/forward_list.h>
|
||||
#include <bitsery/flexible/deque.h>
|
||||
#include <bitsery/flexible/queue.h>
|
||||
#include <bitsery/flexible/stack.h>
|
||||
#include <bitsery/flexible/map.h>
|
||||
#include <bitsery/flexible/unordered_map.h>
|
||||
#include <bitsery/flexible/set.h>
|
||||
#include <bitsery/flexible/unordered_set.h>
|
||||
|
||||
using testing::Eq;
|
||||
|
||||
TEST(FlexibleSyntax, FundamentalTypesAndBool) {
|
||||
int ti = 8745;
|
||||
MyEnumClass te = MyEnumClass::E4;
|
||||
float tf = 485.042f;
|
||||
double_t td = -454184.48445;
|
||||
bool tb=true;
|
||||
SerializationContext ctx;
|
||||
ctx.createSerializer().archive(ti,te,tf,td,tb);
|
||||
|
||||
//result
|
||||
int ri{};
|
||||
MyEnumClass re{};
|
||||
float rf{};
|
||||
double_t rd{};
|
||||
bool rb{};
|
||||
ctx.createDeserializer().archive(ri,re,rf,rd,rb);
|
||||
|
||||
//test
|
||||
EXPECT_THAT(ri, Eq(ti));
|
||||
EXPECT_THAT(re, Eq(te));
|
||||
EXPECT_THAT(rf, Eq(tf));
|
||||
EXPECT_THAT(rd, Eq(td));
|
||||
EXPECT_THAT(rb, Eq(tb));
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, UseObjectFncInsteadOfValueN) {
|
||||
int ti = 8745;
|
||||
MyEnumClass te = MyEnumClass::E4;
|
||||
float tf = 485.042f;
|
||||
double_t td = -454184.48445;
|
||||
bool tb=true;
|
||||
SerializationContext ctx;
|
||||
auto ser = ctx.createSerializer();
|
||||
ser.object(ti);
|
||||
ser.object(te);
|
||||
ser.object(tf);
|
||||
ser.object(td);
|
||||
ser.object(tb);
|
||||
|
||||
//result
|
||||
int ri{};
|
||||
MyEnumClass re{};
|
||||
float rf{};
|
||||
double_t rd{};
|
||||
bool rb{};
|
||||
auto des = ctx.createDeserializer();
|
||||
des.object(ri);
|
||||
des.object(re);
|
||||
des.object(rf);
|
||||
des.object(rd);
|
||||
des.object(rb);
|
||||
|
||||
//test
|
||||
EXPECT_THAT(ri, Eq(ti));
|
||||
EXPECT_THAT(re, Eq(te));
|
||||
EXPECT_THAT(rf, Eq(tf));
|
||||
EXPECT_THAT(rd, Eq(td));
|
||||
EXPECT_THAT(rb, Eq(tb));
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, MixDifferentSyntax) {
|
||||
int ti = 8745;
|
||||
MyEnumClass te = MyEnumClass::E4;
|
||||
float tf = 485.042f;
|
||||
double_t td = -454184.48445;
|
||||
bool tb=true;
|
||||
SerializationContext ctx;
|
||||
auto ser = ctx.createSerializer();
|
||||
ser.value<sizeof(ti)>(ti);
|
||||
ser.archive(te, tf, td);
|
||||
ser.object(tb);
|
||||
|
||||
//result
|
||||
int ri{};
|
||||
MyEnumClass re{};
|
||||
float rf{};
|
||||
double_t rd{};
|
||||
bool rb{};
|
||||
auto des = ctx.createDeserializer();
|
||||
des.archive(ri, re, rf);
|
||||
des.value8b(rd);
|
||||
des.object(rb);
|
||||
|
||||
//test
|
||||
EXPECT_THAT(ri, Eq(ti));
|
||||
EXPECT_THAT(re, Eq(te));
|
||||
EXPECT_THAT(rf, Eq(tf));
|
||||
EXPECT_THAT(rd, Eq(td));
|
||||
EXPECT_THAT(rb, Eq(tb));
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
T procArchive(const T& testData) {
|
||||
SerializationContext ctx;
|
||||
ctx.createSerializer().archive(testData);
|
||||
T res;
|
||||
ctx.createDeserializer().archive(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, CStyleArrayForValueTypesAsContainer) {
|
||||
const int t1[3]{8748,-484,45};
|
||||
int r1[3]{0,0,0};
|
||||
|
||||
SerializationContext ctx;
|
||||
ctx.createSerializer().archive(bitsery::asContainer(t1));
|
||||
ctx.createDeserializer().archive(bitsery::asContainer(r1));
|
||||
|
||||
EXPECT_THAT(r1, ::testing::ContainerEq(t1));
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, CStyleArrayForIntegralTypesAsText) {
|
||||
const char t1[3]{"hi"};
|
||||
char r1[3]{0,0,0};
|
||||
|
||||
SerializationContext ctx;
|
||||
ctx.createSerializer().archive(bitsery::asText(t1));
|
||||
ctx.createDeserializer().archive(bitsery::asText(r1));
|
||||
|
||||
EXPECT_THAT(r1, ::testing::ContainerEq(t1));
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, CStyleArray) {
|
||||
const MyEnumClass t1[3]{MyEnumClass::E1, MyEnumClass::E4, MyEnumClass::E2};
|
||||
MyEnumClass r1[3]{};
|
||||
|
||||
SerializationContext ctx;
|
||||
ctx.createSerializer().archive(t1);
|
||||
ctx.createDeserializer().archive(r1);
|
||||
|
||||
EXPECT_THAT(r1, ::testing::ContainerEq(t1));
|
||||
}
|
||||
|
||||
|
||||
TEST(FlexibleSyntax, StdString) {
|
||||
std::string t1{"my nice string"};
|
||||
std::string t2{};
|
||||
|
||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||
EXPECT_THAT(procArchive(t2), Eq(t2));
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdArray) {
|
||||
std::array<int, 3> t1{8748,-484,45};
|
||||
std::array<int, 0> t2{};
|
||||
|
||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||
EXPECT_THAT(procArchive(t2), Eq(t2));
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdVector) {
|
||||
std::vector<int> t1{8748,-484,45};
|
||||
std::vector<float> t2{5.f,0.198f};
|
||||
|
||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||
EXPECT_THAT(procArchive(t2), Eq(t2));
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdList) {
|
||||
std::list<int> t1{8748,-484,45};
|
||||
std::list<float> t2{5.f,0.198f};
|
||||
|
||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||
EXPECT_THAT(procArchive(t2), Eq(t2));
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdForwardList) {
|
||||
std::forward_list<int> t1{8748,-484,45};
|
||||
std::forward_list<float> t2{5.f,0.198f};
|
||||
|
||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||
EXPECT_THAT(procArchive(t2), Eq(t2));
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdDeque) {
|
||||
std::deque<int> t1{8748,-484,45};
|
||||
std::deque<float> t2{5.f,0.198f};
|
||||
|
||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||
EXPECT_THAT(procArchive(t2), Eq(t2));
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdQueue) {
|
||||
std::queue<std::string> t1;
|
||||
t1.push("first");
|
||||
t1.push("second string");
|
||||
|
||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdPriorityQueue) {
|
||||
std::priority_queue<std::string> t1;
|
||||
t1.push("first");
|
||||
t1.push("second string");
|
||||
t1.push("third");
|
||||
t1.push("fourth");
|
||||
auto r1 = procArchive(t1);
|
||||
//we cannot compare priority queue directly
|
||||
|
||||
EXPECT_THAT(r1.size(), Eq(t1.size()));
|
||||
for (auto i = 0u; i < r1.size(); ++i) {
|
||||
EXPECT_THAT(r1.top(), Eq(t1.top()));
|
||||
r1.pop();
|
||||
t1.pop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdStack) {
|
||||
std::stack<std::string> t1;
|
||||
t1.push("first");
|
||||
t1.push("second string");
|
||||
|
||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdUnorderedMap) {
|
||||
std::unordered_map<int, int> t1;
|
||||
t1.emplace(3423,624);
|
||||
t1.emplace(-5484,-845);
|
||||
|
||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdUnorderedMultiMap) {
|
||||
std::unordered_multimap<std::string, int> t1;
|
||||
t1.emplace("one",624);
|
||||
t1.emplace("two",-845);
|
||||
t1.emplace("one",897);
|
||||
|
||||
EXPECT_TRUE(procArchive(t1) == t1);
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdMap) {
|
||||
std::map<int, int> t1;
|
||||
t1.emplace(3423,624);
|
||||
t1.emplace(-5484,-845);
|
||||
|
||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdMultiMap) {
|
||||
std::multimap<std::string, int> t1;
|
||||
t1.emplace("one",624);
|
||||
t1.emplace("two",-845);
|
||||
t1.emplace("one",897);
|
||||
|
||||
auto res = procArchive(t1);
|
||||
//same key values is not ordered, and operator == compares each element at same position
|
||||
//so we need to compare our selves
|
||||
EXPECT_THAT(res.size(), Eq(3));
|
||||
for (auto it = t1.begin(); it != t1.end();) {
|
||||
const auto lr = t1.equal_range(it->first);
|
||||
const auto rr = res.equal_range(it->first);
|
||||
EXPECT_TRUE(std::distance(lr.first, lr.second) == std::distance(rr.first, rr.second));
|
||||
EXPECT_TRUE(std::is_permutation(lr.first, lr.second, rr.first));
|
||||
it = lr.second;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdUnorderedSet) {
|
||||
std::unordered_set<std::string> t1;
|
||||
t1.emplace("one");
|
||||
t1.emplace("two");
|
||||
t1.emplace("three");
|
||||
|
||||
EXPECT_TRUE(procArchive(t1) == t1);
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdUnorderedMultiSet) {
|
||||
std::unordered_multiset<std::string> t1;
|
||||
t1.emplace("one");
|
||||
t1.emplace("two");
|
||||
t1.emplace("three");
|
||||
t1.emplace("one");
|
||||
|
||||
EXPECT_TRUE(procArchive(t1) == t1);
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdSet) {
|
||||
std::set<std::string> t1;
|
||||
t1.emplace("one");
|
||||
t1.emplace("two");
|
||||
t1.emplace("three");
|
||||
|
||||
EXPECT_TRUE(procArchive(t1) == t1);
|
||||
|
||||
}
|
||||
|
||||
TEST(FlexibleSyntax, StdMultiSet) {
|
||||
std::multiset<std::string> t1;
|
||||
t1.emplace("one");
|
||||
t1.emplace("two");
|
||||
t1.emplace("three");
|
||||
t1.emplace("one");
|
||||
t1.emplace("two");
|
||||
|
||||
EXPECT_TRUE(procArchive(t1) == t1);
|
||||
}
|
||||
|
||||
|
||||
TEST(FlexibleSyntax, NestedTypes) {
|
||||
std::unordered_map<std::string, std::vector<std::string>> t1;
|
||||
t1.emplace("my key", std::vector<std::string>{"very", "nice", "string"});
|
||||
t1.emplace("other key", std::vector<std::string>{"just a string"});
|
||||
|
||||
EXPECT_THAT(procArchive(t1), Eq(t1));
|
||||
}
|
||||
@@ -26,19 +26,30 @@
|
||||
|
||||
using testing::Eq;
|
||||
|
||||
template <bool BitPackingEnabled>
|
||||
using Serializer = bitsery::BasicSerializer<bitsery::DefaultConfig, BitPackingEnabled>;
|
||||
|
||||
template <bool BitPackingEnabled>
|
||||
using Deserializer = bitsery::BasicDeserializer<bitsery::DefaultConfig, BitPackingEnabled>;
|
||||
|
||||
|
||||
TEST(SerializeBooleans, BoolAsBit) {
|
||||
|
||||
SerializationContext ctx;
|
||||
bool t1{true};
|
||||
bool t2{false};
|
||||
bool res1;
|
||||
bool res2;
|
||||
auto ser = ctx.createSerializer();
|
||||
ser.boolBit(t1);
|
||||
ser.boolBit(t2);
|
||||
ser.enableBitPacking([&t1, &t2](Serializer<true>& sbp) {
|
||||
sbp.boolValue(t1);
|
||||
sbp.boolValue(t2);
|
||||
});
|
||||
auto des = ctx.createDeserializer();
|
||||
des.boolBit(res1);
|
||||
des.boolBit(res2);
|
||||
des.enableBitPacking([&res1, &res2](Deserializer <true>& sbp) {
|
||||
sbp.boolValue(res1);
|
||||
sbp.boolValue(res2);
|
||||
});
|
||||
|
||||
EXPECT_THAT(res1, Eq(t1));
|
||||
EXPECT_THAT(res2, Eq(t2));
|
||||
@@ -52,11 +63,11 @@ TEST(SerializeBooleans, BoolAsByte) {
|
||||
bool res1;
|
||||
bool res2;
|
||||
auto ser = ctx.createSerializer();
|
||||
ser.boolByte(t1);
|
||||
ser.boolByte(t2);
|
||||
ser.boolValue(t1);
|
||||
ser.boolValue(t2);
|
||||
auto des = ctx.createDeserializer();
|
||||
des.boolByte(res1);
|
||||
des.boolByte(res2);
|
||||
des.boolValue(res1);
|
||||
des.boolValue(res2);
|
||||
|
||||
EXPECT_THAT(res1, Eq(t1));
|
||||
EXPECT_THAT(res2, Eq(t2));
|
||||
|
||||
@@ -25,13 +25,12 @@
|
||||
#include <gmock/gmock.h>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
// #include <deque>
|
||||
|
||||
#include "serialization_test_utils.h"
|
||||
#include <bitsery/traits/array.h>
|
||||
#include <bitsery/traits/list.h>
|
||||
#include <bitsery/traits/deque.h>
|
||||
|
||||
|
||||
#include <bitsery/traits/forward_list.h>
|
||||
|
||||
using testing::ContainerEq;
|
||||
using testing::Eq;
|
||||
@@ -81,13 +80,15 @@ public:
|
||||
TContainer res{};
|
||||
|
||||
size_t getExpectedBufSize(const SerializationContext &ctx) const {
|
||||
return ctx.containerSizeSerializedBytesCount(src.size()) + src.size() * sizeof(TValue);
|
||||
auto size = bitsery::details::ContainerTraits<TContainer>::size(src);
|
||||
return ctx.containerSizeSerializedBytesCount(size) + size * sizeof(TValue);
|
||||
}
|
||||
};
|
||||
//std::forward_list is not supported, because it doesn't have size() method
|
||||
using SequenceContainersWithArthmeticTypes = ::testing::Types<
|
||||
std::vector<int>,
|
||||
std::list<float>,
|
||||
std::forward_list<int>,
|
||||
std::deque<unsigned short>>;
|
||||
|
||||
TYPED_TEST_CASE(SerializeContainerDynamicSizeArthmeticTypes, SequenceContainersWithArthmeticTypes);
|
||||
|
||||
@@ -36,15 +36,15 @@ TEST(SerializeExtensionEntropy, WhenEntropyEncodedThenOnlyWriteIndexUsingMinRequ
|
||||
constexpr size_t N = 3;
|
||||
int32_t values[3] = {485,4849,89};
|
||||
SerializationContext ctx;
|
||||
ctx.createSerializer().ext4b(v, Entropy<int32_t[3]>{values});
|
||||
ctx.createDeserializer().ext4b(res, Entropy<int32_t[3]>{values});
|
||||
ctx.createBPEnabledSerializer().ext4b(v, Entropy<int32_t[3]>{values});
|
||||
ctx.createBPEnabledDeserializer().ext4b(res, Entropy<int32_t[3]>{values});
|
||||
|
||||
EXPECT_THAT(res, Eq(v));
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
|
||||
|
||||
SerializationContext ctx1;
|
||||
ctx1.createSerializer().ext4b(v, Entropy<int32_t[3]>{values});
|
||||
auto des = ctx1.createDeserializer();
|
||||
ctx1.createBPEnabledSerializer().ext4b(v, Entropy<int32_t[3]>{values});
|
||||
auto des = ctx1.createBPEnabledDeserializer();
|
||||
des.ext(res, bitsery::ext::ValueRange<int32_t>{0, static_cast<int32_t>(N + 1)});
|
||||
EXPECT_THAT(res, Eq(2));
|
||||
}
|
||||
@@ -54,8 +54,8 @@ TEST(SerializeExtensionEntropy, WhenNoEntropyEncodedThenWriteZeroBitsAndValueOrO
|
||||
int16_t res;
|
||||
std::initializer_list<int> values{485,4849,89};
|
||||
SerializationContext ctx;
|
||||
ctx.createSerializer().ext2b(v, Entropy<std::initializer_list<int>>{values});
|
||||
ctx.createDeserializer().ext2b(res, Entropy<std::initializer_list<int>>{values});
|
||||
ctx.createBPEnabledSerializer().ext2b(v, Entropy<std::initializer_list<int>>{values});
|
||||
ctx.createBPEnabledDeserializer().ext2b(res, Entropy<std::initializer_list<int>>{values});
|
||||
|
||||
EXPECT_THAT(res, Eq(v));
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(sizeof(int16_t)+1));
|
||||
@@ -70,8 +70,8 @@ TEST(SerializeExtensionEntropy, CustomTypeEntropyEncoded) {
|
||||
MyStruct1{12, 10}, MyStruct1{485, 454},
|
||||
MyStruct1{4849, 89}, MyStruct1{0, 1}};
|
||||
SerializationContext ctx;
|
||||
ctx.createSerializer().ext(v, Entropy<MyStruct1[N]>{values});
|
||||
ctx.createDeserializer().ext(res, Entropy<MyStruct1[N]>{values});
|
||||
ctx.createBPEnabledSerializer().ext(v, Entropy<MyStruct1[N]>{values});
|
||||
ctx.createBPEnabledDeserializer().ext(res, Entropy<MyStruct1[N]>{values});
|
||||
|
||||
EXPECT_THAT(res, Eq(v));
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
|
||||
@@ -86,14 +86,14 @@ TEST(SerializeExtensionEntropy, CustomTypeNotEntropyEncoded) {
|
||||
MyStruct1{4849,89}, MyStruct1{0,1}};
|
||||
SerializationContext ctx;
|
||||
|
||||
ctx.createSerializer().ext(v, Entropy<std::initializer_list<MyStruct1>>{values});
|
||||
ctx.createDeserializer().ext(res, Entropy<std::initializer_list<MyStruct1>>{values});
|
||||
ctx.createBPEnabledSerializer().ext(v, Entropy<std::initializer_list<MyStruct1>>{values});
|
||||
ctx.createBPEnabledDeserializer().ext(res, Entropy<std::initializer_list<MyStruct1>>{values});
|
||||
|
||||
EXPECT_THAT(res, Eq(v));
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(MyStruct1::SIZE + 1));
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionEntropy, CustomFunctionNotEntropyEncoded) {
|
||||
TEST(SerializeExtensionEntropy, CustomFunctionNotEntropyEncodedWithNoAlignBeforeData) {
|
||||
MyStruct1 v = {8945,4456};
|
||||
MyStruct1 res;
|
||||
constexpr size_t N = 4;
|
||||
@@ -103,29 +103,61 @@ TEST(SerializeExtensionEntropy, CustomFunctionNotEntropyEncoded) {
|
||||
MyStruct1{4849,89}, MyStruct1{0,1}};
|
||||
|
||||
auto rangeForValue = bitsery::ext::ValueRange<int>{0, 10000};
|
||||
auto rangeForIndex = bitsery::ext::ValueRange<size_t>{0u, N+1};
|
||||
|
||||
SerializationContext ctx;
|
||||
auto ser = ctx.createSerializer();
|
||||
auto& ser = ctx.createBPEnabledSerializer();
|
||||
|
||||
//lambdas differ only in capture clauses, it would make sense to use std::bind, but debugger crashes when it sees std::bind...
|
||||
auto serLambda = [&ser, &rangeForValue](MyStruct1& v) {
|
||||
ser.ext(v.i1, rangeForValue);
|
||||
ser.ext(v.i2, rangeForValue);
|
||||
auto serLambda = [&ser, &rangeForValue](MyStruct1& data) {
|
||||
ser.ext(data.i1, rangeForValue);
|
||||
ser.ext(data.i2, rangeForValue);
|
||||
};
|
||||
ser.ext(v, Entropy<std::vector<MyStruct1>>(values), serLambda);
|
||||
ser.ext(v, Entropy<std::vector<MyStruct1>>(values, false), serLambda);
|
||||
|
||||
auto des = ctx.createDeserializer();
|
||||
auto desLambda = [&des, &rangeForValue](MyStruct1& v) {
|
||||
des.ext(v.i1, rangeForValue);
|
||||
des.ext(v.i2, rangeForValue);
|
||||
auto des = ctx.createBPEnabledDeserializer();
|
||||
auto desLambda = [&des, &rangeForValue](MyStruct1& data) {
|
||||
des.ext(data.i1, rangeForValue);
|
||||
des.ext(data.i2, rangeForValue);
|
||||
};
|
||||
des.ext(res, Entropy<std::vector<MyStruct1>>(values), desLambda);
|
||||
des.ext(res, Entropy<std::vector<MyStruct1>>(values, false), desLambda);
|
||||
|
||||
EXPECT_THAT(res, Eq(v));
|
||||
auto rangeForIndex = bitsery::ext::ValueRange<size_t>{0u, N+1};
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq((rangeForIndex.getRequiredBits() + rangeForValue.getRequiredBits() * 2 - 1) / 8 + 1 ));
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionEntropy, CustomFunctionNotEntropyEncodedWithAlignBeforeData) {
|
||||
MyStruct1 v = {8945,4456};
|
||||
MyStruct1 res;
|
||||
|
||||
std::vector<MyStruct1> values{
|
||||
MyStruct1{12,10}, MyStruct1{485, 454},
|
||||
MyStruct1{4849,89}, MyStruct1{0,1}};
|
||||
|
||||
auto rangeForValue = bitsery::ext::ValueRange<int>{0, 10000};
|
||||
|
||||
SerializationContext ctx;
|
||||
auto& ser = ctx.createBPEnabledSerializer();
|
||||
|
||||
//lambdas differ only in capture clauses, it would make sense to use std::bind, but debugger crashes when it sees std::bind...
|
||||
auto serLambda = [&ser, &rangeForValue](MyStruct1& data) {
|
||||
ser.ext(data.i1, rangeForValue);
|
||||
ser.ext(data.i2, rangeForValue);
|
||||
};
|
||||
ser.ext(v, Entropy<std::vector<MyStruct1>>(values, true), serLambda);
|
||||
|
||||
auto des = ctx.createBPEnabledDeserializer();
|
||||
auto desLambda = [&des, &rangeForValue](MyStruct1& data) {
|
||||
des.ext(data.i1, rangeForValue);
|
||||
des.ext(data.i2, rangeForValue);
|
||||
};
|
||||
des.ext(res, Entropy<std::vector<MyStruct1>>(values, true), desLambda);
|
||||
|
||||
EXPECT_THAT(res, Eq(v));
|
||||
auto bitsForIndex = 8; //because aligned
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq((bitsForIndex + rangeForValue.getRequiredBits() * 2 - 1) / 8 + 1 ));
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionEntropy, WhenEntropyEncodedThenCustomFunctionNotInvoked) {
|
||||
MyStruct1 v = {4849,89};
|
||||
MyStruct1 res;
|
||||
@@ -134,8 +166,8 @@ TEST(SerializeExtensionEntropy, WhenEntropyEncodedThenCustomFunctionNotInvoked)
|
||||
MyStruct1{4849,89}, MyStruct1{0,1}};
|
||||
|
||||
SerializationContext ctx;
|
||||
ctx.createSerializer().ext(v, Entropy<std::list<MyStruct1>>{values}, [](MyStruct1& ) {});
|
||||
ctx.createDeserializer().ext(res, Entropy<std::list<MyStruct1>>{values}, []( MyStruct1& ) {});
|
||||
ctx.createBPEnabledSerializer().ext(v, Entropy<std::list<MyStruct1>>{values}, [](MyStruct1& ) {});
|
||||
ctx.createBPEnabledDeserializer().ext(res, Entropy<std::list<MyStruct1>>{values}, []( MyStruct1& ) {});
|
||||
|
||||
EXPECT_THAT(res, Eq(v));
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
|
||||
|
||||
@@ -23,17 +23,15 @@
|
||||
#include <gmock/gmock.h>
|
||||
#include "serialization_test_utils.h"
|
||||
|
||||
#include <bitsery/ext/container_map.h>
|
||||
#include <bitsery/ext/std_map.h>
|
||||
#include <bitsery/ext/entropy.h>
|
||||
#include <unordered_map>
|
||||
#include <bitsery/traits/string.h>
|
||||
|
||||
using ContainerMap = bitsery::ext::ContainerMap;
|
||||
using StdMap = bitsery::ext::StdMap;
|
||||
|
||||
using testing::Eq;
|
||||
|
||||
|
||||
|
||||
template<typename Container>
|
||||
Container createData() {
|
||||
return {};
|
||||
@@ -49,7 +47,7 @@ std::unordered_map<std::string, MyStruct1> createData<std::unordered_map<std::st
|
||||
}
|
||||
|
||||
template<>
|
||||
std::unordered_map<int32_t, float> createData<std::unordered_map<int32_t, float>>() {
|
||||
std::unordered_multimap<int32_t, float> createData<std::unordered_multimap<int32_t, float>>() {
|
||||
return {
|
||||
std::pair<int32_t , float>(545, 45.485f),
|
||||
std::pair<int32_t , float>(6748, -7891.5f),
|
||||
@@ -67,7 +65,7 @@ std::map<MyEnumClass, MyStruct1> createData<std::map<MyEnumClass, MyStruct1>>()
|
||||
}
|
||||
|
||||
template<>
|
||||
std::map<int32_t ,int64_t> createData<std::map<int32_t ,int64_t>>() {
|
||||
std::multimap<int32_t ,int64_t> createData<std::multimap<int32_t ,int64_t>>() {
|
||||
return {//these are optimized with range and entropy
|
||||
std::pair<int32_t, int64_t>(-45, -984196845ll),
|
||||
std::pair<int32_t, int64_t>(54, 1ll),
|
||||
@@ -76,7 +74,7 @@ std::map<int32_t ,int64_t> createData<std::map<int32_t ,int64_t>>() {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class SerializeExtensionContainerMap : public testing::Test {
|
||||
class SerializeExtensionStdMap : public testing::Test {
|
||||
public:
|
||||
using TContainer = T;
|
||||
|
||||
@@ -84,28 +82,28 @@ public:
|
||||
TContainer res{};
|
||||
};
|
||||
|
||||
using SerializeExtensionContainerMapTypes = ::testing::Types<
|
||||
using SerializeExtensionStdMapTypes = ::testing::Types<
|
||||
std::unordered_map<std::string, MyStruct1>,
|
||||
std::unordered_map<int32_t, float>,
|
||||
std::unordered_multimap<int32_t, float>,
|
||||
std::map<MyEnumClass , MyStruct1>,
|
||||
std::map<int32_t ,int64_t>
|
||||
std::multimap<int32_t ,int64_t>
|
||||
>;
|
||||
|
||||
TYPED_TEST_CASE(SerializeExtensionContainerMap, SerializeExtensionContainerMapTypes);
|
||||
TYPED_TEST_CASE(SerializeExtensionStdMap, SerializeExtensionStdMapTypes);
|
||||
|
||||
namespace bitsery {
|
||||
|
||||
template <typename S>
|
||||
void serialize(S& s, std::unordered_map<std::string, MyStruct1>& o) {
|
||||
s.ext(o, ContainerMap{10}, [&s](std::string& key, MyStruct1& value) {
|
||||
s.ext(o, StdMap{10}, [&s](std::string& key, MyStruct1& value) {
|
||||
s.text1b(key, 100);
|
||||
s.object(value);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
void serialize(S& s, std::unordered_map<int32_t, float>& o) {
|
||||
s.ext(o, ContainerMap{10}, [&s](int32_t& key, float& value) {
|
||||
void serialize(S& s, std::unordered_multimap<int32_t, float>& o) {
|
||||
s.ext(o, StdMap{10}, [&s](int32_t& key, float& value) {
|
||||
s.value4b(key);
|
||||
s.value4b(value);
|
||||
});
|
||||
@@ -113,26 +111,27 @@ namespace bitsery {
|
||||
|
||||
template <typename S>
|
||||
void serialize(S& s, std::map<MyEnumClass , MyStruct1>& o) {
|
||||
s.ext(o, ContainerMap{10}, [&s](MyEnumClass& key, MyStruct1& value) {
|
||||
s.ext(o, StdMap{10}, [&s](MyEnumClass& key, MyStruct1& value) {
|
||||
s.value4b(key);
|
||||
s.object(value);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
void serialize(S& s, std::map<int32_t ,int64_t>& o) {
|
||||
s.ext(o, ContainerMap{10}, [&s](int32_t& key, int64_t& value) {
|
||||
int64_t values[3]{1ll, 2ll, 3ll};
|
||||
|
||||
s.ext(key, bitsery::ext::ValueRange<int32_t>{-100,100});
|
||||
s.ext8b(value, bitsery::ext::Entropy<int64_t[3]>{values});
|
||||
void serialize(S& s, std::multimap<int32_t ,int64_t>& o) {
|
||||
s.ext(o, StdMap{10}, [&s](int32_t& key, int64_t& value) {
|
||||
s.enableBitPacking([&key, &value](typename S::BPEnabledType& sbp) {
|
||||
int64_t values[3]{1ll, 2ll, 3ll};
|
||||
sbp.ext(key, bitsery::ext::ValueRange<int32_t>{-100,100});
|
||||
sbp.ext8b(value, bitsery::ext::Entropy<int64_t[3]>{values});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
TYPED_TEST(SerializeExtensionContainerMap, SerializeAndDeserializeEquals) {
|
||||
TYPED_TEST(SerializeExtensionStdMap, SerializeAndDeserializeEquals) {
|
||||
SerializationContext ctx1;
|
||||
ctx1.createSerializer().object(this->src);
|
||||
ctx1.createDeserializer().object(this->res);
|
||||
123
tests/serialization_ext_std_optional.cpp
Normal file
123
tests/serialization_ext_std_optional.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
//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 "serialization_test_utils.h"
|
||||
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
|
||||
|
||||
#include <bitsery/ext/value_range.h>
|
||||
|
||||
|
||||
#include<optional>
|
||||
|
||||
#include <bitsery/ext/std_optional.h>
|
||||
|
||||
|
||||
using StdOptional = bitsery::ext::StdOptional;
|
||||
|
||||
using testing::Eq;
|
||||
|
||||
|
||||
template <typename T>
|
||||
void test(SerializationContext& ctx, const T& v, T& r) {
|
||||
ctx.createSerializer().ext4b(v, StdOptional{});
|
||||
ctx.createDeserializer().ext4b(r, StdOptional{});
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionStdOptional, EmptyOptional) {
|
||||
std::optional<int32_t> t1{};
|
||||
std::optional<int32_t> r1{};
|
||||
|
||||
SerializationContext ctx1;
|
||||
test(ctx1,t1, r1);
|
||||
EXPECT_THAT(ctx1.getBufferSize(), Eq(1));
|
||||
EXPECT_THAT(t1, Eq(r1));
|
||||
|
||||
|
||||
r1 = 3;
|
||||
SerializationContext ctx2;
|
||||
test(ctx2,t1, r1);
|
||||
EXPECT_THAT(ctx2.getBufferSize(), Eq(1));
|
||||
EXPECT_THAT(t1, Eq(r1));
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionStdOptional, OptionalHasValue) {
|
||||
std::optional<int32_t> t1{43};
|
||||
std::optional<int32_t> r1{52};
|
||||
|
||||
SerializationContext ctx1;
|
||||
test(ctx1,t1, r1);
|
||||
EXPECT_THAT(ctx1.getBufferSize(), Eq(1 + sizeof(int)));
|
||||
EXPECT_THAT(t1.value(), Eq(r1.value()));
|
||||
|
||||
r1 = std::optional<int>{};
|
||||
SerializationContext ctx2;
|
||||
test(ctx2,t1, r1);
|
||||
EXPECT_THAT(ctx2.getBufferSize(), Eq(1 + sizeof(int)));
|
||||
EXPECT_THAT(t1.value(), Eq(r1.value()));
|
||||
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionStdOptional, AlignAfterStateWriteRead) {
|
||||
std::optional<int32_t> t1{43};
|
||||
std::optional<int32_t> r1{52};
|
||||
|
||||
SerializationContext ctx;
|
||||
auto& ser = ctx.createBPEnabledSerializer();
|
||||
auto range = bitsery::ext::ValueRange<int>{40,60};
|
||||
ser.ext(t1, StdOptional(true), [&ser, &range](int32_t& v) {
|
||||
ser.ext(v, range);
|
||||
});
|
||||
auto des = ctx.createBPEnabledDeserializer();
|
||||
des.ext(r1, StdOptional(true), [&des, &range](int32_t& v) {
|
||||
des.ext(v, range);
|
||||
});
|
||||
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(2));//1byte for index + 1byte for value
|
||||
EXPECT_THAT(t1.value(), Eq(r1.value()));
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionStdOptional, NoAlignAfterStateWriteRead) {
|
||||
std::optional<int32_t> t1{43};
|
||||
std::optional<int32_t> r1{52};
|
||||
|
||||
SerializationContext ctx;
|
||||
auto& ser = ctx.createBPEnabledSerializer();
|
||||
auto range = bitsery::ext::ValueRange<int>{40,60};
|
||||
ser.ext(t1, StdOptional(false), [&ser, &range](int32_t& v) {
|
||||
ser.ext(v, range);
|
||||
});
|
||||
auto des = ctx.createBPEnabledDeserializer();
|
||||
des.ext(r1, StdOptional(false), [&des, &range](int32_t& v) {
|
||||
des.ext(v, range);
|
||||
});
|
||||
EXPECT_THAT(range.getRequiredBits() + 1, ::testing::Lt(8));
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
|
||||
EXPECT_THAT(t1.value(), Eq(r1.value()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
99
tests/serialization_ext_std_queue.cpp
Normal file
99
tests/serialization_ext_std_queue.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
//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 "serialization_test_utils.h"
|
||||
#include <bitsery/ext/std_queue.h>
|
||||
|
||||
using StdQueue = bitsery::ext::StdQueue;
|
||||
|
||||
using testing::Eq;
|
||||
|
||||
//inherit from queue so we could take underlying container, because priority queue doesn't have equal operator defined
|
||||
template <typename T, typename C>
|
||||
struct PriorityQueueCnt : public std::priority_queue<T, C>
|
||||
{
|
||||
static const C& getContainer(const std::priority_queue<T, C>& s )
|
||||
{
|
||||
//get address of underlying container
|
||||
return s.*(&PriorityQueueCnt::c);
|
||||
}
|
||||
static C& getContainer(std::priority_queue<T, C>& s )
|
||||
{
|
||||
//get address of underlying container
|
||||
return s.*(&PriorityQueueCnt::c);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void test(SerializationContext& ctx, const T& v, T& r) {
|
||||
ctx.createSerializer().ext4b(v, StdQueue{10});
|
||||
ctx.createDeserializer().ext4b(r, StdQueue{10});
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionStdQueue, QueueDefaultContainer) {
|
||||
std::queue<int32_t> t1{};
|
||||
t1.push(3);
|
||||
t1.push(-4854);
|
||||
std::queue<int32_t> r1{};
|
||||
|
||||
SerializationContext ctx1;
|
||||
test(ctx1,t1, r1);
|
||||
EXPECT_THAT(t1, Eq(r1));
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionStdQueue, QueueVectorContainer) {
|
||||
std::queue<int32_t, std::vector<int32_t>> t1{};
|
||||
t1.push(3);
|
||||
t1.push(-4854);
|
||||
std::queue<int32_t, std::vector<int32_t>> r1{};
|
||||
|
||||
SerializationContext ctx1;
|
||||
test(ctx1,t1, r1);
|
||||
EXPECT_THAT(t1, Eq(r1));
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionStdQueue, PriorityQueueDefaultContainer) {
|
||||
std::priority_queue<int32_t> t1{};
|
||||
t1.push(3);
|
||||
t1.push(-4854);
|
||||
std::priority_queue<int32_t> r1{};
|
||||
|
||||
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);
|
||||
EXPECT_THAT(ct1, Eq(cr1));
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionStdQueue, PriorityQueueDequeContainer) {
|
||||
std::priority_queue<int32_t, std::deque<int32_t>> t1{};
|
||||
t1.push(678);
|
||||
t1.push(-44);
|
||||
std::priority_queue<int32_t, std::deque<int32_t>> r1{};
|
||||
|
||||
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);
|
||||
EXPECT_THAT(ct1, Eq(cr1));
|
||||
}
|
||||
78
tests/serialization_ext_std_set.cpp
Normal file
78
tests/serialization_ext_std_set.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
//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 "serialization_test_utils.h"
|
||||
|
||||
#include <bitsery/ext/std_set.h>
|
||||
#include <set>
|
||||
|
||||
using StdSet = bitsery::ext::StdSet;
|
||||
|
||||
using testing::Eq;
|
||||
|
||||
template<typename T>
|
||||
class SerializeExtensionStdSet : public testing::Test {
|
||||
public:
|
||||
using TContainer = T;
|
||||
const TContainer src = {4, 8, 48, 4, 9845, 64, 8};
|
||||
TContainer res{};
|
||||
};
|
||||
|
||||
using SerializeExtensionStdSetTypes = ::testing::Types<
|
||||
std::unordered_set<int32_t>,
|
||||
std::unordered_multiset<int32_t>,
|
||||
std::set<int32_t>,
|
||||
std::multiset<int32_t>>;
|
||||
|
||||
TYPED_TEST_CASE(SerializeExtensionStdSet, SerializeExtensionStdSetTypes);
|
||||
|
||||
TYPED_TEST(SerializeExtensionStdSet, ValuesSyntaxDifferentSetTypes) {
|
||||
SerializationContext ctx1;
|
||||
ctx1.createSerializer().ext4b(this->src, StdSet{10});
|
||||
ctx1.createDeserializer().ext4b(this->res, StdSet{10});
|
||||
EXPECT_THAT(this->res, Eq(this->src));
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionStdSet, ObjectSyntax) {
|
||||
SerializationContext ctx1;
|
||||
std::set<MyStruct1> t1{MyStruct1{874 ,456}, MyStruct1{-874, -456}, MyStruct1{4894,0}};
|
||||
std::set<MyStruct1> r1{};
|
||||
ctx1.createSerializer().ext(t1, StdSet{10});
|
||||
ctx1.createDeserializer().ext(r1, StdSet{10});
|
||||
EXPECT_THAT(r1, Eq(t1));
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionStdSet, FunctionSyntax) {
|
||||
SerializationContext ctx1;
|
||||
std::unordered_multiset<int32_t> t1{54,-484,841,79};
|
||||
std::unordered_multiset<int32_t> r1{};
|
||||
auto ser = ctx1.createSerializer();
|
||||
ser.ext(t1, StdSet{10}, [&ser](int32_t& v) {
|
||||
ser.value4b(v);
|
||||
});
|
||||
auto des = ctx1.createDeserializer();
|
||||
des.ext(r1, StdSet{10}, [&des](int32_t& v) {
|
||||
des.value4b(v);
|
||||
});
|
||||
EXPECT_THAT(r1, Eq(t1));
|
||||
}
|
||||
@@ -22,61 +22,37 @@
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include "serialization_test_utils.h"
|
||||
#include <bitsery/ext/std_stack.h>
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include<optional>
|
||||
|
||||
#include <bitsery/ext/optional.h>
|
||||
|
||||
|
||||
using Optional = bitsery::ext::Optional;
|
||||
using StdStack = bitsery::ext::StdStack;
|
||||
|
||||
using testing::Eq;
|
||||
|
||||
|
||||
template <typename T>
|
||||
void test(SerializationContext& ctx, const T& v, T& r) {
|
||||
ctx.createSerializer().ext4b(v, Optional{});
|
||||
ctx.createDeserializer().ext4b(r, Optional{});
|
||||
ctx.createSerializer().ext4b(v, StdStack{10});
|
||||
ctx.createDeserializer().ext4b(r, StdStack{10});
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionOptional, EmptyOptional) {
|
||||
std::optional<int32_t> t1{};
|
||||
std::optional<int32_t> r1{};
|
||||
TEST(SerializeExtensionStdStack, DefaultContainer) {
|
||||
std::stack<int32_t> t1{};
|
||||
t1.push(3);
|
||||
t1.push(-4854);
|
||||
std::stack<int32_t> r1{};
|
||||
|
||||
SerializationContext ctx1;
|
||||
test(ctx1,t1, r1);
|
||||
EXPECT_THAT(ctx1.getBufferSize(), Eq(1));
|
||||
EXPECT_THAT(t1, Eq(r1));
|
||||
|
||||
|
||||
r1 = 3;
|
||||
SerializationContext ctx2;
|
||||
test(ctx2,t1, r1);
|
||||
EXPECT_THAT(ctx2.getBufferSize(), Eq(1));
|
||||
EXPECT_THAT(t1, Eq(r1));
|
||||
}
|
||||
|
||||
TEST(SerializeExtensionOptional, OptionalHasValue) {
|
||||
std::optional<int32_t> t1{43};
|
||||
std::optional<int32_t> r1{52};
|
||||
TEST(SerializeExtensionStdStack, VectorContainer) {
|
||||
std::stack<int32_t, std::vector<int32_t>> t1{};
|
||||
t1.push(3);
|
||||
t1.push(-4854);
|
||||
std::stack<int32_t, std::vector<int32_t>> r1{};
|
||||
|
||||
SerializationContext ctx1;
|
||||
test(ctx1,t1, r1);
|
||||
EXPECT_THAT(ctx1.getBufferSize(), Eq(1 + sizeof(int)));
|
||||
EXPECT_THAT(t1.value(), Eq(r1.value()));
|
||||
|
||||
r1 = std::optional<int>{};
|
||||
SerializationContext ctx2;
|
||||
test(ctx2,t1, r1);
|
||||
EXPECT_THAT(ctx2.getBufferSize(), Eq(1 + sizeof(int)));
|
||||
EXPECT_THAT(t1.value(), Eq(r1.value()));
|
||||
|
||||
EXPECT_THAT(t1, Eq(r1));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -55,8 +55,8 @@ TEST(SerializeExtensionValueRange, IntegerNegative) {
|
||||
int t1{-8};
|
||||
int res1;
|
||||
|
||||
ctx.createSerializer().ext(t1, r1);
|
||||
ctx.createDeserializer().ext(res1, r1);
|
||||
ctx.createBPEnabledSerializer().ext(t1, r1);
|
||||
ctx.createBPEnabledDeserializer().ext(res1, r1);
|
||||
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
|
||||
EXPECT_THAT(res1, Eq(t1));
|
||||
@@ -69,8 +69,8 @@ TEST(SerializeExtensionValueRange, IntegerPositive) {
|
||||
unsigned t1{8};
|
||||
unsigned res1;
|
||||
|
||||
ctx.createSerializer().ext(t1, r1);
|
||||
ctx.createDeserializer().ext(res1, r1);
|
||||
ctx.createBPEnabledSerializer().ext(t1, r1);
|
||||
ctx.createBPEnabledDeserializer().ext(res1, r1);
|
||||
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
|
||||
EXPECT_THAT(res1, Eq(t1));
|
||||
@@ -83,8 +83,8 @@ TEST(SerializeExtensionValueRange, EnumTypes) {
|
||||
MyEnumClass t1{MyEnumClass::E2};
|
||||
MyEnumClass res1;
|
||||
|
||||
ctx.createSerializer().ext(t1, r1);
|
||||
ctx.createDeserializer().ext(res1, r1);
|
||||
ctx.createBPEnabledSerializer().ext(t1, r1);
|
||||
ctx.createBPEnabledDeserializer().ext(res1, r1);
|
||||
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
|
||||
EXPECT_THAT(res1, Eq(t1));
|
||||
@@ -101,8 +101,8 @@ TEST(SerializeExtensionValueRange, FloatUsingPrecisionConstraint1) {
|
||||
|
||||
float res1;
|
||||
|
||||
ctx.createSerializer().ext(t1, r1);
|
||||
ctx.createDeserializer().ext(res1, r1);
|
||||
ctx.createBPEnabledSerializer().ext(t1, r1);
|
||||
ctx.createBPEnabledDeserializer().ext(res1, r1);
|
||||
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
|
||||
EXPECT_THAT(res1, ::testing::FloatNear(t1, (max - min) * precision));
|
||||
@@ -118,8 +118,8 @@ TEST(SerializeExtensionValueRange, DoubleUsingPrecisionConstraint2) {
|
||||
|
||||
double res1;
|
||||
|
||||
ctx.createSerializer().ext(t1, r1);
|
||||
ctx.createDeserializer().ext(res1, r1);
|
||||
ctx.createBPEnabledSerializer().ext(t1, r1);
|
||||
ctx.createBPEnabledDeserializer().ext(res1, r1);
|
||||
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(5));
|
||||
EXPECT_THAT(res1, ::testing::DoubleNear(t1, (max - min) * precision));
|
||||
@@ -135,8 +135,8 @@ TEST(SerializeExtensionValueRange, FloatUsingBitsSizeConstraint1) {
|
||||
|
||||
float res1;
|
||||
|
||||
ctx.createSerializer().ext(t1, r1);
|
||||
ctx.createDeserializer().ext(res1, r1);
|
||||
ctx.createBPEnabledSerializer().ext(t1, r1);
|
||||
ctx.createBPEnabledDeserializer().ext(res1, r1);
|
||||
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
|
||||
EXPECT_THAT(res1, ::testing::FloatNear(t1, (max - min) / (static_cast<bitsery::details::SAME_SIZE_UNSIGNED<float>>(1) << bits)));
|
||||
@@ -152,8 +152,8 @@ TEST(SerializeExtensionValueRange, DoubleUsingBitsSizeConstraint2) {
|
||||
|
||||
double res1;
|
||||
|
||||
ctx.createSerializer().ext(t1, r1);
|
||||
ctx.createDeserializer().ext(res1, r1);
|
||||
ctx.createBPEnabledSerializer().ext(t1, r1);
|
||||
ctx.createBPEnabledDeserializer().ext(res1, r1);
|
||||
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(7));
|
||||
EXPECT_THAT(res1, ::testing::DoubleNear(t1, (max - min) / (static_cast<bitsery::details::SAME_SIZE_UNSIGNED<double>>(1) << bits)));
|
||||
@@ -164,8 +164,8 @@ TEST(SerializeExtensionValueRange, WhenDataIsInvalidThenReturnMinimumRangeValue)
|
||||
ValueRange<int> r1{4, 10};//6 is max, but 3bits required
|
||||
int res1;
|
||||
uint8_t tmp{0xFF};//write all 1 so when reading 3 bits we get 7
|
||||
ctx.createSerializer().value1b(tmp);
|
||||
ctx.createDeserializer().ext(res1, r1);
|
||||
ctx.createBPEnabledSerializer().value1b(tmp);
|
||||
ctx.createBPEnabledDeserializer().ext(res1, r1);
|
||||
|
||||
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
|
||||
EXPECT_THAT(res1, Eq(4));
|
||||
|
||||
@@ -43,6 +43,9 @@ struct MyStruct1 {
|
||||
bool operator==(const MyStruct1 &rhs) const {
|
||||
return i1 == rhs.i1 && i2 == rhs.i2;
|
||||
}
|
||||
friend bool operator < (const MyStruct1 &lhs, const MyStruct1 &rhs) {
|
||||
return lhs.i1 < rhs.i1 || (lhs.i1 == rhs.i1 && lhs.i2 < rhs.i2);
|
||||
}
|
||||
|
||||
static constexpr size_t SIZE = sizeof(MyStruct1::i1) + sizeof(MyStruct1::i2);
|
||||
};
|
||||
@@ -88,6 +91,7 @@ public:
|
||||
bitsery::DefaultConfig::BufferType buf{};
|
||||
std::unique_ptr<bitsery::BufferWriter> bw;
|
||||
std::unique_ptr<bitsery::BufferReader> br;
|
||||
std::unique_ptr<bitsery::BasicSerializer<bitsery::DefaultConfig, true>> sbp;
|
||||
|
||||
bitsery::Serializer createSerializer() {
|
||||
//make_unique is not in c++11
|
||||
@@ -95,6 +99,14 @@ public:
|
||||
return bitsery::Serializer{*bw};
|
||||
};
|
||||
|
||||
bitsery::BasicSerializer<bitsery::DefaultConfig, true>& createBPEnabledSerializer() {
|
||||
//make_unique is not in c++11
|
||||
bw = std::unique_ptr<bitsery::BufferWriter>(new bitsery::BufferWriter(buf));
|
||||
sbp = std::unique_ptr<bitsery::BasicSerializer<bitsery::DefaultConfig, true>>(
|
||||
new bitsery::BasicSerializer<bitsery::DefaultConfig, true>{*bw});
|
||||
return *sbp;
|
||||
};
|
||||
|
||||
size_t getBufferSize() const {
|
||||
auto range = bw->getWrittenRange();
|
||||
return std::distance(range.begin(), range.end());
|
||||
@@ -116,6 +128,13 @@ public:
|
||||
br = std::unique_ptr<bitsery::BufferReader>(new bitsery::BufferReader(bw->getWrittenRange()));
|
||||
return bitsery::Deserializer{*br};
|
||||
};
|
||||
|
||||
bitsery::BasicDeserializer<bitsery::DefaultConfig, true> createBPEnabledDeserializer() {
|
||||
sbp.reset(nullptr);
|
||||
//make_unique is not in c++11
|
||||
br = std::unique_ptr<bitsery::BufferReader>(new bitsery::BufferReader(bw->getWrittenRange()));
|
||||
return bitsery::BasicDeserializer<bitsery::DefaultConfig, true>{*br};
|
||||
};
|
||||
};
|
||||
|
||||
#endif //BITSERY_SERIALIZER_TEST_UTILS_H
|
||||
|
||||
Reference in New Issue
Block a user