diff options
author | dec05eba <dec05eba@protonmail.com> | 2018-02-01 20:56:03 +0100 |
---|---|---|
committer | Aleksi Lindeman <aleksi_888@hotmail.com> | 2018-02-01 20:56:11 +0100 |
commit | 91418b32d7b67c335eb3baffc0bf381c04f68035 (patch) | |
tree | 37afbd00ee237b039baa83042567d7be9ec0f742 | |
parent | d6f8d63dc4ed077fa986a78d6390fa4497110152 (diff) |
Initial commit0.1.0
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | README.md | 9 | ||||
-rw-r--r-- | project.conf | 9 | ||||
-rw-r--r-- | sibs/SafeDeserializer.hpp | 90 | ||||
-rw-r--r-- | sibs/SafeSerializer.hpp | 44 | ||||
-rw-r--r-- | tests/main.cpp | 40 | ||||
-rw-r--r-- | types.hpp | 22 | ||||
-rwxr-xr-x | utils.hpp | 6 |
8 files changed, 220 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f2d790 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +sibs-build/ +.vscode/ @@ -1,2 +1,7 @@ -# serializer -Safe serializer +# Note +Using this library to serialize non plain old data types will result in platform defined behavior unless you specify +padding for the struct yourself. If you want to serialize non plain old data types, then it is recommended to serialize +each field manually (also when deserializing) + +# TODO +Add more tests
\ No newline at end of file diff --git a/project.conf b/project.conf new file mode 100644 index 0000000..6badb64 --- /dev/null +++ b/project.conf @@ -0,0 +1,9 @@ +[package] +name = "sibs-serializer" +version = "0.1.0" +type = "static" +platforms = ["any"] +tests = "tests" + +[config] +expose_include_dirs = ["."]
\ No newline at end of file diff --git a/sibs/SafeDeserializer.hpp b/sibs/SafeDeserializer.hpp new file mode 100644 index 0000000..3d83042 --- /dev/null +++ b/sibs/SafeDeserializer.hpp @@ -0,0 +1,90 @@ +#pragma once + +#include "../types.hpp" +#include "../utils.hpp" +#include <cstring> +#include <stdexcept> + +namespace sibs +{ + class DeserializeException : public std::runtime_error + { + public: + DeserializeException(const std::string &errMsg) : std::runtime_error(errMsg) {} + }; + + /** + * Endian independent deserializer + */ + class SafeDeserializer + { + DISABLE_COPY(SafeDeserializer); + public: + SafeDeserializer(const u8 *_data, usize _size) : + data(_data), + size(_size) + { + + } + + /* + * Throws DeserializeException on failure + */ + template <typename T> + T&& extract() + { + constexpr usize typeSize = sizeof(T); + verifyExtractSize(typeSize); + size -= typeSize; + T result; + memcpy(&result, data, typeSize); + data += typeSize; + return std::move(result); + } + + /* + * Throws DeserializeException on failure + */ + void extract(u8 *destination, usize destinationSize) + { + if(destinationSize > 0) + { + verifyExtractSize(destinationSize); + size -= destinationSize; + memcpy(destination, data, destinationSize); + data += destinationSize; + } + } + + bool empty() const + { + return size == 0; + } + + const u8* getBuffer() + { + return data; + } + + usize getSize() const + { + return size; + } + private: + void verifyExtractSize(usize typeSize) const + { + if(typeSize > size) + { + std::string errMsg = "Unable to extract "; + errMsg += std::to_string(typeSize); + errMsg += " bytes, only "; + errMsg += std::to_string(size); + errMsg += " bytes left in buffer"; + throw DeserializeException(errMsg); + } + } + private: + const u8 *data; + usize size; + }; +} diff --git a/sibs/SafeSerializer.hpp b/sibs/SafeSerializer.hpp new file mode 100644 index 0000000..94bcdc5 --- /dev/null +++ b/sibs/SafeSerializer.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include "../types.hpp" +#include "../utils.hpp" +#include <vector> +#include <cstring> + +namespace sibs +{ + /** + * Endian independent serializer + */ + class SafeSerializer + { + DISABLE_COPY(SafeSerializer); + public: + SafeSerializer(){} + + template <typename T> + void add(const T &data) + { + usize offset = buffer.size(); + buffer.resize(buffer.size() + sizeof(data)); + memcpy(&buffer[offset], &data, sizeof(data)); + } + + void add(const u8 *data, usize size) + { + if(size > 0) + { + usize offset = buffer.size(); + buffer.resize(buffer.size() + size); + memcpy(&buffer[offset], data, size); + } + } + + std::vector<u8>& getBuffer() + { + return buffer; + } + private: + std::vector<u8> buffer; + }; +} diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100644 index 0000000..e495b3a --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,40 @@ +#include <cstdio> +#include <cstdlib> +#include <sibs/SafeSerializer.hpp> +#include <sibs/SafeDeserializer.hpp> +#include <cstdint> + +#define REQUIRE(statement) do { if(!(statement)) { fprintf(stderr, "Assertion failed:\n%s\n", #statement); exit(1); } } while(0) +#define FAIL(str) do { fprintf(stderr, "Failed:\n%s\n", (str)); exit(1); } while(0) + +int main() +{ + sibs::SafeSerializer serializer; + serializer.add((uint32_t)3563634); + serializer.add((uint64_t)204232532533423632); + serializer.add((uint8_t)2); + serializer.add((uint8_t*)"hello", 5); + REQUIRE(serializer.getBuffer().size() == 18); + + sibs::SafeDeserializer deserializer(serializer.getBuffer().data(), serializer.getBuffer().size()); + REQUIRE(deserializer.extract<uint32_t>() == 3563634); + REQUIRE(deserializer.extract<uint64_t>() == 204232532533423632); + REQUIRE(deserializer.extract<uint8_t>() == 2); + char str[6]; + str[5] = '\0'; + deserializer.extract((uint8_t*)str, 5); + REQUIRE(strcmp(str, "hello") == 0); + REQUIRE(deserializer.empty()); + + try + { + deserializer.extract<uint8_t>(); + FAIL("Expected extract to fail since we have extracted all data"); + } + catch (sibs::DeserializeException &e) + { + + } + + return 0; +}
\ No newline at end of file diff --git a/types.hpp b/types.hpp new file mode 100644 index 0000000..0379100 --- /dev/null +++ b/types.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include <cstdint> + +namespace sibs +{ + typedef int8_t i8; + typedef int16_t i16; + typedef int32_t i32; + typedef int64_t i64; + + typedef uint8_t u8; + typedef uint16_t u16; + typedef uint32_t u32; + typedef uint64_t u64; + + typedef float f32; + typedef double f64; + + typedef intptr_t isize; + typedef uintptr_t usize; +} diff --git a/utils.hpp b/utils.hpp new file mode 100755 index 0000000..01e478d --- /dev/null +++ b/utils.hpp @@ -0,0 +1,6 @@ +#pragma once + +// Disable copying for a class or struct +#define DISABLE_COPY(ClassName) \ + ClassName(ClassName&) = delete; \ + ClassName& operator = (ClassName&) = delete; |