view 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 source

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