Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
ByteBuffer.h
Go to the documentation of this file.
1#pragma once
2
3#include "Utility/TSpan.h"
4
5#include <Common/assertion.h>
6
7#include <vector>
8#include <cstddef>
9#include <algorithm>
10#include <iterator>
11
12namespace ph
13{
14
17class ByteBuffer final
18{
19public:
20 ByteBuffer();
21 explicit ByteBuffer(std::size_t numExpectedWrittenBytes);
22
23 template<typename T>
24 T read();
25
26 template<typename T>
27 void read(T* out_data, std::size_t numElements);
28
31 template<typename T>
32 void write(const T& data);
33
36 template<typename T>
37 void write(const T* data, std::size_t numElements);
38
39 void rewindRead();
40 void rewindWrite();
41
44 void clear();
45
46 void fill(std::byte filledByte);
47 void truncate();
48 void fit();
49 void setReadPosition(std::size_t indexOfByte);
50 void setWritePosition(std::size_t indexOfByte);
51 void setNumBytes(std::size_t numBytes);
52
56 std::size_t getReadPosition() const;
57
61 std::size_t getWritePosition() const;
62
69
70 std::size_t numBytes() const;
71 bool isEmpty() const;
72 bool hasMoreToRead() const;
73
74private:
75 std::vector<std::byte> m_buffer;
76 std::size_t m_readHead;
77 std::size_t m_writeHead;
78};
79
80// In-header Implementations:
81
83 m_buffer(),
84 m_readHead(0),
85 m_writeHead(0)
86{}
87
88inline ByteBuffer::ByteBuffer(std::size_t numExpectedWrittenBytes) :
89 m_buffer(),
90 m_readHead(0),
91 m_writeHead(0)
92{
93 m_buffer.reserve(numExpectedWrittenBytes);
94}
95
96template<typename T>
98{
99 T data;
100 read(&data, 1);
101 return data;
102}
103
104template<typename T>
105inline void ByteBuffer::read(T* const out_data, const std::size_t numElements)
106{
107 static_assert(std::is_trivially_copyable_v<T>,
108 "reading the type from ByteBuffer is not allowed");
109
110 PH_ASSERT(out_data);
111 PH_ASSERT_LE(m_readHead, m_buffer.size());
112
113 const std::size_t numRemainingBytes = m_buffer.size() - m_readHead;
114 const std::size_t numDataBytes = std::min(sizeof(T) * numElements, numRemainingBytes);
115
116 std::copy_n(
117 m_buffer.data() + m_readHead,
118 numDataBytes,
119 reinterpret_cast<std::byte*>(out_data));
120
121 m_readHead += numDataBytes;
122
123 PH_ASSERT_LE(m_readHead, m_buffer.size());
124}
125
126template<typename T>
127inline void ByteBuffer::write(const T& data)
128{
129 write(&data, 1);
130}
131
132template<typename T>
133inline void ByteBuffer::write(const T* const data, const std::size_t numElements)
134{
135 static_assert(std::is_trivially_copyable_v<T>,
136 "writing the type into ByteBuffer is not allowed");
137
138 PH_ASSERT(data);
139 PH_ASSERT_LE(m_writeHead, m_buffer.size());
140
141 const std::size_t numDataBytes = sizeof(T) * numElements;
142 const std::size_t numAvailableBytes = m_buffer.size() - m_writeHead;
143
144 // Existing space is enough for writing
145 if(numAvailableBytes >= numDataBytes)
146 {
147 std::copy_n(
148 reinterpret_cast<const std::byte*>(data),
149 numDataBytes,
150 m_buffer.data() + m_writeHead);
151 }
152 else
153 {
154 // So existing space is not enough
155
156 const std::size_t numShortedBytes = numDataBytes - numAvailableBytes;
157
158 // First copy into what we have left
159 std::copy_n(
160 reinterpret_cast<const std::byte*>(data),
161 numAvailableBytes,
162 m_buffer.data() + m_writeHead);
163
164 // Then copy remaining bytes into the buffer (and let the buffer grow by itself)
165 m_buffer.insert(
166 m_buffer.end(),
167 reinterpret_cast<const std::byte*>(data) + numAvailableBytes,
168 reinterpret_cast<const std::byte*>(data) + numDataBytes);
169 }
170
171 m_writeHead += numDataBytes;
172
173 PH_ASSERT_LE(m_writeHead, m_buffer.size());
174}
175
177{
178 m_readHead = 0;
179}
180
182{
183 m_writeHead = 0;
184}
185
186inline void ByteBuffer::clear()
187{
188 m_buffer.clear();
189
190 rewindRead();
191 rewindWrite();
192}
193
194inline void ByteBuffer::fill(const std::byte filledByte)
195{
196 std::fill(m_buffer.begin(), m_buffer.end(), filledByte);
197
198 m_writeHead = m_buffer.size();
199}
200
202{
203 PH_ASSERT_LE(m_writeHead, m_buffer.size());
204
205 m_buffer.resize(m_writeHead);
206
207 if(m_readHead > m_writeHead)
208 {
209 setReadPosition(m_writeHead);
210 }
211}
212
213inline void ByteBuffer::fit()
214{
215 m_buffer.shrink_to_fit();
216}
217
218inline void ByteBuffer::setReadPosition(const std::size_t indexOfByte)
219{
220 PH_ASSERT_LE(indexOfByte, m_buffer.size());
221
222 m_readHead = indexOfByte;
223}
224
225inline void ByteBuffer::setWritePosition(const std::size_t indexOfByte)
226{
227 PH_ASSERT_LE(indexOfByte, m_buffer.size());
228
229 m_writeHead = indexOfByte;
230}
231
232inline void ByteBuffer::setNumBytes(const std::size_t numBytes)
233{
234 m_buffer.resize(numBytes);
235
236 if(m_writeHead > numBytes)
237 {
239 }
240
241 if(m_readHead > numBytes)
242 {
244 }
245}
246
247inline std::size_t ByteBuffer::getReadPosition() const
248{
249 return m_readHead;
250}
251
252inline std::size_t ByteBuffer::getWritePosition() const
253{
254 return m_writeHead;
255}
256
258{
259 return m_buffer;
260}
261
263{
264 return m_buffer;
265}
266
267inline std::size_t ByteBuffer::numBytes() const
268{
269 return m_buffer.size();
270}
271
272inline bool ByteBuffer::isEmpty() const
273{
274 return m_buffer.empty();
275}
276
277inline bool ByteBuffer::hasMoreToRead() const
278{
279 return getReadPosition() < numBytes();
280}
281
282}// end namespace ph
An auto-resizable byte storage.
Definition ByteBuffer.h:18
void rewindWrite()
Definition ByteBuffer.h:181
TSpan< std::byte > getBytes()
Direct access to all the bytes in the buffer.
Definition ByteBuffer.h:257
std::size_t getReadPosition() const
Definition ByteBuffer.h:247
bool hasMoreToRead() const
Definition ByteBuffer.h:277
bool isEmpty() const
Definition ByteBuffer.h:272
void write(const T &data)
Writes data to the buffer. Grows the buffer if no space left.
Definition ByteBuffer.h:127
void truncate()
Definition ByteBuffer.h:201
ByteBuffer()
Definition ByteBuffer.h:82
T read()
Definition ByteBuffer.h:97
void setReadPosition(std::size_t indexOfByte)
Definition ByteBuffer.h:218
void setNumBytes(std::size_t numBytes)
Definition ByteBuffer.h:232
std::size_t getWritePosition() const
Definition ByteBuffer.h:252
void clear()
Clear all data and reset reader and writer positions.
Definition ByteBuffer.h:186
void rewindRead()
Definition ByteBuffer.h:176
void fit()
Definition ByteBuffer.h:213
std::size_t numBytes() const
Definition ByteBuffer.h:267
void fill(std::byte filledByte)
Definition ByteBuffer.h:194
void setWritePosition(std::size_t indexOfByte)
Definition ByteBuffer.h:225
The root for all renderer implementations.
Definition EEngineProject.h:6
std::span< const T, EXTENT > TSpanView
Same as TSpan, except that the objects are const-qualified. Note that for pointer types,...
Definition TSpan.h:19
std::span< T, EXTENT > TSpan
A contiguous sequence of objects of type T. Effectively the same as std::span.
Definition TSpan.h:12