二进制序列化

#include <cstring>
#include <cstdint>
#include <vector>

namespace bond
{
	template<typename STRLEN_TYPE = std::uint32_t>
	class reader
	{
		unsigned char const * first;
		unsigned char const * last;
		unsigned char const * it;
	public:
		reader() noexcept
		{
			first = nullptr;
			last = nullptr;
			it = nullptr;
		}

		reader(void const * data, std::size_t len) noexcept
		{
			set(data, len);
		}

		void set(void const * data, std::size_t len) noexcept
		{
			first = static_cast<unsigned char const *>(data);
			last = static_cast<unsigned char const *>(data) + len;
			it = static_cast<unsigned char const *>(data);
		}

		std::size_t remain() noexcept
		{
			return static_cast<std::size_t>(last - it);
		}

		template<typename T>
		bool read(T * output) noexcept
		{
			if (remain() < sizeof(*output))
				return false;
			std::memcpy(output, it, sizeof(*output));
			it += sizeof(*output);
			return true;
		}

		bool read(void * output, std::size_t len) noexcept
		{
			if (remain() < len)
				return false;
			std::memcpy(output, it, len);
			it += len;
			return true;
		}

		bool next_strlen(STRLEN_TYPE * output) noexcept
		{
			STRLEN_TYPE len;
			std::size_t remain_size = remain();
			if (remain_size < sizeof(len))
				return false;
			std::memcpy(&len, it, sizeof(len));
			if (remain_size < sizeof(len) + len)
				return false;
			*output = len;
			return true;
		}

		bool read_str(char * output, STRLEN_TYPE len) noexcept
		{
			STRLEN_TYPE slen;
			if (!next_strlen(&slen))
				return false;
			if (len <= slen)
				return false;
			unsigned char const * data = it + sizeof(slen);
			std::memcpy(output, data, slen);
			output[slen] = '\0';
			it = data + slen;
			return true;
		}

	};

	template<typename STRLEN_TYPE = std::uint32_t>
	class writer
	{
		unsigned char * first;
		unsigned char * last;
		unsigned char * it;
	public:
		writer() noexcept
		{
			first = nullptr;
			last = nullptr;
			it = nullptr;
		}

		writer(void * data, std::size_t len) noexcept
		{
			set(data, len);
		}

		void set(void * data, std::size_t len) noexcept
		{
			first = static_cast<unsigned char *>(data);
			last = static_cast<unsigned char *>(data) + len;
			it = static_cast<unsigned char *>(data);
		}

		void * data() noexcept
		{
			return first;
		}

		std::size_t size() noexcept
		{
			return static_cast<std::size_t>(it - first);
		}

		std::size_t remain() noexcept
		{
			return static_cast<std::size_t>(last - it);
		}

		template<typename T>
		bool write(T const & input) noexcept
		{
			if (remain() < sizeof(input))
				return false;
			unsigned char * data = it;
			std::memcpy(data, &input, sizeof(input));
			it = data + sizeof(input);
			return true;
		}

		bool write(void const * input, std::size_t len) noexcept
		{
			if (remain() < len)
				return false;
			unsigned char * data = it;
			std::memcpy(data, input, len);
			it = data + len;
			return true;
		}

		bool write_str(char const * input) noexcept
		{
			STRLEN_TYPE slen = static_cast<STRLEN_TYPE>(std::strlen(input));
			std::size_t len = sizeof(slen) + slen;
			if (remain() < len)
				return false;
			unsigned char * data = it;
			std::memcpy(&data[0], &slen, sizeof(slen));
			std::memcpy(&data[sizeof(slen)], input, slen);
			it = data + len;
			return true;
		}

	};

	template<typename STRLEN_TYPE = std::uint32_t>
	class dynamic_writer
	{
		std::vector<unsigned char> block;
	public:
		dynamic_writer()
		{

		}

		dynamic_writer(std::size_t capacity)
		{
			block.reserve(capacity);
		}

		void * data() noexcept
		{
			return block.data();
		}

		std::size_t size() noexcept
		{
			return block.size();
		}

		std::size_t remain() noexcept
		{
			return block.capacity() - block.size();
		}

		template<typename T>
		void write(T const & input)
		{
			block.insert(block.end(),
				reinterpret_cast<unsigned char const *>(&input),
				reinterpret_cast<unsigned char const *>(&input) + sizeof(input));
		}

		void write(void const * input, std::size_t len)
		{
			block.insert(block.end(),
				reinterpret_cast<unsigned char const *>(input),
				reinterpret_cast<unsigned char const *>(input) + len);
		}

		void write_str(char const * input)
		{
			STRLEN_TYPE slen = static_cast<STRLEN_TYPE>(std::strlen(input));
			block.insert(block.end(),
				reinterpret_cast<unsigned char const *>(&slen),
				reinterpret_cast<unsigned char const *>(&slen) + sizeof(slen));
			block.insert(block.end(),
				reinterpret_cast<unsigned char const *>(input),
				reinterpret_cast<unsigned char const *>(input) + slen);
		}
	};

}

  

posted @ 2022-06-11 21:59  ruster  阅读(57)  评论(0)    收藏  举报