1
0
mirror of https://github.com/Rogiel/PacketBuffer synced 2025-12-06 00:13:04 +00:00

Initial commit

This commit is contained in:
2017-05-30 14:44:14 -03:00
commit dff846799a
28 changed files with 3203 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
cmake-build-*
/.idea

32
.gitmodules vendored Normal file
View File

@@ -0,0 +1,32 @@
#
# Copyright (c) 2017, Rogiel Sulzbach
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of Rogiel Sulzbach nor the names of contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
[submodule "Catch"]
path = Catch
url = https://github.com/philsquared/Catch.git

50
CMakeLists.txt Normal file
View File

@@ -0,0 +1,50 @@
#
# Copyright (c) 2017, Rogiel Sulzbach
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of Rogiel Sulzbach nor the names of contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
cmake_minimum_required(VERSION 3.8)
project(PacketBuffer)
set(CMAKE_CXX_STANDARD 14)
add_library(PacketBuffer INTERFACE)
target_include_directories(PacketBuffer INTERFACE include)
option(PACKET_BUFFER_EXAMPLES "Enable to build examples" OFF)
if(PACKET_BUFFER_EXAMPLES)
add_executable(PacketBuffer.Example example/main.cpp)
target_link_libraries(PacketBuffer.Example PacketBuffer)
endif()
option(PACKET_BUFFER_TESTS "Enable to build tests" OFF)
if(PACKET_BUFFER_TESTS)
file(GLOB_RECURSE TESTS_SRC tests/*.cpp)
add_executable(PacketBuffer.Tests ${TESTS_SRC})
target_link_libraries(PacketBuffer.Tests PacketBuffer)
target_include_directories(PacketBuffer.Tests PRIVATE Catch/include)
endif()

1
Catch Submodule

Submodule Catch added at 3e328f55fc

30
LICENSE Normal file
View File

@@ -0,0 +1,30 @@
The BSD 3-Clause ("BSD New" or "BSD Simplified") License
========================================================
Copyright (c) 2017, Rogiel Sulzbach
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the Rogiel Sulzbach nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

63
README.md Normal file
View File

@@ -0,0 +1,63 @@
PacketBuffer - Lightning fast packet parsing library
========================================================
PacketBuffer is a C++14 header-only library designed specifically to be really fast at processing binary network packets. It supports many of the C++ standard containers, including:
* [`std::array`](include/PacketBuffer/Serializer/Std/Array.h)
* [`T[S]` (statically sized arrays)](include/PacketBuffer/Serializer/Std/Array.h)
* [`std::chrono::duration`](include/PacketBuffer/Serializer/Std/Chrono.h)
* [`std::chrono::time_point`](include/PacketBuffer/Serializer/Std/Chrono.h)
* [`std::vector`](include/PacketBuffer/Serializer/Std/Vector.h)
* [`std::map`](include/PacketBuffer/Serializer/Std/Map.h)
* [`std::unordered_map`](include/PacketBuffer/Serializer/Std/Map.h)
* [`std::list`](include/PacketBuffer/Serializer/Std/List.h)
* [`std::set`](include/PacketBuffer/Serializer/Std/Set.h)
* [`std::unoredered_set`](include/PacketBuffer/Serializer/Std/Set.h)
* [`std::string`](include/PacketBuffer/Serializer/Std/String.h)
* [`std::tuple`](include/PacketBuffer/Serializer/Std/Tuple.h)
* [`std::pair`](include/PacketBuffer/Serializer/Std/Pair.h)
* [`std::experimental::optional`](include/PacketBuffer/Serializer/Std/Experimental/Optional.h)
It also supports endian swapping the following types:
`uint8_t`, `int8_t`,
`uint16_t`, `int16_t`,
`uint32_t`, `int32_t`,
`uint64_t`, `int64_t`.
## Getting Started
````````
using namespace PacketBuffer;
std::stringstream ss;
Packer<std::stringstream> packer(ss);
packer.pack(uint8_t(100));
````````
That's it!
But wait, you probably want something more than just packing a `uint8_t`, right? What about some custom structs?
### Packing structs
``` c++
using namespace PacketBuffer;
struct MyPacket {
uint8_t id;
std::string name;
uint8_t age;
template<typename Packer>
void pack(Packer& packer) const { packer(id, name, age); }
template<typename Unpacker>
void unpack(Unpacker& unpacker) { unpacker(id, name, age); }
};
std::stringstream ss;
Packer<std::stringstream> packer(ss);
MyPacket packet;
packer.pack(packet);
```
Seriously, that is it! You can now serialize and deserialize your structure on any machine with whatever byte order it has!

125
example/main.cpp Normal file
View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <PacketBuffer/PacketBuffer.h>
#include <PacketBuffer/Serializer/Std/Experimental.h>
#include <iostream>
#include <sstream>
using namespace PacketBuffer;
struct HELLO_MESSAGE {
uint8_t id;
uint8_t kind;
unsigned char payload[64];
std::array<uint8_t, 16> test;
std::vector<int> vec;
std::tuple<uint8_t, uint32_t, uint64_t> tuple;
std::pair<uint8_t, uint32_t> pair;
std::map<uint8_t, uint64_t> mapping;
std::unordered_map<uint8_t, uint64_t> umapping;
std::list<uint8_t> list;
std::list<uint8_t> flist;
std::set<uint8_t> set;
std::unordered_set<uint8_t> uset;
std::chrono::seconds durationSec;
std::chrono::hours durationHour;
std::chrono::system_clock::time_point time;
std::experimental::optional<std::string> oName;
std::string name;
template<typename Packer>
void pack(Packer& packer) const {
packer(
id, kind, payload, test, vec, tuple, pair, mapping, umapping, list, flist, set, uset, name, durationSec,
durationHour, time, oName
);
}
template<typename Unpacker>
void unpack(Unpacker& unpacker) {
unpacker(
id, kind, payload, test, vec, tuple, pair, mapping, umapping, list, flist, set, uset, name, durationSec,
durationHour, time, oName
);
}
};
int main(int argc, const char** argv) {
std::stringstream ss;
Packer<std::ostream> packer(ss);
{
HELLO_MESSAGE hello;
hello.id = 20;
hello.kind = 2;
memset(hello.payload, 'A', sizeof(hello.payload));
hello.vec = {1, 2, 3};
hello.mapping[1] = 200;
hello.mapping[2] = 300;
hello.name = "It Works!";
// hello.wname = L"Teste";
hello.oName = std::string(";)");
packer.pack(hello);
}
std::cout << "Serialized message has " << ss.str().size() << std::endl;
{
Unpacker<std::istream> unpacker(ss);
HELLO_MESSAGE unpacked;
unpacker.unpack(unpacked);
std::cout << "id: " << (int) unpacked.id << std::endl;
std::cout << "kind: " << (int) unpacked.kind << std::endl;
std::cout << "payload: " << std::string((char*) unpacked.payload, 64) << std::endl;
std::cout << "vec: " << unpacked.vec.size() << std::endl;
std::cout << "name: " << unpacked.name << std::endl;
std::cout << "mapping: " << std::endl;
for(auto& entry : unpacked.mapping) {
std::cout << " " << (int) entry.first << " = " << entry.second << std::endl;
}
}
}

View File

@@ -0,0 +1,185 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_OBJECTSERIALIZER_H
#define PACKETBUFFER_OBJECTSERIALIZER_H
namespace PacketBuffer {
template<typename Packer, typename T>
struct HasIntrusivePackMethod {
template<typename U, void (U::*)(Packer&) const>
struct SFINAE;
template<typename U>
static char test(SFINAE<U, &U::pack>*);
template<typename U>
static int test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(char);
};
template<typename Unpacker, typename T>
struct HasIntrusiveUnpackMethod {
template<typename U, void (U::*)(Unpacker&)>
struct SFINAE;
template<typename U>
static char test(SFINAE<U, &U::unpack>*);
template<typename U>
static int test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(char);
};
/**
* The ObjectSerializer class template is responsible for implementing the serialization logic
* for non-primitive types.
*
* A user can provide a specialization for any type it wishes to add custom serialization code.
*
* By default, the ObjectSerializer will call the intrusive pack() and unpack() methods on the
* user given object. If these methods are not available, compilation will fail with a error
* message describing which of the required methods are missing.
*
* A custom ObjectSerialization specialization can be provided as follows:
*
* @code
* struct UserDefinedType {
* uint64_t id;
* std::string name;
* }
*
* namespace PacketBuffer {
* template<>
* class ObjectSerializer<UserDefinedType> {
* public:
* template<typename Packer>
* static void pack(Packer& packer, const T& object) {
* packer(object.id, object.name);
* }
*
* template<typename Unpacker>
* static void unpack(Unpacker& unpacker, T& object) {
* unpacker(object.id, object.name);
* }
* }
* }
* @endcode
*
* If more convenient, a user can also provide a set of **intrusive** methods that allow
* packing and unpacking objects:
*
* @code
* struct UserDefinedType {
* uint64_t id;
* std::string name;
*
* template<typename Packer>
* void pack(Packer& packer) const {
* packer(id, name);
* }
*
* template<typename Unpacker>
* void unpack(Unpacker& unpacker) {
* unpacker(id, name);
* }
* }
* @endcode
*
* @tparam T the type of the object to be packed and/or unpacked
*/
template<typename T, typename = void>
class ObjectSerializer {
public:
/**
* Packs a object to its packed representation.
*
* This is a default implementation whose only job is to forward to the intrusive implementation,
* and if this is not available, fail at compile time.
*
* @tparam Packer the packer type
* @param packer the packer to write data from
* @param object the object to be packed
*/
template<typename Packer>
static inline void pack(Packer& packer, const T& object) {
/*
* If you are getting an error here, this means that one of your objects being serialized does not implement
* a pack() method. A pack method can be implemented as follows:
*
* template<typename Packer>
* void pack(Packer& packer) const {
* packer(
* a, b, c
* );
* }
*/
static_assert(HasIntrusivePackMethod<Packer, T>::value,
"The object of type T does not have a ObjectSerializer<T> "
"specialization and does not implement a intrusive pack(Packer&) method.");
object.pack(packer);
}
/**
* Unpacks a object from its packet representation.
*
* This is a default implementation whose only job is to forward to the intrusive implementation,
* and if this is not available, fail at compile time.
*
* @tparam Unpacker the unpacker type
* @param unpacker the unpacker to read data from
* @param object the object to unpack to
*/
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, T& object) {
/*
* If you are getting an error here, this means that one of your objects being serialized does not implement
* a unpack() method. A unpack method can be implemented as follows:
*
* template<typename Unpacker>
* void unpack(Unpacker& unpacker) {
* unpacker(
* a, b, c
* );
* }
*/
static_assert(HasIntrusiveUnpackMethod<Unpacker, T>::value,
"The object of type T does not have a ObjectSerializer<T> "
"specialization and does not implement a intrusive unpack(Unpacker&) method.");
object.unpack(unpacker);
}
};
}
#endif //PACKETBUFFER_OBJECTSERIALIZER_H

View File

@@ -0,0 +1,321 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_PACKER_H
#define PACKETBUFFER_PACKER_H
#include <boost/endian/conversion.hpp>
#include "ObjectSerializer.h"
namespace PacketBuffer {
/**
* The Packer template class is responsible for converting C++ primitive types like integers and raw buffers
* into a platform independent raw buffer.
*
* By default, all integers are encoded as little endian, this, however can be changed by setting "Endianess"
* template parameter to something else.
*
* The <tt>Buffer</tt> class must implement a <tt>write</tt> with the following signature:
* @code
* void write(const char* data, size_t length);
* @endcode
*
* @tparam Buffer the buffer type to write data to
* @tparam Endianess the endianess used to encode integer types
*/
template<typename Buffer, boost::endian::order Endianess = boost::endian::order::little>
class Packer {
private:
/**
* A reference to the buffer in which packed data is written to
*/
Buffer& buffer;
public:
/**
* Creates a new Packer instance with the given buffer reference. Packed data will be written
* into the given buffer object.
*
* @param buffer the buffer object to write data to
*/
explicit Packer(Buffer& buffer) : buffer(buffer) {};
/**
* Deleted copy constructor.
*/
Packer(const Packer& other) = delete;
/**
* Deleted copy assignment operator.
*/
Packer& operator=(const Packer& other) = delete;
/**
* Deleted move constructor.
*/
Packer(Packer&& other) = delete;
/**
* Deleted move assignment operator.
*/
Packer& operator=(Packer&& other) = delete;
/**
* Default destructor.
*/
~Packer() = default;
public: // Helper methods
/**
* A helper <tt>&</tt> operator overload. Calls the pack() method for the given type.
*
* @tparam T the data type to pack
* @param v the value to be packed
*
* @return this
*/
template<typename T>
inline Packer& operator&(const T& v) {
return pack(v);
}
/**
* A helper <tt><<</tt> operator overload that behaves similarly to ostreams operator. Calls the
* pack() method for given type.
*
* @tparam T the data type to pack
* @param v the value to be packed
*
* @return this
*/
template<typename T>
inline Packer& operator<<(const T& v) {
return pack(v);
}
/**
* A helper call operator overload. Calls pack() method for the given types.
*
* @tparam Ts the types to be packed
* @param vs the values to be packed. The values will be packed in the given order.
*
* @return this
*/
template<typename... Ts>
inline Packer& operator()(const Ts& ... vs) {
return pack(vs...);
}
public: // Object serialization
/**
* Packs a sequence of objects of types <tt>T</tt> and <tt>Ts...</tt>.
*
* The objects will be packed in the given order.
*
* @tparam T the type of the first object to be packed
* @tparam Ts the type of the remaining objects to be packed
* @param v the value of the first object to be packed
* @param vs the value of the remaining objects to be packed
*
* @return this
*/
template<typename T, typename... Ts>
inline Packer& pack(const T& v, const Ts& ... vs) {
pack(v);
pack(vs...);
return *this;
}
/**
* Packs a single object of type <tt>T</tt>.
*
* @tparam T the type of the object to be packed
* @param object the value of the object to be packed
*
* @return this
*/
template<typename T>
inline Packer& pack(const T& object) {
ObjectSerializer<T>::pack(*this, object);
return *this;
}
public: // Integer types
/**
* Packs a uint8_t integer value.
*
* @param i the integer value to pack
*
* @return this
*/
inline Packer& pack(uint8_t i) {
static_assert(sizeof(i) == 1, "uint8_t size must be 1 byte");
boost::endian::conditional_reverse_inplace<boost::endian::order::native, Endianess>(i);
return pack(reinterpret_cast<const char*>(&i), sizeof(i));
}
/**
* Packs a int8_t integer value.
*
* @param i the integer value to pack
*
* @return this
*/
inline Packer& pack(int8_t i) {
static_assert(sizeof(i) == 1, "int8_t size must be 1 byte");
boost::endian::conditional_reverse_inplace<boost::endian::order::native, Endianess>(i);
return pack(reinterpret_cast<const char*>(&i), sizeof(i));
}
/**
* Packs a uint16_t integer value.
*
* @param i the integer value to pack
*
* @return this
*/
inline Packer& pack(uint16_t i) {
static_assert(sizeof(i) == 2, "uint16_t size must be 2 byte2");
boost::endian::conditional_reverse_inplace<boost::endian::order::native, Endianess>(i);
return pack(reinterpret_cast<const char*>(&i), sizeof(i));
}
/**
* Packs a int16_t integer value.
*
* @param i the integer value to pack
*
* @return this
*/
inline Packer& pack(int16_t i) {
static_assert(sizeof(i) == 2, "int16_t size must be 2 byte2");
boost::endian::conditional_reverse_inplace<boost::endian::order::native, Endianess>(i);
return pack(reinterpret_cast<const char*>(&i), sizeof(i));
}
/**
* Packs a uint32_t integer value.
*
* @param i the integer value to pack
*
* @return this
*/
inline Packer& pack(uint32_t i) {
static_assert(sizeof(i) == 4, "uint32_t size must be 4 bytes");
boost::endian::conditional_reverse_inplace<boost::endian::order::native, Endianess>(i);
return pack(reinterpret_cast<const char*>(&i), sizeof(i));
}
/**
* Packs a int32_t integer value.
*
* @param i the integer value to pack
*
* @return this
*/
inline Packer& pack(int32_t i) {
static_assert(sizeof(i) == 4, "int32_t size must be 4 bytes");
boost::endian::conditional_reverse_inplace<boost::endian::order::native, Endianess>(i);
return pack(reinterpret_cast<const char*>(&i), sizeof(i));
}
/**
* Packs a uint64_t integer value.
*
* @param i the integer value to pack
*
* @return this
*/
inline Packer& pack(uint64_t i) {
static_assert(sizeof(i) == 8, "uint64_t size must be 8 bytes");
boost::endian::conditional_reverse_inplace<boost::endian::order::native, Endianess>(i);
return pack(reinterpret_cast<const char*>(&i), sizeof(i));
}
/**
* Packs a int64_t integer value.
*
* @param i the integer value to pack
*
* @return this
*/
inline Packer& pack(int64_t i) {
static_assert(sizeof(i) == 8, "int64_t size must be 8 bytes");
boost::endian::conditional_reverse_inplace<boost::endian::order::native, Endianess>(i);
return pack(reinterpret_cast<const char*>(&i), sizeof(i));
}
/**
* Packs a boolean value.
*
* @param b the boolean value to pack
*
* @return this
*/
inline Packer& pack(bool b) {
static_assert(sizeof(b) == 1, "bool size must be 1 byte");
boost::endian::conditional_reverse_inplace<boost::endian::order::native, Endianess>(b);
return pack(reinterpret_cast<const char*>(&b), sizeof(b));
}
public: // write operation
/**
* Packs a char-pointer gives by <tt>ptr</tt> with length given by <tt>size</tt>.
*
* @param ptr the char pointer to be packed
* @param size the char pointer length
*
* @return this
*/
inline Packer& pack(const char* ptr, size_t size) {
buffer.write(ptr, size);
return *this;
}
/**
* Packs a char-pointer givem by <tt>ptr</tt> with length given by <tt>size</tt>.
*
* @param ptr the char pointer to be packed
* @param size the char pointer length
*
* @return this
*/
inline Packer& pack(const unsigned char* ptr, size_t size) {
buffer.write(ptr, size);
return *this;
}
};
}
#endif //PACKETBUFFER_PACKER_H

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "Packer.h"
#include "Unpacker.h"
#include "ObjectSerializer.h"
#include "Serializer/Std.h"

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_SERIALIZER_STD_H
#define PACKETBUFFER_SERIALIZER_STD_H
#include "Std/Array.h"
#include "Std/Chrono.h"
#include "Std/List.h"
#include "Std/Map.h"
#include "Std/Pair.h"
#include "Std/Set.h"
#include "Std/String.h"
#include "Std/Tuple.h"
#include "Std/Vector.h"
#endif //PACKETBUFFER_SERIALIZER_STD_H

View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_SERIALIZER_STD_ARRAY_H
#define PACKETBUFFER_SERIALIZER_STD_ARRAY_H
#include "PacketBuffer/ObjectSerializer.h"
#include <array>
namespace PacketBuffer {
/**
* A ObjectSerializer for a statically sized array of type <tt>T</tt>
* with size of <tt>S</tt>.
*
* @note This serializer does not include the size of the original array
* when serialized. Further changing the size of the array will cause a
* change in the binary format of the packet.
*
* @tparam T the array type
* @tparam S the array fixed size
*/
template<typename T, size_t S>
class ObjectSerializer<T[S], typename std::enable_if<sizeof(T) != 1>::type> {
public:
template<typename Packer>
static inline void pack(Packer& packer, T const array[S]) {
for(int i = 0; i < S; i++) {
packer(array[i]);
}
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, T array[S]) {
for(int i = 0; i < S; i++) {
unpacker(array[i]);
}
}
};
/**
* A ObjectSerializer for a statically sized array of type <tt>T</tt>
* with size of <tt>S</tt>.
*
* This implementation is specialized for object whose size is 1 byte.
*
* @note This serializer does not include the size of the original array
* when serialized. Further changing the size of the array will cause a
* change in the binary format of the packet.
*
* @tparam T the array type
* @tparam S the array fixed size
*/
template<typename T, size_t S>
class ObjectSerializer<T[S], typename std::enable_if<sizeof(T) == 1>::type> {
public:
template<typename Packer>
static inline void pack(Packer& packer, T const array[S]) {
packer.pack(reinterpret_cast<const char*>(array), S);
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, T array[S]) {
unpacker.unpack(reinterpret_cast<char*>(array), S);
}
};
/**
* A ObjectSerializer for a statically sized array of type <tt>T</tt>
* with size of <tt>S</tt>.
*
* @note This serializer does not include the size of the original array
* when serialized. Further changing the size of the array will cause a
* change in the binary format of the packet.
*
* @tparam T the array type
* @tparam S the array fixed size
*/
template<typename T, size_t S>
class ObjectSerializer<std::array<T, S>> {
public:
template<typename Packer>
static inline void pack(Packer& packer, const std::array<T, S>& array) {
for(int i = 0; i < S; i++) {
packer(array[i]);
}
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, std::array<T, S>& array) {
for(int i = 0; i < S; i++) {
unpacker(array[i]);
}
}
};
}
#endif //PACKETBUFFER_SERIALIZER_STD_ARRAY_H

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_SERIALIZER_STD_CHRONO_H
#define PACKETBUFFER_SERIALIZER_STD_CHRONO_H
#include "PacketBuffer/ObjectSerializer.h"
#include <chrono>
namespace PacketBuffer {
/**
* A ObjectSerializer for std::chrono::duration values with representation
* of type <tt>R</tt> and period type of <tt>P</tt>.
*
* @tparam R the duration representation type
* @tparam P the duration period type
*/
template<typename R, typename P>
class ObjectSerializer<std::chrono::duration<R, P>> {
public:
template<typename Packer>
static inline void pack(Packer& packer, const std::chrono::duration<R, P>& duration) {
packer((int64_t) duration.count());
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, std::chrono::duration<R, P>& duration) {
int64_t r;
unpacker(r);
duration = std::chrono::duration<R, P>(r);
}
};
/**
* A ObjectSerializer for std::chrono::time_point values with clock
* of type <tt>Clock</tt> and duration type of <tt>Duration</tt>.
*
* @tparam Clock the time_point clock type
* @tparam Duration the time_point duration type
*/
template<typename Clock, typename Duration>
class ObjectSerializer<std::chrono::time_point<Clock, Duration>> {
public:
template<typename Packer>
static inline void pack(Packer& packer, const std::chrono::time_point<Clock, Duration>& point) {
packer(point.time_since_epoch());
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, std::chrono::time_point<Clock, Duration>& point) {
Duration d;
unpacker(d);
point = std::chrono::time_point<Clock, Duration>(d);
}
};
}
#endif //PACKETBUFFER_SERIALIZER_STD_CHRONO_H

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_SERIALIZER_STD_EXPERIMENTAL_H
#define PACKETBUFFER_SERIALIZER_STD_EXPERIMENTAL_H
#include "Experimental/Optional.h"
#endif //PACKETBUFFER_SERIALIZER_STD_EXPERIMENTAL_H

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_SERIALIZER_STD_EXPERIMENTAL_OPTIONAL_H
#define PACKETBUFFER_SERIALIZER_STD_EXPERIMENTAL_OPTIONAL_H
#include "PacketBuffer/ObjectSerializer.h"
#if __has_include(<experimental/optional>)
#include <experimental/optional>
namespace PacketBuffer {
/**
* A ObjectSerializer for std::optional of type <tt>T</tt>.
*
* @tparam T the optional type
*/
template<typename T>
class ObjectSerializer<std::experimental::optional<T>> {
public:
template<typename Packer>
static inline void pack(Packer& packer, const std::experimental::optional<T>& optional) {
if(optional) {
packer(true);
packer(*optional);
} else {
packer(false);
}
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, std::experimental::optional<T>& optional) {
bool hasValue;
unpacker(hasValue);
if(hasValue) {
unpacker(*optional);
}
}
};
}
#endif
#endif //PACKETBUFFER_SERIALIZER_STD_EXPERIMENTAL_OPTIONAL_H

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_SERIALIZER_STD_LIST_H
#define PACKETBUFFER_SERIALIZER_STD_LIST_H
#include "PacketBuffer/ObjectSerializer.h"
#include <list>
#include <forward_list>
namespace PacketBuffer {
/**
* A ObjectSerializer for std::list with elements of type <tt>R</tt>
* using an allocator of type <tt>Allocator</tt>.
*
* @tparam T the list element type
* @tparam Allocator the list allocator type
*/
template<typename T, typename Allocator>
class ObjectSerializer<std::list<T, Allocator>> {
public:
template<typename Packer>
static inline void pack(Packer& packer, const std::list<T, Allocator>& list) {
auto items = static_cast<uint64_t>(list.size());
packer(items);
for(auto& entry : list) {
packer(entry);
}
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, std::list<T, Allocator>& list) {
uint64_t items;
unpacker(items);
for(int i = 0; i < items; i++) {
T v;
unpacker(v);
list.push_back(v);
}
}
};
}
#endif //PACKETBUFFER_SERIALIZER_STD_LIST_H

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_SERIALIZER_STD_MAP_H
#define PACKETBUFFER_SERIALIZER_STD_MAP_H
#include "PacketBuffer/ObjectSerializer.h"
#include "PacketBuffer/Serializer/Std/Pair.h"
#include <map>
#include <unordered_map>
namespace PacketBuffer {
/**
* A ObjectSerializer for std::map with keys of type <tt>K</tt>,
* values of type <tt>T</tt>, comparison functor of type
* <tt>Compare</tt> and using an allocator of type <tt>Allocator</tt>.
*
* @tparam K the map element key
* @tparam V the map element value
* @tparam Compare the map comparison functor
* @tparam Allocator the map allocator type
*/
template<typename K, typename V, typename Compare, typename Allocator>
class ObjectSerializer<std::map<K, V, Compare, Allocator>> {
public:
template<typename Packer>
static inline void pack(Packer& packer, const std::map<K, V, Compare, Allocator>& map) {
auto items = static_cast<uint64_t>(map.size());
packer(items);
for(const std::pair<K, V>& entry : map) {
packer(entry);
}
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, std::map<K, V, Compare, Allocator>& map) {
uint64_t items;
unpacker(items);
for(int i = 0; i < items; i++) {
std::pair<K, V> entry;
unpacker(entry);
map.insert(std::move(entry));
}
}
};
/**
* A ObjectSerializer for std::unordered_map with keys of type <tt>K</tt>,
* values of type <tt>T</tt>, comparison functor of type <tt>Compare</tt>
* and using an allocator of type <tt>Allocator</tt>.
*
* @tparam K the map element key
* @tparam V the map element value
* @tparam Compare the map comparison functor
* @tparam Allocator the map allocator type
*/
template<typename K, typename V, class Hash, class Predicate, typename Allocator>
class ObjectSerializer<std::unordered_map<K, V, Hash, Predicate, Allocator>> {
public:
template<typename Packer>
static inline void pack(Packer& packer, const std::unordered_map<K, V, Hash, Predicate, Allocator>& map) {
auto items = static_cast<uint64_t>(map.size());
packer(items);
for(const std::pair<K, V>& entry : map) {
packer(entry);
}
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, std::unordered_map<K, V, Hash, Predicate, Allocator>& map) {
uint64_t items;
unpacker(items);
for(int i = 0; i < items; i++) {
std::pair<K, V> entry;
unpacker(entry);
map.insert(std::move(entry));
}
}
};
}
#endif //PACKETBUFFER_SERIALIZER_STD_MAP_H

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_SERIALIZER_STD_PAIR_H
#define PACKETBUFFER_SERIALIZER_STD_PAIR_H
#include "PacketBuffer/ObjectSerializer.h"
#include <utility>
namespace PacketBuffer {
/**
* A ObjectSerializer for std::pair of types <tt>T1</tt> and <tt>T2</tt>.
*
* @tparam T1 the pair first type
* @tparam T2 the pair second type
*/
template<typename T1, typename T2>
class ObjectSerializer<std::pair<T1, T2>> {
public:
template<typename Packer>
static inline void pack(Packer& packer, const std::pair<T1, T2>& pair) {
packer(pair.first, pair.second);
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, std::pair<T1, T2>& pair) {
unpacker(pair.first, pair.second);
}
};
}
#endif //PACKETBUFFER_SERIALIZER_STD_PAIR_H

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_SERIALIZER_STD_SET_H
#define PACKETBUFFER_SERIALIZER_STD_SET_H
#include "PacketBuffer/ObjectSerializer.h"
#include <set>
#include <unordered_set>
namespace PacketBuffer {
/**
* A ObjectSerializer for std::set with elements of type <tt>T</tt>,
* comparison functor of type <tt>Compare</tt> and using an allocator
* of type <tt>Allocator</tt>.
*
* @tparam T the set element key
* @tparam Compare the set comparison functor
* @tparam Allocator the set allocator type
*/
template<typename T, typename Compare, typename Allocator>
class ObjectSerializer<std::set<T, Compare, Allocator>> {
public:
template<typename Packer>
static inline void pack(Packer& packer, const std::set<T, Compare, Allocator>& set) {
auto items = static_cast<uint64_t>(set.size());
packer(items);
for(auto& entry : set) {
packer(entry);
}
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, std::set<T, Compare, Allocator>& set) {
uint64_t items;
unpacker(items);
for(int i = 0; i < items; i++) {
T v;
unpacker(v);
set.insert(v);
}
}
};
/**
* A ObjectSerializer for std::unordered_set with elements of type
* <tt>T</tt>, hash functor of type <tt>Hash</tt>, predicate of type
* <tt>Predicate</tt> and using an allocator of type <tt>Allocator</tt>.
*
* @tparam T the set element key
* @tparam Hash the set hash functor
* @tparam Predicate the set predicate functor
* @tparam Allocator the set allocator type
*/
template<typename T, typename Hash, typename Predicate, typename Allocator>
class ObjectSerializer<std::unordered_set<T, Hash, Predicate, Allocator>> {
public:
template<typename Packer>
static inline void pack(Packer& packer, const std::unordered_set<T, Hash, Predicate, Allocator>& set) {
auto items = static_cast<uint64_t>(set.size());
packer(items);
for(auto& entry : set) {
packer(entry);
}
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, std::unordered_set<T, Hash, Predicate, Allocator>& set) {
uint64_t items;
unpacker(items);
set.reserve(items);
for(int i = 0; i < items; i++) {
T v;
unpacker(v);
set.insert(v);
}
}
};
}
#endif //PACKETBUFFER_SERIALIZER_STD_SET_H

View File

@@ -0,0 +1,97 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_SERIALIZER_STD_STRING_H
#define PACKETBUFFER_SERIALIZER_STD_STRING_H
#include "PacketBuffer/ObjectSerializer.h"
#include <string>
namespace PacketBuffer {
/**
* A ObjectSerializer for std::basic_string with character of type
* <tt>T</tt>, traits of type <tt>Traits</tt> and using an allocator
* of type <tt>Allocator</tt>.
*
* @tparam T the string character type
* @tparam Traits the string traits
* @tparam Allocator the string character allocator
*/
template<typename T, typename Traits, typename Allocator>
class ObjectSerializer<std::basic_string<T, Traits, Allocator>> {
public:
template<typename Packer>
static inline void pack(Packer& packer, const std::basic_string<T, Traits, Allocator>& string) {
auto length = static_cast<uint64_t>(string.size());
packer(length);
for(int i = 0; i < length; i++) {
packer(string[i]);
}
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, std::basic_string<T, Traits, Allocator>& string) {
uint64_t length;
unpacker(length);
string.resize(length);
for(int i = 0; i < length; i++) {
unpacker(string[i]);
}
}
};
/**
* A ObjectSerializer for std::string.
*/
template<>
class ObjectSerializer<std::string> {
public:
template<typename Packer>
static inline void pack(Packer& packer, const std::string& string) {
auto length = static_cast<uint64_t>(string.size());
packer(length);
packer.pack(string.data(), string.size());
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, std::string& string) {
uint64_t length;
unpacker(length);
string.resize(length);
unpacker.unpack(&string[0], string.size());
}
};
}
#endif //PACKETBUFFER_SERIALIZER_STD_STRING_H

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_SERIALIZER_STD_TUPLE_H
#define PACKETBUFFER_SERIALIZER_STD_TUPLE_H
#include "PacketBuffer/ObjectSerializer.h"
#include <tuple>
namespace PacketBuffer {
/**
* A ObjectSerializer for std::tuple with elements of type <tt>Ts</tt>.
*
* @tparam Ts the tuple element types
*/
template<typename... Ts>
class ObjectSerializer<std::tuple<Ts...>> {
public:
template<typename Packer>
static inline void pack(Packer& packer, const std::tuple<Ts...>& tuple) {
packImpl<Packer, 0, Ts...>(packer, tuple);
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, std::tuple<Ts...>& tuple) {
unpackImpl<Unpacker, 0, Ts...>(unpacker, tuple);
}
private:
template<typename Packer, size_t I, typename T, typename... OTs>
static inline void packImpl(Packer& packer, const std::tuple<Ts...>& tuple) {
packer(std::get<I>(tuple));
packImpl<Packer, I + 1, OTs...>(packer, tuple);
}
template<typename Packer, size_t I>
static inline void packImpl(Packer& packer, const std::tuple<Ts...>& tuple) {}
template<typename Unpacker, size_t I, typename T, typename... OTs>
static inline void unpackImpl(Unpacker& unpacker, std::tuple<Ts...>& tuple) {
unpacker(std::get<I>(tuple));
unpackImpl<Unpacker, I + 1, OTs...>(unpacker, tuple);
}
template<typename Unpacker, size_t I>
static inline void unpackImpl(Unpacker& unpacker, std::tuple<Ts...>& tuple) {}
};
}
#endif //PACKETBUFFER_SERIALIZER_STD_TUPLE_H

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_SERIALIZER_STD_VECTOR_H
#define PACKETBUFFER_SERIALIZER_STD_VECTOR_H
#include "PacketBuffer/ObjectSerializer.h"
#include <vector>
namespace PacketBuffer {
/**
* A ObjectSerializer for std::vector with elements of type <tt>R</tt>
* using an allocator of type <tt>Allocator</tt>.
*
* @tparam T the vector element type
* @tparam Allocator the vector allocator type
*/
template<typename T, typename Allocator>
class ObjectSerializer<std::vector<T, Allocator>> {
public:
template<typename Packer>
static inline void pack(Packer& packer, const std::vector<T, Allocator>& vector) {
auto items = static_cast<uint64_t>(vector.size());
packer(items);
for(int i = 0; i < items; i++) {
packer(vector[i]);
}
}
template<typename Unpacker>
static inline void unpack(Unpacker& unpacker, std::vector<T, Allocator>& vector) {
uint64_t items;
unpacker(items);
vector.resize(items);
for(int i = 0; i < items; i++) {
unpacker(vector[i]);
}
}
};
}
#endif //PACKETBUFFER_SERIALIZER_STD_VECTOR_H

View File

@@ -0,0 +1,320 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef PACKETBUFFER_UNPACKER_H
#define PACKETBUFFER_UNPACKER_H
#include <boost/endian/conversion.hpp>
#include "ObjectSerializer.h"
namespace PacketBuffer {
template<typename Buffer, boost::endian::order Endianess = boost::endian::order::little>
class Unpacker {
private:
Buffer& buffer;
public:
Unpacker(Buffer& buffer) : buffer(buffer) {};
/**
* Deleted copy constructor.
*/
Unpacker(const Unpacker& other) = delete;
/**
* Deleted copy assignment operator.
*/
Unpacker& operator=(const Unpacker& other) = delete;
/**
* Deleted move constructor.
*/
Unpacker(Unpacker&& other) = delete;
/**
* Deleted move assignment operator.
*/
Unpacker& operator=(Unpacker&& other) = delete;
/**
* Default destructor.
*/
~Unpacker() = default;
public: // Helper methods
/**
* A helper <tt>&</tt> operator overload. Calls the unpack() method for the given type.
*
* @tparam T the data type to unpack
* @param v the value to unpack to
*
* @return this
*/
template<typename T>
Unpacker& operator&(T& v) {
return unpack(v);
}
/**
* A helper <tt>>></tt> operator overload that behaves similarly to ostreams operator. Calls the
* unpack() method for given type.
*
* @tparam T the data type to unpack
* @param v the value to unpack to
*
* @return this
*/
template<typename T>
Unpacker& operator>>(T& v) {
return unpack(v);
}
/**
* A helper call operator overload. Calls unpack() method for the given types.
*
* @tparam Ts the types to be unpacked
* @param vs the values to be unpacked. The values will be unpacked in the given order.
*
* @return this
*/
template<typename... Ts>
Unpacker& operator()(Ts& ... vs) {
return unpack(vs...);
}
/**
* Creates a default constructible object of type T and unpacks the data into it.
*
* @tparam T the type to be unpacked
*
* @return the unpacked object
*/
template<typename T>
T unpack() {
T v;
unpack(v);
return v;
}
public: // Object serialization
/**
* Unpacks a sequence of objects of types <tt>T</tt> and <tt>Ts...</tt>.
*
* The objects will be unpacked in the given order.
*
* @tparam T the type of the first object to be unpacked
* @tparam Ts the type of the remaining objects to be unpacked
* @param v the value of the first object to be unpacked
* @param vs the value of the remaining objects to be unpacked
*
* @return this
*/
template<typename T, typename... Ts>
Unpacker& unpack(T& v, Ts& ... vs) {
unpack(v);
unpack(vs...);
return *this;
}
/**
* Unpacks a single object of type <tt>T</tt>.
*
* @tparam T the type of the object to be unpacked
* @param object the value of the object to be unpacked
*
* @return this
*/
template<typename T>
Unpacker& unpack(T& object) {
ObjectSerializer<T>::unpack(*this, object);
return *this;
}
public: // Integer types
/**
* Unpacks a uint8_t integer value.
*
* @param i the integer value to unpack
*
* @return this
*/
Unpacker& unpack(uint8_t& i) {
static_assert(sizeof(i) == 1, "uint8_t size must be 1 byte");
unpack(reinterpret_cast<char*>(&i), sizeof(i));
boost::endian::conditional_reverse_inplace<Endianess, boost::endian::order::native>(i);
return *this;
}
/**
* Unpacks a int8_t integer value.
*
* @param i the integer value to unpack
*
* @return this
*/
Unpacker& unpack(int8_t& i) {
static_assert(sizeof(i) == 1, "int8_t size must be 1 byte");
unpack(reinterpret_cast<char*>(&i), sizeof(i));
boost::endian::conditional_reverse_inplace<Endianess, boost::endian::order::native>(i);
return *this;
}
/**
* Unpacks a uint16_t integer value.
*
* @param i the integer value to unpack
*
* @return this
*/
Unpacker& unpack(uint16_t& i) {
static_assert(sizeof(i) == 2, "uint16_t size must be 2 byte2");
unpack(reinterpret_cast<char*>(&i), sizeof(i));
boost::endian::conditional_reverse_inplace<Endianess, boost::endian::order::native>(i);
return *this;
}
/**
* Unpacks a int16_t integer value.
*
* @param i the integer value to unpack
*
* @return this
*/
Unpacker& unpack(int16_t& i) {
static_assert(sizeof(i) == 2, "int16_t size must be 2 byte2");
unpack(reinterpret_cast<char*>(&i), sizeof(i));
boost::endian::conditional_reverse_inplace<Endianess, boost::endian::order::native>(i);
return *this;
}
/**
* Unpacks a uint32_t integer value.
*
* @param i the integer value to unpack
*
* @return this
*/
Unpacker& unpack(uint32_t& i) {
static_assert(sizeof(i) == 4, "uint32_t size must be 4 bytes");
unpack(reinterpret_cast<char*>(&i), sizeof(i));
boost::endian::conditional_reverse_inplace<Endianess, boost::endian::order::native>(i);
return *this;
}
/**
* Unpacks a int32_t integer value.
*
* @param i the integer value to unpack
*
* @return this
*/
Unpacker& unpack(int32_t& i) {
static_assert(sizeof(i) == 4, "int32_t size must be 4 bytes");
unpack(reinterpret_cast<char*>(&i), sizeof(i));
boost::endian::conditional_reverse_inplace<Endianess, boost::endian::order::native>(i);
return *this;
}
/**
* Unpacks a uint64_t integer value.
*
* @param i the integer value to unpack
*
* @return this
*/
Unpacker& unpack(uint64_t& i) {
static_assert(sizeof(i) == 8, "uint64_t size must be 8 bytes");
unpack(reinterpret_cast<char*>(&i), sizeof(i));
boost::endian::conditional_reverse_inplace<Endianess, boost::endian::order::native>(i);
return *this;
}
/**
* Unpacks a int64_t integer value.
*
* @param i the integer value to unpack
*
* @return this
*/
Unpacker& unpack(int64_t& i) {
static_assert(sizeof(i) == 8, "int64_t size must be 8 bytes");
unpack(reinterpret_cast<char*>(&i), sizeof(i));
boost::endian::conditional_reverse_inplace<Endianess, boost::endian::order::native>(i);
return *this;
}
/**
* Unpacks a boolean value.
*
* @param b the boolean value to unpack
*
* @return this
*/
Unpacker& unpack(bool& b) {
static_assert(sizeof(b) == 1, "bool size must be 1 byte");
unpack(reinterpret_cast<char*>(&b), sizeof(b));
boost::endian::conditional_reverse_inplace<Endianess, boost::endian::order::native>(b);
return *this;
}
public: // write operation
/**
* Unpacks a char-pointer given by <tt>ptr</tt> with length given by <tt>size</tt>.
*
* @param ptr the char pointer to be unpacked
* @param size the char pointer length
*
* @return this
*/
Unpacker& unpack(char* ptr, size_t size) {
buffer.read(ptr, size);
return *this;
}
/**
* Unpacks a char-pointer given by <tt>ptr</tt> with length given by <tt>size</tt>.
*
* @param ptr the char pointer to be unpacked
* @param size the char pointer length
*
* @return this
*/
Unpacker& unpack(unsigned char* ptr, size_t size) {
buffer.read(ptr, size);
return *this;
}
};
}
#endif //PACKETBUFFER_UNPACKER_H

397
tests/Packer.cpp Normal file
View File

@@ -0,0 +1,397 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <catch.hpp>
#include <sstream>
#include <PacketBuffer/PacketBuffer.h>
std::string string_to_hex(const std::string& input) {
static const char* const lut = "0123456789ABCDEF";
size_t len = input.length();
std::string output;
output.reserve(2 * len);
for(size_t i = 0; i < len; ++i) {
const unsigned char c = input[i];
output.push_back(lut[c >> 4]);
output.push_back(lut[c & 15]);
}
return output;
}
TEST_CASE("Packer", "[packer]") {
std::stringstream ss;
SECTION("little endian") {
PacketBuffer::Packer<std::ostream, boost::endian::order::little> packer(ss);
SECTION("uint8_t") {
SECTION("min") {
packer.pack(std::numeric_limits<uint8_t>::min());
CHECK(string_to_hex(ss.str()) == "00");
}
SECTION("one") {
packer.pack(uint8_t(1));
CHECK(string_to_hex(ss.str()) == "01");
}
SECTION("max") {
packer.pack(std::numeric_limits<uint8_t>::max());
CHECK(string_to_hex(ss.str()) == "FF");
}
}
SECTION("int8_t") {
SECTION("min") {
packer.pack(std::numeric_limits<int8_t>::min());
CHECK(string_to_hex(ss.str()) == "80");
}
SECTION("zero") {
packer.pack(int8_t(0));
CHECK(string_to_hex(ss.str()) == "00");
}
SECTION("one") {
packer.pack(int8_t(1));
CHECK(string_to_hex(ss.str()) == "01");
}
SECTION("max") {
packer.pack(std::numeric_limits<int8_t>::max());
CHECK(string_to_hex(ss.str()) == "7F");
}
}
SECTION("uint16_t") {
SECTION("min") {
packer.pack(std::numeric_limits<uint16_t>::min());
CHECK(string_to_hex(ss.str()) == "0000");
}
SECTION("one") {
packer.pack(uint16_t(1));
CHECK(string_to_hex(ss.str()) == "0100");
}
SECTION("max") {
packer.pack(std::numeric_limits<uint16_t>::max());
CHECK(string_to_hex(ss.str()) == "FFFF");
}
}
SECTION("int16_t") {
SECTION("min") {
packer.pack(std::numeric_limits<int16_t>::min());
CHECK(string_to_hex(ss.str()) == "0080");
}
SECTION("zero") {
packer.pack(int16_t(0));
CHECK(string_to_hex(ss.str()) == "0000");
}
SECTION("one") {
packer.pack(int16_t(1));
CHECK(string_to_hex(ss.str()) == "0100");
}
SECTION("max") {
packer.pack(std::numeric_limits<int16_t>::max());
CHECK(string_to_hex(ss.str()) == "FF7F");
}
}
SECTION("uint32_t") {
SECTION("min") {
packer.pack(std::numeric_limits<uint32_t>::min());
CHECK(string_to_hex(ss.str()) == "00000000");
}
SECTION("one") {
packer.pack(uint32_t(1));
CHECK(string_to_hex(ss.str()) == "01000000");
}
SECTION("max") {
packer.pack(std::numeric_limits<uint32_t>::max());
CHECK(string_to_hex(ss.str()) == "FFFFFFFF");
}
}
SECTION("int32_t") {
SECTION("min") {
packer.pack(std::numeric_limits<int32_t>::min());
CHECK(string_to_hex(ss.str()) == "00000080");
}
SECTION("zero") {
packer.pack(int32_t(0));
CHECK(string_to_hex(ss.str()) == "00000000");
}
SECTION("one") {
packer.pack(int32_t(1));
CHECK(string_to_hex(ss.str()) == "01000000");
}
SECTION("max") {
packer.pack(std::numeric_limits<int32_t>::max());
CHECK(string_to_hex(ss.str()) == "FFFFFF7F");
}
}
SECTION("uint64_t") {
SECTION("min") {
packer.pack(std::numeric_limits<uint64_t>::min());
CHECK(string_to_hex(ss.str()) == "0000000000000000");
}
SECTION("one") {
packer.pack(uint64_t(1));
CHECK(string_to_hex(ss.str()) == "0100000000000000");
}
SECTION("max") {
packer.pack(std::numeric_limits<uint64_t>::max());
CHECK(string_to_hex(ss.str()) == "FFFFFFFFFFFFFFFF");
}
}
SECTION("int64_t") {
SECTION("min") {
packer.pack(std::numeric_limits<int64_t>::min());
CHECK(string_to_hex(ss.str()) == "0000000000000080");
}
SECTION("zero") {
packer.pack(int64_t(0));
CHECK(string_to_hex(ss.str()) == "0000000000000000");
}
SECTION("one") {
packer.pack(int64_t(1));
CHECK(string_to_hex(ss.str()) == "0100000000000000");
}
SECTION("max") {
packer.pack(std::numeric_limits<int64_t>::max());
CHECK(string_to_hex(ss.str()) == "FFFFFFFFFFFFFF7F");
}
}
SECTION("bool") {
SECTION("true") {
packer.pack(true);
CHECK(string_to_hex(ss.str()) == "01");
}
SECTION("false") {
packer.pack(false);
CHECK(string_to_hex(ss.str()) == "00");
}
}
}
SECTION("big endian") {
PacketBuffer::Packer<std::ostream, boost::endian::order::big> packer(ss);
SECTION("uint8_t") {
SECTION("min") {
packer.pack(std::numeric_limits<uint8_t>::min());
CHECK(string_to_hex(ss.str()) == "00");
}
SECTION("one") {
packer.pack(uint8_t(1));
CHECK(string_to_hex(ss.str()) == "01");
}
SECTION("max") {
packer.pack(std::numeric_limits<uint8_t>::max());
CHECK(string_to_hex(ss.str()) == "FF");
}
}
SECTION("int8_t") {
SECTION("min") {
packer.pack(std::numeric_limits<int8_t>::min());
CHECK(string_to_hex(ss.str()) == "80");
}
SECTION("zero") {
packer.pack(int8_t(0));
CHECK(string_to_hex(ss.str()) == "00");
}
SECTION("one") {
packer.pack(int8_t(1));
CHECK(string_to_hex(ss.str()) == "01");
}
SECTION("max") {
packer.pack(std::numeric_limits<int8_t>::max());
CHECK(string_to_hex(ss.str()) == "7F");
}
}
SECTION("uint16_t") {
SECTION("min") {
packer.pack(std::numeric_limits<uint16_t>::min());
CHECK(string_to_hex(ss.str()) == "0000");
}
SECTION("one") {
packer.pack(uint16_t(1));
CHECK(string_to_hex(ss.str()) == "0001");
}
SECTION("max") {
packer.pack(std::numeric_limits<uint16_t>::max());
CHECK(string_to_hex(ss.str()) == "FFFF");
}
}
SECTION("int16_t") {
SECTION("min") {
packer.pack(std::numeric_limits<int16_t>::min());
CHECK(string_to_hex(ss.str()) == "8000");
}
SECTION("zero") {
packer.pack(int16_t(0));
CHECK(string_to_hex(ss.str()) == "0000");
}
SECTION("one") {
packer.pack(int16_t(1));
CHECK(string_to_hex(ss.str()) == "0001");
}
SECTION("max") {
packer.pack(std::numeric_limits<int16_t>::max());
CHECK(string_to_hex(ss.str()) == "7FFF");
}
}
SECTION("uint32_t") {
SECTION("min") {
packer.pack(std::numeric_limits<uint32_t>::min());
CHECK(string_to_hex(ss.str()) == "00000000");
}
SECTION("one") {
packer.pack(uint32_t(1));
CHECK(string_to_hex(ss.str()) == "00000001");
}
SECTION("max") {
packer.pack(std::numeric_limits<uint32_t>::max());
CHECK(string_to_hex(ss.str()) == "FFFFFFFF");
}
}
SECTION("int32_t") {
SECTION("min") {
packer.pack(std::numeric_limits<int32_t>::min());
CHECK(string_to_hex(ss.str()) == "80000000");
}
SECTION("zero") {
packer.pack(int32_t(0));
CHECK(string_to_hex(ss.str()) == "00000000");
}
SECTION("one") {
packer.pack(int32_t(1));
CHECK(string_to_hex(ss.str()) == "00000001");
}
SECTION("max") {
packer.pack(std::numeric_limits<int32_t>::max());
CHECK(string_to_hex(ss.str()) == "7FFFFFFF");
}
}
SECTION("uint64_t") {
SECTION("min") {
packer.pack(std::numeric_limits<uint64_t>::min());
CHECK(string_to_hex(ss.str()) == "0000000000000000");
}
SECTION("one") {
packer.pack(uint64_t(1));
CHECK(string_to_hex(ss.str()) == "0000000000000001");
}
SECTION("max") {
packer.pack(std::numeric_limits<uint64_t>::max());
CHECK(string_to_hex(ss.str()) == "FFFFFFFFFFFFFFFF");
}
}
SECTION("int64_t") {
SECTION("min") {
packer.pack(std::numeric_limits<int64_t>::min());
CHECK(string_to_hex(ss.str()) == "8000000000000000");
}
SECTION("zero") {
packer.pack(int64_t(0));
CHECK(string_to_hex(ss.str()) == "0000000000000000");
}
SECTION("one") {
packer.pack(int64_t(1));
CHECK(string_to_hex(ss.str()) == "0000000000000001");
}
SECTION("max") {
packer.pack(std::numeric_limits<int64_t>::max());
CHECK(string_to_hex(ss.str()) == "7FFFFFFFFFFFFFFF");
}
}
SECTION("bool") {
SECTION("true") {
packer.pack(true);
CHECK(string_to_hex(ss.str()) == "01");
}
SECTION("false") {
packer.pack(false);
CHECK(string_to_hex(ss.str()) == "00");
}
}
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <catch.hpp>
#include <sstream>
#include <PacketBuffer/PacketBuffer.h>
namespace {
std::string string_to_hex(const std::string& input) {
static const char* const lut = "0123456789ABCDEF";
size_t len = input.length();
std::string output;
output.reserve(2 * len);
for(size_t i = 0; i < len; ++i) {
const unsigned char c = input[i];
output.push_back(lut[c >> 4]);
output.push_back(lut[c & 15]);
}
return output;
}
}
TEST_CASE("Serializer/Std/Array", "[serializer][std][array]") {
std::stringstream ss;
PacketBuffer::Packer<std::ostream> packer(ss);
PacketBuffer::Unpacker<std::istream> unpacker(ss);
SECTION("empty array") {
SECTION("should be correctly packed") {
std::array<uint8_t, 0> array;
packer.pack(array);
CHECK(string_to_hex(ss.str()) == "");
SECTION("and should unpack back") {
std::array<uint8_t, 0> unpacked;
unpacker.unpack(unpacked);
CHECK(unpacked.size() == 0);
}
}
}
SECTION("should be correctly packed") {
std::array<uint8_t, 2> array = {100, 200};
packer.pack(array);
CHECK(string_to_hex(ss.str()) == "64C8");
SECTION("and should unpack back") {
std::array<uint8_t, 2> unpacked;
unpacker.unpack(unpacked);
REQUIRE(unpacked.size() == 2);
CHECK(unpacked == array);
}
}
}
TEST_CASE("Serializer/Std/CArray", "[serializer][std][c-array]") {
std::stringstream ss;
PacketBuffer::Packer<std::ostream> packer(ss);
PacketBuffer::Unpacker<std::istream> unpacker(ss);
SECTION("should be correctly packed") {
uint8_t array[4] = {1, 2, 3, 4};
packer.pack(array);
CHECK(string_to_hex(ss.str()) == "01020304");
SECTION("and should unpack back") {
uint8_t unpacked[4];
unpacker.unpack(unpacked);
CHECK(unpacked[0] == array[0]);
CHECK(unpacked[1] == array[1]);
CHECK(unpacked[2] == array[2]);
CHECK(unpacked[3] == array[3]);
}
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <catch.hpp>
#include <sstream>
#include <PacketBuffer/PacketBuffer.h>
namespace {
std::string string_to_hex(const std::string& input) {
static const char* const lut = "0123456789ABCDEF";
size_t len = input.length();
std::string output;
output.reserve(2 * len);
for(size_t i = 0; i < len; ++i) {
const unsigned char c = input[i];
output.push_back(lut[c >> 4]);
output.push_back(lut[c & 15]);
}
return output;
}
}
TEST_CASE("Serializer/Std/String", "[serializer][std][string]") {
std::stringstream ss;
PacketBuffer::Packer<std::ostream> packer(ss);
PacketBuffer::Unpacker<std::istream> unpacker(ss);
SECTION("empty string") {
SECTION("should be correctly packed") {
std::string string = "";
packer.pack(string);
CHECK(string_to_hex(ss.str()) == "0000000000000000");
SECTION("and should unpack back") {
std::string unpacked;
unpacker.unpack(unpacked);
CHECK(unpacked.size() == 0);
CHECK(unpacked == string);
}
}
}
SECTION("should be correctly packed") {
std::string string = "Hello Testing World";
packer.pack(string);
CHECK(string_to_hex(ss.str()) == "130000000000000048656C6C6F2054657374696E6720576F726C64");
SECTION("and should unpack back") {
std::string unpacked;
unpacker.unpack(unpacked);
REQUIRE(unpacked.size() == 19);
CHECK(unpacked == string);
}
}
SECTION("with NULL character") {
SECTION("should be correctly packed") {
std::string string = "Hey";
string.resize(4);
string[3] = 0x00;
packer.pack(string);
CHECK(string_to_hex(ss.str()) == "040000000000000048657900");
SECTION("and should unpack back") {
std::string unpacked;
unpacker.unpack(unpacked);
REQUIRE(unpacked.size() == 4);
CHECK(unpacked == string);
}
}
}
}

413
tests/Unpacker.cpp Normal file
View File

@@ -0,0 +1,413 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <catch.hpp>
#include <sstream>
#include <algorithm>
#include <stdexcept>
#include <PacketBuffer/PacketBuffer.h>
std::string hex_to_string(const std::string& input) {
static const char* const lut = "0123456789ABCDEF";
size_t len = input.length();
if(len & 1) throw std::invalid_argument("odd length");
std::string output;
output.reserve(len / 2);
for(size_t i = 0; i < len; i += 2) {
char a = input[i];
const char* p = std::lower_bound(lut, lut + 16, a);
if(*p != a) throw std::invalid_argument("not a hex digit");
char b = input[i + 1];
const char* q = std::lower_bound(lut, lut + 16, b);
if(*q != b) throw std::invalid_argument("not a hex digit");
output.push_back(((p - lut) << 4) | (q - lut));
}
return output;
}
TEST_CASE("Unpacker", "[unpacker]") {
std::stringstream ss;
SECTION("little endian") {
PacketBuffer::Unpacker<std::istream, boost::endian::order::little> unpacker(ss);
SECTION("uint8_t") {
SECTION("min") {
ss.str(hex_to_string("00"));
CHECK(unpacker.unpack<uint8_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("01"));
CHECK(unpacker.unpack<uint8_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("FF"));
CHECK(unpacker.unpack<uint8_t>() == 255);
}
}
SECTION("int8_t") {
SECTION("min") {
ss.str(hex_to_string("80"));
CHECK(unpacker.unpack<int8_t>() == -128);
}
SECTION("zero") {
ss.str(hex_to_string("00"));
CHECK(unpacker.unpack<int8_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("01"));
CHECK(unpacker.unpack<int8_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("7F"));
CHECK(unpacker.unpack<int8_t>() == 127);
}
}
SECTION("uint16_t") {
SECTION("min") {
ss.str(hex_to_string("0000"));
CHECK(unpacker.unpack<uint16_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("0100"));
CHECK(unpacker.unpack<uint16_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("FFFF"));
CHECK(unpacker.unpack<uint16_t>() == 65535);
}
}
SECTION("int16_t") {
SECTION("min") {
ss.str(hex_to_string("0080"));
CHECK(unpacker.unpack<int16_t>() == -32768);
}
SECTION("zero") {
ss.str(hex_to_string("0000"));
CHECK(unpacker.unpack<int16_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("0100"));
CHECK(unpacker.unpack<int16_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("FF7F"));
CHECK(unpacker.unpack<int16_t>() == 32767);
}
}
SECTION("uint32_t") {
SECTION("min") {
ss.str(hex_to_string("00000000"));
CHECK(unpacker.unpack<uint32_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("01000000"));
CHECK(unpacker.unpack<uint32_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("FFFFFFFF"));
CHECK(unpacker.unpack<uint32_t>() == 4294967295);
}
}
SECTION("int32_t") {
SECTION("min") {
ss.str(hex_to_string("00000080"));
CHECK(unpacker.unpack<int32_t>() == -2147483648);
}
SECTION("zero") {
ss.str(hex_to_string("00000000"));
CHECK(unpacker.unpack<int32_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("01000000"));
CHECK(unpacker.unpack<int32_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("FFFFFF7F"));
CHECK(unpacker.unpack<int32_t>() == 2147483647);
}
}
SECTION("uint64_t") {
SECTION("min") {
ss.str(hex_to_string("0000000000000000"));
CHECK(unpacker.unpack<uint64_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("0100000000000000"));
CHECK(unpacker.unpack<uint64_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("FFFFFFFFFFFFFFFF"));
CHECK(unpacker.unpack<uint64_t>() == 18446744073709551615UL);
}
}
SECTION("int64_t") {
SECTION("min") {
ss.str(hex_to_string("0000000000000080"));
CHECK(unpacker.unpack<int64_t>() == -9223372036854775808L);
}
SECTION("zero") {
ss.str(hex_to_string("0000000000000000"));
CHECK(unpacker.unpack<int64_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("0100000000000000"));
CHECK(unpacker.unpack<int64_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("FFFFFFFFFFFFFF7F"));
CHECK(unpacker.unpack<int64_t>() == 9223372036854775807L);
}
}
SECTION("bool") {
SECTION("true") {
ss.str(hex_to_string("01"));
CHECK(unpacker.unpack<bool>() == true);
}
SECTION("false") {
ss.str(hex_to_string("00"));
CHECK(unpacker.unpack<bool>() == false);
}
}
}
SECTION("big endian") {
PacketBuffer::Unpacker<std::istream, boost::endian::order::big> unpacker(ss);
SECTION("uint8_t") {
SECTION("min") {
ss.str(hex_to_string("00"));
CHECK(unpacker.unpack<uint8_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("01"));
CHECK(unpacker.unpack<uint8_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("FF"));
CHECK(unpacker.unpack<uint8_t>() == 255);
}
}
SECTION("int8_t") {
SECTION("min") {
ss.str(hex_to_string("80"));
CHECK(unpacker.unpack<int8_t>() == -128);
}
SECTION("zero") {
ss.str(hex_to_string("00"));
CHECK(unpacker.unpack<int8_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("01"));
CHECK(unpacker.unpack<int8_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("7F"));
CHECK(unpacker.unpack<int8_t>() == 127);
}
}
SECTION("uint16_t") {
SECTION("min") {
ss.str(hex_to_string("0000"));
CHECK(unpacker.unpack<uint16_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("0001"));
CHECK(unpacker.unpack<uint16_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("FFFF"));
CHECK(unpacker.unpack<uint16_t>() == 65535);
}
}
SECTION("int16_t") {
SECTION("min") {
ss.str(hex_to_string("8000"));
CHECK(unpacker.unpack<int16_t>() == -32768);
}
SECTION("zero") {
ss.str(hex_to_string("0000"));
CHECK(unpacker.unpack<int16_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("0001"));
CHECK(unpacker.unpack<int16_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("7FFF"));
CHECK(unpacker.unpack<int16_t>() == 32767);
}
}
SECTION("uint32_t") {
SECTION("min") {
ss.str(hex_to_string("00000000"));
CHECK(unpacker.unpack<uint32_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("00000001"));
CHECK(unpacker.unpack<uint32_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("FFFFFFFF"));
CHECK(unpacker.unpack<uint32_t>() == 4294967295);
}
}
SECTION("int32_t") {
SECTION("min") {
ss.str(hex_to_string("80000000"));
CHECK(unpacker.unpack<int32_t>() == -2147483648);
}
SECTION("zero") {
ss.str(hex_to_string("00000000"));
CHECK(unpacker.unpack<int32_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("00000001"));
CHECK(unpacker.unpack<int32_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("7FFFFFFF"));
CHECK(unpacker.unpack<int32_t>() == 2147483647);
}
}
SECTION("uint64_t") {
SECTION("min") {
ss.str(hex_to_string("0000000000000000"));
CHECK(unpacker.unpack<uint64_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("0000000000000001"));
CHECK(unpacker.unpack<uint64_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("FFFFFFFFFFFFFFFF"));
CHECK(unpacker.unpack<uint64_t>() == 18446744073709551615UL);
}
}
SECTION("int64_t") {
SECTION("min") {
ss.str(hex_to_string("8000000000000000"));
CHECK(unpacker.unpack<int64_t>() == -9223372036854775808L);
}
SECTION("zero") {
ss.str(hex_to_string("0000000000000000"));
CHECK(unpacker.unpack<int64_t>() == 0);
}
SECTION("one") {
ss.str(hex_to_string("0000000000000001"));
CHECK(unpacker.unpack<int64_t>() == 1);
}
SECTION("max") {
ss.str(hex_to_string("7FFFFFFFFFFFFFFF"));
CHECK(unpacker.unpack<int64_t>() == 9223372036854775807L);
}
}
SECTION("bool") {
SECTION("true") {
ss.str(hex_to_string("01"));
CHECK(unpacker.unpack<bool>() == true);
}
SECTION("false") {
ss.str(hex_to_string("00"));
CHECK(unpacker.unpack<bool>() == false);
}
}
}
SECTION("should throw an error on overflow") {
PacketBuffer::Unpacker<std::istream> unpacker(ss);
// REQUIRE_THROWS(unpacker.unpack<uint32_t>());
}
}

32
tests/main.cpp Normal file
View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2017, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rogiel Sulzbach nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#define CATCH_CONFIG_MAIN
#include "catch.hpp"