Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
ByteBufferInputStream.h
Go to the documentation of this file.
1#pragma once
2
4
5#include <Common/assertion.h>
6#include <Common/io_exceptions.h>
7
8#include <cstddef>
9#include <memory>
10#include <type_traits>
11#include <algorithm>
12#include <format>
13
14namespace ph
15{
16
20{
21public:
23 ByteBufferInputStream(const std::byte* srcByteBuffer, std::size_t numBytes);
24 ByteBufferInputStream(const char* srcCharBuffer, std::size_t numChars);
25 ByteBufferInputStream(const unsigned char* srcUCharBuffer, std::size_t numUChars);
26 explicit ByteBufferInputStream(std::size_t numBytes);
28
29 void read(std::size_t numBytes, std::byte* out_bytes) override;
30 void readString(std::string* out_string, char delimiter) override;
31 void seekGet(std::size_t pos) override;
32 std::optional<std::size_t> tellGet() override;
33 operator bool () const override;
34 std::size_t readSome(std::size_t numBytes, std::byte* out_bytes) override;
35
36 template<typename T>
37 void readData(T* out_data);
38
41 std::size_t numBufferBytes() const;
42
46 std::byte* byteBuffer();
47 const std::byte* byteBuffer() const;
49
56 char* charBuffer();
57 const char* charBuffer() const;
58 unsigned char* ucharBuffer();
59 const unsigned char* ucharBuffer() const;
61
64 bool canRead(std::size_t numBytes) const;
65
68 bool canRead() const;
69
71
72private:
73 std::unique_ptr<std::byte[]> m_byteBuffer;
74 std::size_t m_numBytes;
75 std::size_t m_readHead;
76};
77
78// In-header Implementations:
79
80inline void ByteBufferInputStream::read(const std::size_t numBytes, std::byte* const out_bytes)
81{
82 PH_ASSERT(out_bytes);
83
84 if(canRead(numBytes))
85 {
86 PH_ASSERT_LT(m_readHead, numBufferBytes());
87 PH_ASSERT_LE(m_readHead + numBytes, numBufferBytes());
88
89 std::copy(
90 byteBuffer() + m_readHead,
91 byteBuffer() + m_readHead + numBytes,
92 out_bytes);
93
94 m_readHead += numBytes;
95 }
96 else
97 {
98 throw IOException(std::format(
99 "Attempt to read bytes in [{}, {}) which overflows [{}, {}).",
100 m_readHead, m_readHead + numBytes, m_readHead, numBufferBytes()));
101 }
102}
103
104inline void ByteBufferInputStream::readString(std::string* const out_string, const char delimiter)
105{
106 PH_ASSERT(out_string);
107
108 if(canRead())
109 {
110 PH_ASSERT_LT(m_readHead, numBufferBytes());
111
112 const char* const charBufferView = charBuffer();
113
114 const std::size_t beginIdx = m_readHead;
115 for(; m_readHead < numBufferBytes(); ++m_readHead)
116 {
117 if(charBufferView[m_readHead] == delimiter)
118 {
119 ++m_readHead;
120 break;
121 }
122 }
123 // <m_readHead> is on either one past delimiter or buffer size after the loop
124
125 PH_ASSERT_LT(beginIdx, m_readHead);
126
127 out_string->clear();
128
129 // Ternary for not to include the delimiter in the output string
130 const auto numChars = m_readHead < numBufferBytes() ? m_readHead - 1 - beginIdx : m_readHead - beginIdx;
131 out_string->append(
132 &(charBufferView[beginIdx]),
133 numChars);
134 }
135 else
136 {
137 throw IOException(std::format(
138 "Attempt to read a string with delimiter {} from buffer range [{}, {}).",
139 delimiter, m_readHead, numBufferBytes()));
140 }
141}
142
143inline void ByteBufferInputStream::seekGet(const std::size_t pos)
144{
145 if(pos < numBufferBytes())
146 {
147 m_readHead = pos;
148 }
149 else
150 {
151 throw IOException(std::format(
152 "Attempt to seek to read position {} which overflows [0, {}).",
153 pos, numBufferBytes()));
154 }
155}
156
157inline std::optional<std::size_t> ByteBufferInputStream::tellGet()
158{
159 return m_readHead;
160}
161
162inline std::size_t ByteBufferInputStream::readSome(const std::size_t numBytes, std::byte* const out_bytes)
163{
164 PH_ASSERT(out_bytes);
165
166 if(canRead(numBytes))
167 {
168 read(numBytes, out_bytes);
169 return numBytes;
170 }
171 else
172 {
173 PH_ASSERT_LE(m_readHead, numBufferBytes());
174 const auto numRemainingBytes = numBufferBytes() - m_readHead;
175
176 PH_ASSERT_LT(numRemainingBytes, numBytes);
177 read(numRemainingBytes, out_bytes);
178 return numRemainingBytes;
179 }
180}
181
182inline bool ByteBufferInputStream::canRead(const std::size_t numBytes) const
183{
184 PH_ASSERT(
185 m_byteBuffer ||
186 (!m_byteBuffer && m_readHead == 0 && numBufferBytes() == 0));
187
188 // For empty buffer, the only allowed <numBytes> to read is 0
189 return m_readHead + numBytes <= numBufferBytes();
190}
191
193{
194 PH_ASSERT(
195 m_byteBuffer ||
196 (!m_byteBuffer && m_readHead == 0 && numBufferBytes() == 0));
197
198 // For empty buffer, both <m_readHead> and <numBufferBytes()> should be 0 which results in `false`
199 return m_readHead < numBufferBytes();
200}
201
202inline ByteBufferInputStream::operator bool () const
203{
204 return canRead();
205}
206
207template<typename T>
208inline void ByteBufferInputStream::readData(T* const out_data)
209{
210 static_assert(std::is_trivially_copyable_v<T>);
211 PH_ASSERT(out_data);
212
213 read(sizeof(T), reinterpret_cast<std::byte*>(out_data));
214}
215
217{
218 return m_numBytes;
219}
220
222{
223 PH_ASSERT(m_byteBuffer);
224 return m_byteBuffer.get();
225}
226
227inline const std::byte* ByteBufferInputStream::byteBuffer() const
228{
229 PH_ASSERT(m_byteBuffer);
230 return m_byteBuffer.get();
231}
232
234{
235 return reinterpret_cast<char*>(byteBuffer());
236}
237
238inline const char* ByteBufferInputStream::charBuffer() const
239{
240 return reinterpret_cast<const char*>(byteBuffer());
241}
242
244{
245 return reinterpret_cast<unsigned char*>(byteBuffer());
246}
247
248inline const unsigned char* ByteBufferInputStream::ucharBuffer() const
249{
250 return reinterpret_cast<const unsigned char*>(byteBuffer());
251}
252
253}// end namespace ph
An in-memory byte stream designed for I/O performance.
Definition ByteBufferInputStream.h:20
std::byte * byteBuffer()
Direct access to the underlying byte buffer.
Definition ByteBufferInputStream.h:221
std::optional< std::size_t > tellGet() override
Get the current input position of the stream. The unit of the position is defined by the implementati...
Definition ByteBufferInputStream.h:157
char * charBuffer()
Definition ByteBufferInputStream.h:233
void readString(std::string *out_string, char delimiter) override
Read a string in one go. Note the EOF is also considered a delimiter (the final one).
Definition ByteBufferInputStream.h:104
void seekGet(std::size_t pos) override
Set the input position of the stream. The unit of the position is defined by the implementation.
Definition ByteBufferInputStream.h:143
ByteBufferInputStream()
Definition ByteBufferInputStream.cpp:6
std::size_t numBufferBytes() const
Get the size of the underlying byte buffer.
Definition ByteBufferInputStream.h:216
ByteBufferInputStream(ByteBufferInputStream &&other)=default
ByteBufferInputStream & operator=(ByteBufferInputStream &&rhs)=default
void read(std::size_t numBytes, std::byte *out_bytes) override
Read specific number of raw bytes in one go. The method does not return before finishing the reading ...
Definition ByteBufferInputStream.h:80
unsigned char * ucharBuffer()
Definition ByteBufferInputStream.h:243
std::size_t readSome(std::size_t numBytes, std::byte *out_bytes) override
Read some data in the form of raw bytes. The method may return before finish reading all bytes....
Definition ByteBufferInputStream.h:162
void readData(T *out_data)
Definition ByteBufferInputStream.h:208
bool canRead() const
Whether we can read any number (non-zero) of bytes from the stream.
Definition ByteBufferInputStream.h:192
Definition IInputStream.h:13
The root for all renderer implementations.
Definition EEngineProject.h:6