Mercurial > minori
diff include/core/byte_stream.h @ 364:99c961c91809
core: refactor out byte stream into its own file
easy dubs
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Tue, 16 Jul 2024 21:15:59 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/core/byte_stream.h Tue Jul 16 21:15:59 2024 -0400 @@ -0,0 +1,75 @@ +#ifndef MINORI_CORE_BYTE_STREAM_H_ +#define MINORI_CORE_BYTE_STREAM_H_ + +#include "core/endian.h" + +#include <string> +#include <vector> +#include <cstdint> +#include <type_traits> + +struct ByteStream { +public: + enum class ByteOrder { + Little, + Big, + }; + + ByteStream(std::uint8_t *bytes, std::size_t size); + + void ResetOffset(); + void SetEndianness(ByteOrder endian); + + template<typename T> + bool ReadBinary(T& ret) { + if (offset_ + sizeof(T) >= size_) + return false; + + ret = *reinterpret_cast<T*>(bytes_ + offset_); + Advance(sizeof(T)); + return true; + } + + template<typename T> + bool ReadInt(T& ret) { + static_assert(std::is_integral<T>::value); + + if (!ReadBinary<T>(ret)) + return false; + + switch (endian_) { + case ByteOrder::Little: + if constexpr (std::is_unsigned<T>::value) { + ret = Endian::byteswap_little_to_host(ret); + } else { + ret = Endian::signed_byteswap_little_to_host(ret); + } + break; + case ByteOrder::Big: + if constexpr (std::is_unsigned<T>::value) { + ret = Endian::byteswap_big_to_host(ret); + } else { + ret = Endian::signed_byteswap_big_to_host(ret); + } + break; + default: + /* can't know for sure. punt */ + return false; + } + + return true; + } + + bool ReadString(std::string& str, std::size_t size); + bool Advance(std::size_t amount); + +private: + /* raw data */ + std::uint8_t *bytes_ = nullptr; + std::size_t offset_ = 0; + std::size_t size_ = 0; + + ByteOrder endian_ = ByteOrder::Little; +}; + +#endif /* MINORI_CORE_BYTE_STREAM_H_ */