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_ */