ReXGlue SDK
Loading...
Searching...
No Matches
stream.h
Go to the documentation of this file.
1
14
15#pragma once
16
17#include <cstddef>
18#include <cstdint>
19#include <span>
20#include <string>
21#include <type_traits>
22#include <vector>
23
24#include <rex/assert.h>
25#include <rex/memory/endian.h>
26#include <rex/platform.h>
27#include <rex/types.h>
28
29namespace rex::memory {
30
33 public:
39 BitStream(u8* buffer, size_t size_in_bits);
40 ~BitStream() = default;
41
42 const u8* GetBuffer() const { return buffer_; }
43
44 u8* GetBuffer() { return buffer_; }
45
46 size_t GetOffsetBits() const { return offset_bits_; }
47
48 size_t GetSizeBits() const { return size_bits_; }
49
50 void Advance(size_t num_bits);
51
53 void SetOffset(size_t offset_bits);
54
55 size_t GetBitsRemaining() const;
56
63 u64 Peek(size_t num_bits);
64
71 u64 Read(size_t num_bits);
72
79 bool Write(u64 val, size_t num_bits);
80
86 size_t Copy(u8* dest_buffer, size_t num_bits);
87
88 private:
89 u8* buffer_ = nullptr;
90 size_t offset_bits_ = 0;
91 size_t size_bits_ = 0;
92};
93
96 public:
102 ByteStream(u8* data, size_t data_length, size_t offset = 0);
103 ~ByteStream() = default;
104
105 void Advance(size_t num_bytes);
106
112 void Read(std::span<u8> buf);
113
119 void Write(std::span<const u8> buf);
120
122 void Read(void* buf, size_t len) { return Read(std::span<u8>(reinterpret_cast<u8*>(buf), len)); }
123
125 void Write(const void* buf, size_t len) {
126 return Write(std::span<const u8>(reinterpret_cast<const u8*>(buf), len));
127 }
128
129 const u8* GetData() const { return data_; }
130
131 u8* GetData() { return data_; }
132
133 size_t GetSize() const { return data_length_; }
134
135 size_t GetOffset() const { return offset_; }
136
137 void SetOffset(size_t offset) { offset_ = offset; }
138
144 template <typename T>
145 T Read() {
146 T data;
147 Read(std::span<u8>(reinterpret_cast<u8*>(&data), sizeof(T)));
148 return data;
149 }
150
152 template <typename T>
153 void Write(T data) {
154 Write(std::span<const u8>(reinterpret_cast<const u8*>(&data), sizeof(T)));
155 }
156
158 void Write(const std::string_view str) {
159 Write(static_cast<u32>(str.length()));
160 Write(str.data(), str.length() * sizeof(char));
161 }
162
164 void Write(const std::u16string_view str) {
165 Write(static_cast<u32>(str.length()));
166 Write(str.data(), str.length() * sizeof(char16_t));
167 }
168
169 private:
170 u8* data_ = nullptr;
171 size_t data_length_ = 0;
172 size_t offset_ = 0;
173};
174
176template <>
178
180template <>
181REX_API std::u16string ByteStream::Read();
182
183using RingSizeT = u32;
184
189class REX_API RingBuffer {
190 public:
191 RingBuffer(u8* buffer, size_t capacity);
192
193 u8* GetBuffer() const { return buffer_; }
194
195 RingSizeT GetCapacity() const { return capacity_; }
196
202 bool IsEmpty() const { return read_offset_ == write_offset_; }
203
204 RingSizeT GetReadOffset() const { return read_offset_; }
205
207 uintptr_t GetReadPtr() const {
208 return reinterpret_cast<uintptr_t>(buffer_) + static_cast<uintptr_t>(read_offset_);
209 }
210
216 void SetReadOffset(size_t offset) { read_offset_ = static_cast<RingSizeT>(offset) % capacity_; }
217
219 RingSizeT GetReadCount() const {
220 RingSizeT read_offs = read_offset_;
221 RingSizeT write_offs = write_offset_;
222 RingSizeT cap = capacity_;
223 if (read_offs <= write_offs) {
224 return write_offs - read_offs;
225 } else {
226 return (cap - read_offs) + write_offs;
227 }
228 }
229
230 RingSizeT GetWriteOffset() const { return write_offset_; }
231
233 uintptr_t GetWritePtr() const {
234 return reinterpret_cast<uintptr_t>(buffer_) + static_cast<uintptr_t>(write_offset_);
235 }
236
242 void SetWriteOffset(size_t offset) { write_offset_ = static_cast<RingSizeT>(offset) % capacity_; }
243
248 RingSizeT GetWriteCount() const {
249 RingSizeT read_offs = read_offset_;
250 RingSizeT write_offs = write_offset_;
251 RingSizeT cap = capacity_;
252 if (read_offs == write_offs) {
253 return cap;
254 } else if (write_offs < read_offs) {
255 return read_offs - write_offs;
256 } else {
257 return (cap - write_offs) + read_offs;
258 }
259 }
260
262 void AdvanceRead(size_t count);
263
265 void AdvanceWrite(size_t count);
266
268 struct ReadRange {
269 const u8* __restrict first;
270 const u8* __restrict second;
271 RingSizeT first_length;
272 RingSizeT second_length;
273 };
274
280 ReadRange BeginRead(size_t count);
281
287 void EndRead(ReadRange read_range);
288
295 size_t Read(u8* buffer, size_t count);
296
303 template <typename T>
304 size_t Read(T* buffer, size_t count) {
305 return Read(reinterpret_cast<u8*>(buffer), count);
306 }
307
309 template <typename T>
310 T Read() {
311 static_assert(std::is_fundamental<T>::value, "Immediate read only supports basic types!");
312
313 T imm;
314 size_t read = Read(reinterpret_cast<u8*>(&imm), sizeof(T));
315 REX_ASSERT(read == sizeof(T));
316 return imm;
317 }
318
320 template <typename T>
322 static_assert(std::is_fundamental<T>::value, "Immediate read only supports basic types!");
323
324 T imm;
325 size_t read = Read(reinterpret_cast<u8*>(&imm), sizeof(T));
326 REX_ASSERT(read == sizeof(T));
327 imm = rex::byte_swap(imm);
328 return imm;
329 }
330
337 size_t Write(const u8* buffer, size_t count);
338
345 template <typename T>
346 size_t Write(const T* buffer, size_t count) {
347 return Write(reinterpret_cast<const u8*>(buffer), count);
348 }
349
355 template <typename T>
356 size_t Write(T& data) {
357 return Write(reinterpret_cast<const u8*>(&data), sizeof(T));
358 }
359
360 private:
361 u8* __restrict buffer_ = nullptr;
362 RingSizeT capacity_ = 0;
363 RingSizeT read_offset_ = 0;
364 RingSizeT write_offset_ = 0;
365};
366
368template <>
370 REX_ASSERT(capacity_ >= 4);
371 RingSizeT read_offs = read_offset_;
372 RingSizeT next_read_offs = read_offs + 4;
373 if (next_read_offs == capacity_) [[unlikely]] {
374 next_read_offs = 0;
375 }
376 read_offset_ = next_read_offs;
377 return memory::load<be_u32>(buffer_ + read_offs);
378}
379
380} // namespace rex::memory
#define REX_ASSERT(cond,...)
Definition assert.h:84
bool Write(u64 val, size_t num_bits)
u64 Read(size_t num_bits)
size_t Copy(u8 *dest_buffer, size_t num_bits)
u64 Peek(size_t num_bits)
void SetOffset(size_t offset_bits)
BitStream(u8 *buffer, size_t size_in_bits)
void Write(std::span< const u8 > buf)
void Write(T data)
Definition stream.h:153
ByteStream(u8 *data, size_t data_length, size_t offset=0)
void Read(std::span< u8 > buf)
void Write(const std::string_view str)
Definition stream.h:158
void Write(const void *buf, size_t len)
Definition stream.h:125
void Write(const std::u16string_view str)
Definition stream.h:164
T Read()
Definition stream.h:145
void Read(void *buf, size_t len)
Definition stream.h:122
size_t Write(const u8 *buffer, size_t count)
size_t Write(const T *buffer, size_t count)
Definition stream.h:346
void AdvanceWrite(size_t count)
T Read()
Definition stream.h:310
RingSizeT GetReadCount() const
Definition stream.h:219
void AdvanceRead(size_t count)
size_t Write(T &data)
Definition stream.h:356
RingSizeT GetWriteCount() const
Definition stream.h:248
T ReadAndSwap()
Definition stream.h:321
bool IsEmpty() const
Definition stream.h:202
ReadRange BeginRead(size_t count)
size_t Read(T *buffer, size_t count)
Definition stream.h:304
void EndRead(ReadRange read_range)
size_t Read(u8 *buffer, size_t count)
void SetReadOffset(size_t offset)
Definition stream.h:216
void SetWriteOffset(size_t offset)
Definition stream.h:242
uintptr_t GetWritePtr() const
Definition stream.h:233
uintptr_t GetReadPtr() const
Definition stream.h:207
Definition endian.h:27
T load(const void *mem)
Definition endian.h:134
constexpr T byte_swap(T value) noexcept
Definition types.h:52
Platform flags, packing macros and export markers.
#define REX_API
Definition platform.h:177
Definition stream.h:268
const u8 *__restrict second
Definition stream.h:270
const u8 *__restrict first
Definition stream.h:269
Integer types, byte order wrappers and size literals.