diff --git a/include/NZSL/Serializer.hpp b/include/NZSL/Serializer.hpp index 1a12b8b..4fcc547 100644 --- a/include/NZSL/Serializer.hpp +++ b/include/NZSL/Serializer.hpp @@ -7,6 +7,7 @@ #ifndef NZSL_SERIALIZER_HPP #define NZSL_SERIALIZER_HPP +#include #include #include #include @@ -18,18 +19,34 @@ namespace nzsl public: virtual ~AbstractSerializer(); - virtual void Serialize(bool value); - virtual void Serialize(double value); - virtual void Serialize(float value); - virtual void Serialize(std::int8_t value); - virtual void Serialize(std::int16_t value); - virtual void Serialize(std::int32_t value); - virtual void Serialize(std::int64_t value); - virtual void Serialize(std::uint8_t value) = 0; - virtual void Serialize(std::uint16_t value) = 0; - virtual void Serialize(std::uint32_t value) = 0; - virtual void Serialize(std::uint64_t value) = 0; - virtual void Serialize(const std::string& value); + virtual void Serialize(std::size_t offset, bool value); + virtual void Serialize(std::size_t offset, double value); + virtual void Serialize(std::size_t offset, float value); + virtual void Serialize(std::size_t offset, std::int8_t value); + virtual void Serialize(std::size_t offset, std::int16_t value); + virtual void Serialize(std::size_t offset, std::int32_t value); + virtual void Serialize(std::size_t offset, std::int64_t value); + virtual void Serialize(std::size_t offset, std::uint8_t value) = 0; + virtual void Serialize(std::size_t offset, std::uint16_t value) = 0; + virtual void Serialize(std::size_t offset, std::uint32_t value) = 0; + virtual void Serialize(std::size_t offset, std::uint64_t value) = 0; + virtual void Serialize(std::size_t offset, const std::string& value); + virtual void Serialize(std::size_t offset, const void* data, std::size_t size) = 0; + + virtual std::size_t Serialize(bool value); + virtual std::size_t Serialize(double value); + virtual std::size_t Serialize(float value); + virtual std::size_t Serialize(std::int8_t value); + virtual std::size_t Serialize(std::int16_t value); + virtual std::size_t Serialize(std::int32_t value); + virtual std::size_t Serialize(std::int64_t value); + virtual std::size_t Serialize(std::uint8_t value) = 0; + virtual std::size_t Serialize(std::uint16_t value) = 0; + virtual std::size_t Serialize(std::uint32_t value) = 0; + virtual std::size_t Serialize(std::uint64_t value) = 0; + virtual std::size_t Serialize(const std::string& value); + virtual std::size_t Serialize(const void* data, std::size_t size); + virtual std::size_t Serialize(std::size_t size, const Nz::FunctionRef& callback) = 0; }; class NZSL_API AbstractDeserializer @@ -49,6 +66,10 @@ namespace nzsl virtual void Deserialize(std::uint32_t& value) = 0; virtual void Deserialize(std::uint64_t& value) = 0; virtual void Deserialize(std::string& value); + virtual void Deserialize(void* data, std::size_t size) = 0; + virtual void Deserialize(std::size_t size, const Nz::FunctionRef& callback) = 0; + + virtual void SeekTo(std::size_t offset) = 0; }; class NZSL_API Serializer : public AbstractSerializer @@ -59,13 +80,23 @@ namespace nzsl Serializer(Serializer&&) noexcept = default; ~Serializer() = default; - inline const std::vector& GetData() const; + inline const std::vector& GetData() const&; + inline std::vector GetData() &&; using AbstractSerializer::Serialize; - void Serialize(std::uint8_t value) override; - void Serialize(std::uint16_t value) override; - void Serialize(std::uint32_t value) override; - void Serialize(std::uint64_t value) override; + + void Serialize(std::size_t offset, std::uint8_t value) override; + void Serialize(std::size_t offset, std::uint16_t value) override; + void Serialize(std::size_t offset, std::uint32_t value) override; + void Serialize(std::size_t offset, std::uint64_t value) override; + void Serialize(std::size_t offset, const void* data, std::size_t size) override; + + std::size_t Serialize(std::uint8_t value) override; + std::size_t Serialize(std::uint16_t value) override; + std::size_t Serialize(std::uint32_t value) override; + std::size_t Serialize(std::uint64_t value) override; + std::size_t Serialize(const void* data, std::size_t size) override; + std::size_t Serialize(std::size_t size, const Nz::FunctionRef& callback) override; Serializer& operator=(const Serializer&) = default; Serializer& operator=(Serializer&&) noexcept = default; @@ -87,12 +118,17 @@ namespace nzsl void Deserialize(std::uint16_t& value) override; void Deserialize(std::uint32_t& value) override; void Deserialize(std::uint64_t& value) override; + void Deserialize(void* data, std::size_t size) override; + void Deserialize(std::size_t size, const Nz::FunctionRef& callback) override; + + void SeekTo(std::size_t offset) override; Deserializer& operator=(const Deserializer&) = default; Deserializer& operator=(Deserializer&&) noexcept = default; private: const std::uint8_t* m_ptr; + const std::uint8_t* m_ptrBegin; const std::uint8_t* m_ptrEnd; }; } diff --git a/include/NZSL/Serializer.inl b/include/NZSL/Serializer.inl index 15581fa..2ff23b6 100644 --- a/include/NZSL/Serializer.inl +++ b/include/NZSL/Serializer.inl @@ -6,14 +6,20 @@ namespace nzsl { - inline const std::vector& Serializer::GetData() const + inline const std::vector& Serializer::GetData() const& { return m_data; } + inline std::vector Serializer::GetData() && + { + return std::move(m_data); + } + inline Deserializer::Deserializer(const void* data, std::size_t dataSize) { m_ptr = static_cast(data); + m_ptrBegin = m_ptr; m_ptrEnd = m_ptr + dataSize; } } diff --git a/src/NZSL/Serializer.cpp b/src/NZSL/Serializer.cpp index 25d4cd5..bea9b65 100644 --- a/src/NZSL/Serializer.cpp +++ b/src/NZSL/Serializer.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -13,46 +14,99 @@ namespace nzsl AbstractDeserializer::~AbstractDeserializer() = default; - void AbstractSerializer::Serialize(bool value) + void AbstractSerializer::Serialize(std::size_t offset, bool value) { - Serialize(static_cast(value)); + return Serialize(offset, static_cast(value)); } - void AbstractSerializer::Serialize(double value) + void AbstractSerializer::Serialize(std::size_t offset, double value) { - Serialize(Nz::BitCast(value)); + return Serialize(offset, Nz::BitCast(value)); } - void AbstractSerializer::Serialize(float value) + void AbstractSerializer::Serialize(std::size_t offset, float value) { - Serialize(Nz::BitCast(value)); + return Serialize(offset, Nz::BitCast(value)); } - void AbstractSerializer::Serialize(std::int8_t value) + void AbstractSerializer::Serialize(std::size_t offset, std::int8_t value) { - Serialize(Nz::BitCast(value)); + return Serialize(offset, Nz::BitCast(value)); } - void AbstractSerializer::Serialize(std::int16_t value) + void AbstractSerializer::Serialize(std::size_t offset, std::int16_t value) { - Serialize(Nz::BitCast(value)); + return Serialize(offset, Nz::BitCast(value)); } - void AbstractSerializer::Serialize(std::int32_t value) + void AbstractSerializer::Serialize(std::size_t offset, std::int32_t value) { - Serialize(Nz::BitCast(value)); + return Serialize(offset, Nz::BitCast(value)); } - void AbstractSerializer::Serialize(std::int64_t value) + void AbstractSerializer::Serialize(std::size_t offset, std::int64_t value) { - Serialize(Nz::BitCast(value)); + return Serialize(offset, Nz::BitCast(value)); } - void AbstractSerializer::Serialize(const std::string& value) + void AbstractSerializer::Serialize(std::size_t offset, const std::string& value) { - Serialize(Nz::SafeCast(value.size())); - for (char c : value) - Serialize(static_cast(c)); + Serialize(offset, Nz::SafeCast(value.size())); + Serialize(offset + sizeof(std::uint32_t), value.data(), value.size()); + } + + std::size_t AbstractSerializer::Serialize(bool value) + { + return Serialize(static_cast(value)); + } + + std::size_t AbstractSerializer::Serialize(double value) + { + return Serialize(Nz::BitCast(value)); + } + + std::size_t AbstractSerializer::Serialize(float value) + { + return Serialize(Nz::BitCast(value)); + } + + std::size_t AbstractSerializer::Serialize(std::int8_t value) + { + return Serialize(Nz::BitCast(value)); + } + + std::size_t AbstractSerializer::Serialize(std::int16_t value) + { + return Serialize(Nz::BitCast(value)); + } + + std::size_t AbstractSerializer::Serialize(std::int32_t value) + { + return Serialize(Nz::BitCast(value)); + } + + std::size_t AbstractSerializer::Serialize(std::int64_t value) + { + return Serialize(Nz::BitCast(value)); + } + + std::size_t AbstractSerializer::Serialize(const std::string& value) + { + std::size_t offset = Serialize(Nz::SafeCast(value.size())); + Serialize(value.data(), value.size()); + + return offset; + } + + std::size_t AbstractSerializer::Serialize(const void* data, std::size_t size) + { + return Serialize(size, [&](void* dst) + { + if (data) + std::memcpy(dst, data, size); + + return size; + }); } @@ -118,82 +172,137 @@ namespace nzsl Deserialize(size); value.resize(size); - for (char& c : value) - { - std::uint8_t characterValue; - Deserialize(characterValue); + Deserialize(value.data(), size); + } - c = static_cast(characterValue); - } + + void Serializer::Serialize(std::size_t offset, std::uint8_t value) + { + m_data[offset] = value; } - void Serializer::Serialize(std::uint8_t value) + void Serializer::Serialize(std::size_t offset, std::uint16_t value) { - m_data.push_back(value); + value = Nz::HostToLittleEndian(value); + std::memcpy(&m_data[offset], &value, sizeof(value)); } - void Serializer::Serialize(std::uint16_t value) + void Serializer::Serialize(std::size_t offset, std::uint32_t value) { value = Nz::HostToLittleEndian(value); + std::memcpy(&m_data[offset], &value, sizeof(value)); + } + + void Serializer::Serialize(std::size_t offset, std::uint64_t value) + { + value = Nz::HostToLittleEndian(value); + std::memcpy(&m_data[offset], &value, sizeof(value)); + } + + void Serializer::Serialize(std::size_t offset, const void* data, std::size_t size) + { + assert(data); + std::memcpy(&m_data[offset], data, size); + } + + std::size_t Serializer::Serialize(std::uint8_t value) + { + std::size_t offset = m_data.size(); + m_data.push_back(value); - std::uint8_t* ptr = reinterpret_cast(&value); - m_data.insert(m_data.end(), ptr, ptr + sizeof(value)); + return offset; } - void Serializer::Serialize(std::uint32_t value) + std::size_t Serializer::Serialize(std::uint16_t value) { value = Nz::HostToLittleEndian(value); + return Serialize(&value, sizeof(value)); + } - std::uint8_t* ptr = reinterpret_cast(&value); - m_data.insert(m_data.end(), ptr, ptr + sizeof(value)); + std::size_t Serializer::Serialize(std::uint32_t value) + { + value = Nz::HostToLittleEndian(value); + return Serialize(&value, sizeof(value)); } - void Serializer::Serialize(std::uint64_t value) + std::size_t Serializer::Serialize(std::uint64_t value) { value = Nz::HostToLittleEndian(value); + return Serialize(&value, sizeof(value)); + } - std::uint8_t* ptr = reinterpret_cast(&value); - m_data.insert(m_data.end(), ptr, ptr + sizeof(value)); + std::size_t Serializer::Serialize(const void* data, std::size_t size) + { + const std::uint8_t* ptr = reinterpret_cast(data); + + std::size_t offset = m_data.size(); + if (data) + m_data.insert(m_data.end(), ptr, ptr + size); + else + m_data.resize(offset + size); + + return offset; } + std::size_t Serializer::Serialize(std::size_t size, const Nz::FunctionRef& callback) + { + std::size_t offset = m_data.size(); + m_data.resize(offset + size); + std::size_t realSize = callback(&m_data[offset]); + m_data.resize(offset + realSize); + + return offset; + } + + void Deserializer::Deserialize(std::uint8_t& value) { - if (m_ptr + sizeof(value) > m_ptrEnd) - throw std::runtime_error("not enough data to deserialize u8"); + if NAZARA_UNLIKELY(m_ptr + sizeof(value) > m_ptrEnd) + throw std::runtime_error("not enough data to deserialize byte"); value = *m_ptr++; } void Deserializer::Deserialize(std::uint16_t& value) { - if (m_ptr + sizeof(value) > m_ptrEnd) - throw std::runtime_error("not enough data to deserialize u16"); + Deserialize(&value, sizeof(value)); + value = Nz::LittleEndianToHost(value); + } - std::memcpy(&value, m_ptr, sizeof(value)); - m_ptr += sizeof(value); + void Deserializer::Deserialize(std::uint32_t& value) + { + Deserialize(&value, sizeof(value)); + value = Nz::LittleEndianToHost(value); + } + void Deserializer::Deserialize(std::uint64_t& value) + { + Deserialize(&value, sizeof(value)); value = Nz::LittleEndianToHost(value); } - void Deserializer::Deserialize(std::uint32_t& value) + void Deserializer::Deserialize(void* data, std::size_t size) { - if (m_ptr + sizeof(value) > m_ptrEnd) - throw std::runtime_error("not enough data to deserialize u32"); + if NAZARA_UNLIKELY(m_ptr + size > m_ptrEnd) + throw std::runtime_error(fmt::format("not enough data to deserialize {} bytes", size)); - std::memcpy(&value, m_ptr, sizeof(value)); - m_ptr += sizeof(value); + if (data) + std::memcpy(data, m_ptr, size); - value = Nz::LittleEndianToHost(value); + m_ptr += size; } - void Deserializer::Deserialize(std::uint64_t& value) + void Deserializer::Deserialize(std::size_t size, const Nz::FunctionRef& callback) { - if (m_ptr + sizeof(value) > m_ptrEnd) - throw std::runtime_error("not enough data to deserialize u64"); + if NAZARA_UNLIKELY(m_ptr + size > m_ptrEnd) + throw std::runtime_error(fmt::format("not enough data to deserialize {} bytes", size)); - std::memcpy(&value, m_ptr, sizeof(value)); - m_ptr += sizeof(value); + std::size_t readSize = callback(m_ptr); + m_ptr += readSize; + } - value = Nz::LittleEndianToHost(value); + void Deserializer::SeekTo(std::size_t offset) + { + m_ptr = m_ptrBegin + offset; } }