/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2015-2020 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** * * @modified 2026 Tom Clay * Modified for rexglue - Xbox 360 recompilation framework * * @changes - Consolidated bit.h and byte.h into single header */ #pragma once #include #include #include #include namespace rex::stream { //============================================================================= // BitStream - Bit-level stream operations //============================================================================= class BitStream { public: BitStream(uint8_t* buffer, size_t size_in_bits); ~BitStream(); const uint8_t* buffer() const { return buffer_; } uint8_t* buffer() { return buffer_; } size_t offset_bits() const { return offset_bits_; } size_t size_bits() const { return size_bits_; } void Advance(size_t num_bits); void SetOffset(size_t offset_bits); size_t BitsRemaining(); // Note: num_bits MUST be in the range 0-57 (inclusive) uint64_t Peek(size_t num_bits); uint64_t Read(size_t num_bits); bool Write(uint64_t val, size_t num_bits); // TODO(DrChat): Not tested! size_t Copy(uint8_t* dest_buffer, size_t num_bits); private: uint8_t* buffer_ = nullptr; size_t offset_bits_ = 0; size_t size_bits_ = 0; }; //============================================================================= // ByteStream - Byte-level stream operations //============================================================================= class ByteStream { public: ByteStream(uint8_t* data, size_t data_length, size_t offset = 0); ~ByteStream(); void Advance(size_t num_bytes); void Read(std::span buf); void Write(std::span buf); // Convenience overloads for void* (legacy compatibility) void Read(void* buf, size_t len) { return Read(std::span(reinterpret_cast(buf), len)); } void Write(const void* buf, size_t len) { return Write(std::span(reinterpret_cast(buf), len)); } const uint8_t* data() const { return data_; } uint8_t* data() { return data_; } size_t data_length() const { return data_length_; } size_t offset() const { return offset_; } void set_offset(size_t offset) { offset_ = offset; } template T Read() { T data; Read(std::span(reinterpret_cast(&data), sizeof(T))); return data; } template void Write(T data) { Write(std::span(reinterpret_cast(&data), sizeof(T))); } void Write(const std::string_view str) { Write(uint32_t(str.length())); Write(str.data(), str.length() * sizeof(char)); } void Write(const std::u16string_view str) { Write(uint32_t(str.length())); Write(str.data(), str.length() * sizeof(char16_t)); } private: uint8_t* data_ = nullptr; size_t data_length_ = 0; size_t offset_ = 0; }; template <> std::string ByteStream::Read(); template <> std::u16string ByteStream::Read(); } // namespace rex::stream