diff options
Diffstat (limited to 'sibs/SafeDeserializer.hpp')
-rw-r--r-- | sibs/SafeDeserializer.hpp | 90 |
1 files changed, 90 insertions, 0 deletions
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; + }; +} |