Devel Lib
ReadStream.h
1 #pragma once
2 
3 #include "Core/Exceptions.h"
4 #include "IO/Buffer/Buffer.h"
5 #include "Core/CharArray/CharArray.h"
6 
9 namespace Devel::IO {
10  static auto ZeroTerminatedStringException = std::overflow_error("String is not zero terminated!");
11 
37  class CReadStream {
38  public:
42  : m_pBuffer(nullptr), m_nSize(0), m_nPosition(0), m_fDeleteBuffer(false) {
43  this->clear();
44  }
45 
50  CReadStream(const char *i_pBuffer, const size_t i_nSize, const bool i_fCopyBuffer)
51  : CReadStream() {
52  this->setBuffer(i_pBuffer, i_nSize, i_fCopyBuffer);
53  }
54 
57  CReadStream(const CReadStream &i_oOther) {
58  this->operator=(i_oOther);
59  }
60 
63  CReadStream(CReadStream &&i_oOther) noexcept {
64  this->operator=(std::move(i_oOther));
65  }
66 
68  virtual ~CReadStream() = default;
69 
70  private:
74  void deleteBuffer();
75 
76  private:
81  [[nodiscard]] bool checkBuffer() const {
82  if (!this->m_pBuffer) {
83  throw NoBufferException;
84  }
85 
86  return true;
87  }
88 
93  [[nodiscard]] bool checkSize(const size_t i_nPosition, const size_t i_nReadBytes) const {
94  if (this->leftBytes(i_nPosition) < i_nReadBytes) {
95  throw IndexOutOfRangeException;
96  }
97 
98  return true;
99  }
100 
105  [[nodiscard]] bool checkBufferAndSize(const size_t i_nPosition, const size_t i_nReadBytes) const {
106  return this->checkBuffer() && this->checkSize(i_nPosition, i_nReadBytes);
107  }
108 
112  [[nodiscard]] char *bufferPosition(const size_t i_nPosition) const {
113  return const_cast<char *>(this->m_pBuffer + i_nPosition);
114  }
115 
116  public:
121  void setBuffer(const char *i_pBuffer, size_t i_nSize, bool i_fCopyBuffer = false);
122 
125  void setPosition(const size_t i_nPosition) {
126  if (this->m_pBuffer) {
127  this->m_nPosition = i_nPosition > this->m_nSize ? this->m_nSize : i_nPosition;
128  }
129  }
130 
133  void seek(const size_t i_nBytes) {
134  if (i_nBytes > 0) {
135  this->setPosition(this->position() + i_nBytes);
136  }
137  }
138 
140  void clear();
141 
142  public:
145  [[nodiscard]] const char *buffer() const {
146  return this->m_pBuffer;
147  }
148 
151  [[nodiscard]] size_t size() const {
152  return this->m_nSize;
153  }
154 
157  [[nodiscard]] size_t position() const {
158  return this->m_nPosition;
159  }
160 
164  [[nodiscard]] size_t leftBytes(const size_t i_nPosition) const {
165  if (this->m_pBuffer) {
166  return this->m_nSize - i_nPosition;
167  }
168 
169  return 0;
170  }
171 
174  [[nodiscard]] size_t leftBytes() const {
175  return this->leftBytes(this->m_nPosition);
176  }
177 
180  [[nodiscard]] bool isEndOfBuffer() const {
181  return (this->m_nPosition == this->size());
182  }
183 
186  [[nodiscard]] bool isEoB() const {
187  return this->isEndOfBuffer();
188  }
189 
190  private:
199  template<typename TReturnType, typename TType>
200  TReturnType
201  readString(const size_t i_nPosition, size_t i_nLength, bool i_fIsZeroTerminated, const bool i_fSetPosition) {
202  TReturnType sReturn;
203 
204  if (this->checkBuffer()) {
205  if (i_fIsZeroTerminated) {
206  const size_t nLeftBytes = this->leftBytes(i_nPosition);
207  if (nLeftBytes > 0) {
208  // Set to false for check if found
209  i_fIsZeroTerminated = false;
210  i_nLength = 0;
211 
212  sReturn.reserve((nLeftBytes > 20 ? 20 : nLeftBytes));
213 
214  for (; i_nLength < nLeftBytes; i_nLength += sizeof(TType)) {
215  auto *pBufferPosition = reinterpret_cast<TType *>(this->bufferPosition(
216  this->m_nPosition + i_nLength));
217  if (*pBufferPosition != TType(0x00)) {
218  sReturn += *pBufferPosition;
219  } else {
220  i_fIsZeroTerminated = true;
221  break;
222  }
223  }
224 
225  if (!i_fIsZeroTerminated) {
226  throw ZeroTerminatedStringException;
227  }
228  }
229  } else if (i_nLength > 0 && this->checkSize(i_nPosition, i_nLength)) {
230  sReturn = TReturnType(reinterpret_cast<TType *>(this->bufferPosition(i_nPosition)), i_nLength);
231  i_nLength *= sizeof(TType); // For wchar_t (x characters = x * 2 bytes)
232  }
233 
234  if (i_fSetPosition) {
235  this->setPosition(i_nPosition + i_nLength + (i_fIsZeroTerminated * sizeof(TType)));
236  }
237  }
238 
239  return sReturn;
240  }
241 
242  public:
249  std::string getString(const size_t i_nPosition, const size_t i_nLength, const bool i_fIsZeroTerminated,
250  const bool i_fSetPosition) {
251  return this->readString<std::string, char>(i_nPosition, i_nLength, i_fIsZeroTerminated, i_fSetPosition);
252  }
253 
259  std::string getString(const size_t i_nPosition, const size_t i_nLength, const bool i_fSetPosition = true) {
260  return this->getString(i_nPosition, i_nLength, false, i_fSetPosition);
261  }
262 
267  std::string getString(const size_t i_nLength, const bool i_fSetPosition = true) {
268  return this->getString(this->m_nPosition, i_nLength, false, i_fSetPosition);
269  }
270 
274  std::string getString(const bool i_fSetPosition = true) {
275  return this->getString(this->m_nPosition, 0, true, i_fSetPosition);
276  }
277 
278  public:
285  std::wstring getWString(const size_t i_nPosition, const size_t i_nLength, const bool i_fIsZeroTerminated,
286  const bool i_fSetPosition) {
287  return this->readString<std::wstring, wchar_t>(i_nPosition, i_nLength, i_fIsZeroTerminated, i_fSetPosition);
288  }
289 
295  std::wstring getWString(const size_t i_nPosition, const size_t i_nLength, const bool i_fSetPosition = true) {
296  return this->getWString(i_nPosition, i_nLength, false, i_fSetPosition);
297  }
298 
303  std::wstring getWString(const size_t i_nLength, const bool i_fSetPosition = true) {
304  return this->getWString(this->m_nPosition, i_nLength, false, i_fSetPosition);
305  }
306 
310  std::wstring getWString(const bool i_fSetPosition = true) {
311  return this->getWString(this->m_nPosition, 0, true, i_fSetPosition);
312  }
313 
314  public:
320  void getRaw(void *i_pDestination, size_t i_nReadBytes, size_t i_nPosition, bool i_fSetPosition);
321 
326  void getRaw(void *i_pDestination, const size_t i_nReadBytes, const bool i_fSetPosition) {
327  return this->getRaw(i_pDestination, i_nReadBytes, this->m_nPosition, i_fSetPosition);
328  }
329 
333  void getRaw(void *i_pDestination, const size_t i_nReadBytes) {
334  return this->getRaw(i_pDestination, i_nReadBytes, true);
335  }
336 
337  public:
343  template<typename T, typename std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
344  T get(const size_t i_nPosition, const bool i_fSetPosition) {
345  if (this->checkBufferAndSize(i_nPosition, sizeof(T))) {
346  T tReturn = *reinterpret_cast<T *>(this->bufferPosition(i_nPosition));
347 
348  if (i_fSetPosition) {
349  this->setPosition(i_nPosition + sizeof(T));
350  }
351 
352  return tReturn;
353  }
354 
355  throw ShouldNotExecuteException;
356  }
357 
362  template<typename T, typename std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
363  T get(const size_t i_nPosition) {
364  return this->get<T>(this->m_nPosition, true);
365  }
366 
370  template<typename T, typename std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
371  T get() {
372  return this->get<T>(this->m_nPosition);
373  }
374 
379  template<typename T, typename std::enable_if_t<std::is_enum_v<T>> * = nullptr>
380  T get(const size_t i_nPosition) {
381  return static_cast<T>(this->get<std::underlying_type_t<T>>(this->m_nPosition, true));
382  }
383 
387  template<typename T, typename std::enable_if_t<std::is_enum_v<T>> * = nullptr>
388  T get() {
389  return static_cast<T>(this->get<std::underlying_type_t<T>>(this->m_nPosition));
390  }
391 
392  public:
398  template<size_t TSize>
399  CCharArray<TSize> getArray(const size_t i_nPosition, const bool i_fSetPosition) {
400  CCharArray<TSize> oBuffer;
401 
402  this->getRaw(oBuffer.begin(), TSize, i_nPosition, i_fSetPosition);
403 
404  return oBuffer;
405  }
406 
410  template<size_t TSize>
412  return this->getArray<TSize>(this->m_nPosition, true);
413  }
414 
415  public:
419  const char &operator[](const size_t i_nIndex) const {
420  if (this->checkBufferAndSize(i_nIndex, 1)) {
421  return this->m_pBuffer[i_nIndex];
422  }
423 
424  throw ShouldNotExecuteException;
425  }
426 
430  CReadStream &operator=(const CReadStream &i_oOther) {
431  this->setBuffer(i_oOther.m_pBuffer, i_oOther.m_nSize, true);
432 
433  this->m_nPosition = i_oOther.m_nPosition;
434  this->m_fDeleteBuffer = i_oOther.m_fDeleteBuffer;
435 
436  return *this;
437  }
438 
442  CReadStream &operator=(CReadStream &&i_oOther) noexcept {
443  this->m_pBuffer = i_oOther.m_pBuffer;
444  this->m_nSize = i_oOther.m_nSize;
445  this->m_nPosition = i_oOther.m_nPosition;
446  this->m_fDeleteBuffer = i_oOther.m_fDeleteBuffer;
447 
448  i_oOther.m_fDeleteBuffer = false;
449  i_oOther.clear();
450 
451  return *this;
452  }
453 
454  private:
457  const char *m_pBuffer{};
458 
461  size_t m_nSize{};
462 
465  size_t m_nPosition{};
466 
469  bool m_fDeleteBuffer{};
470  };
471 }
A class for representing and manipulating a character array.
Definition: CharArray.h:41
char * begin()
Definition: CharArray.h:122
A class for reading data from a buffer. This class provides functionality to read data from a buffer....
Definition: ReadStream.h:37
CReadStream(const char *i_pBuffer, const size_t i_nSize, const bool i_fCopyBuffer)
Constructor for CReadStream with a buffer.
Definition: ReadStream.h:50
std::wstring getWString(const size_t i_nPosition, const size_t i_nLength, const bool i_fSetPosition=true)
Reads a wide string from the buffer.
Definition: ReadStream.h:295
size_t leftBytes() const
Returns the number of bytes left from the current position to the end of the buffer.
Definition: ReadStream.h:174
std::string getString(const size_t i_nPosition, const size_t i_nLength, const bool i_fSetPosition=true)
Reads a string from the buffer.
Definition: ReadStream.h:259
void getRaw(void *i_pDestination, size_t i_nReadBytes, size_t i_nPosition, bool i_fSetPosition)
Reads raw data from the buffer.
Definition: ReadStream.cpp:38
void setBuffer(const char *i_pBuffer, size_t i_nSize, bool i_fCopyBuffer=false)
Sets the buffer for the CReadStream.
Definition: ReadStream.cpp:20
const char & operator[](const size_t i_nIndex) const
Overload of the subscript operator.
Definition: ReadStream.h:419
void setPosition(const size_t i_nPosition)
Sets the current position of the CReadStream.
Definition: ReadStream.h:125
std::string getString(const bool i_fSetPosition=true)
Reads a null-terminated string from the buffer.
Definition: ReadStream.h:274
std::wstring getWString(const size_t i_nPosition, const size_t i_nLength, const bool i_fIsZeroTerminated, const bool i_fSetPosition)
Reads a wide string from the buffer.
Definition: ReadStream.h:285
bool isEndOfBuffer() const
Checks if the current position is at the end of the buffer.
Definition: ReadStream.h:180
CReadStream & operator=(CReadStream &&i_oOther) noexcept
Move assignment operator.
Definition: ReadStream.h:442
size_t position() const
Returns the current position of the CReadStream.
Definition: ReadStream.h:157
size_t size() const
Returns the size of the buffer.
Definition: ReadStream.h:151
CReadStream & operator=(const CReadStream &i_oOther)
Assignment operator.
Definition: ReadStream.h:430
CCharArray< TSize > getArray(const size_t i_nPosition, const bool i_fSetPosition)
Reads an array from the buffer.
Definition: ReadStream.h:399
CCharArray< TSize > getArray()
Reads an array from the buffer.
Definition: ReadStream.h:411
CReadStream(CReadStream &&i_oOther) noexcept
Move constructor for CReadStream.
Definition: ReadStream.h:63
T get(const size_t i_nPosition)
Reads a value of type T from the buffer.
Definition: ReadStream.h:363
size_t leftBytes(const size_t i_nPosition) const
Returns the number of bytes left from the current position to the end of the buffer.
Definition: ReadStream.h:164
std::wstring getWString(const size_t i_nLength, const bool i_fSetPosition=true)
Reads a wide string from the buffer.
Definition: ReadStream.h:303
T get()
Reads a value of type T from the buffer.
Definition: ReadStream.h:371
void getRaw(void *i_pDestination, const size_t i_nReadBytes, const bool i_fSetPosition)
Reads raw data from the buffer.
Definition: ReadStream.h:326
void clear()
Clears the CReadStream.
Definition: ReadStream.cpp:12
void seek(const size_t i_nBytes)
Moves the current position of the CReadStream.
Definition: ReadStream.h:133
void getRaw(void *i_pDestination, const size_t i_nReadBytes)
Reads raw data from the buffer.
Definition: ReadStream.h:333
virtual ~CReadStream()=default
Destructor for CReadStream.
const char * buffer() const
Returns the buffer of the CReadStream.
Definition: ReadStream.h:145
std::string getString(const size_t i_nLength, const bool i_fSetPosition=true)
Reads a string from the buffer.
Definition: ReadStream.h:267
std::string getString(const size_t i_nPosition, const size_t i_nLength, const bool i_fIsZeroTerminated, const bool i_fSetPosition)
Reads a string from the buffer.
Definition: ReadStream.h:249
bool isEoB() const
Checks if the current position is at the end of the buffer.
Definition: ReadStream.h:186
CReadStream(const CReadStream &i_oOther)
Copy constructor for CReadStream.
Definition: ReadStream.h:57
T get(const size_t i_nPosition, const bool i_fSetPosition)
Reads a value of type T from the buffer.
Definition: ReadStream.h:344
std::wstring getWString(const bool i_fSetPosition=true)
Reads a null-terminated wide string from the buffer.
Definition: ReadStream.h:310
CReadStream()
Default constructor for CReadStream.
Definition: ReadStream.h:41
The namespace encapsulating I/O related classes and functions in the Devel framework.