C++ Utilities  4.17.0
Useful C++ classes and routines such as argument parser, IO and conversion utilities
binaryreader.cpp
Go to the documentation of this file.
1 #include "./binaryreader.h"
2 
3 #include "../conversion/conversionexception.h"
4 
5 #include <cstring>
6 #include <memory>
7 #include <sstream>
8 
9 using namespace std;
10 using namespace IoUtilities;
11 using namespace ConversionUtilities;
12 
29 BinaryReader::BinaryReader(istream *stream)
30  : m_stream(stream)
31  , m_ownership(false)
32 {
33 }
34 
40  : m_stream(other.m_stream)
41  , m_ownership(false)
42 {
43 }
44 
49 {
50  if (m_ownership) {
51  delete m_stream;
52  }
53 }
54 
66 void BinaryReader::setStream(istream *stream, bool giveOwnership)
67 {
68  if (m_ownership) {
69  delete m_stream;
70  }
71  if (stream) {
72  m_stream = stream;
73  m_ownership = giveOwnership;
74  } else {
75  m_stream = nullptr;
76  m_ownership = false;
77  }
78 }
79 
87 istream::pos_type BinaryReader::readStreamsize()
88 {
89  istream::pos_type cp = m_stream->tellg();
90  m_stream->seekg(0, ios_base::end);
91  const auto streamsize = m_stream->tellg();
92  m_stream->seekg(cp);
93  return streamsize;
94 }
95 
96 void BinaryReader::bufferVariableLengthInteger()
97 {
98  static constexpr int maxPrefixLength = 8;
99  int prefixLength = 1;
100  const byte beg = static_cast<byte>(m_stream->peek());
101  byte mask = 0x80;
102  while (prefixLength <= maxPrefixLength && (beg & mask) == 0) {
103  ++prefixLength;
104  mask >>= 1;
105  }
106  if (prefixLength > maxPrefixLength) {
107  throw ConversionException("Length denotation of variable length unsigned integer exceeds maximum.");
108  }
109  memset(m_buffer, 0, maxPrefixLength);
110  m_stream->read(m_buffer + (maxPrefixLength - prefixLength), prefixLength);
111  *(m_buffer + (maxPrefixLength - prefixLength)) ^= mask;
112 }
113 
121 {
123 }
124 
128 string BinaryReader::readString(size_t length)
129 {
130  string res;
131  res.resize(length);
132  m_stream->read(&res[0], length);
133  return res;
134 }
135 
146 string BinaryReader::readTerminatedString(byte termination)
147 {
148  stringstream ss(ios_base::in | ios_base::out | ios_base::binary);
149  ss.exceptions(ios_base::badbit | ios_base::failbit);
150  m_stream->get(*ss.rdbuf(), static_cast<char>(termination)); // delim byte is not extracted from the stream
151  m_stream->seekg(1, ios_base::cur); // "extract" delim byte manually
152  return ss.str();
153 }
154 
167 string BinaryReader::readTerminatedString(size_t maxBytesToRead, byte termination)
168 {
169  unique_ptr<char[]> buff = make_unique<char[]>(maxBytesToRead);
170  for (char *i = buff.get(), *end = i + maxBytesToRead; i < end; ++i) {
171  m_stream->get(*i);
172  if (*(reinterpret_cast<byte *>(i)) == termination) {
173  return string(buff.get(), i - buff.get());
174  }
175  }
176  return string(buff.get(), maxBytesToRead);
177 }
178 
190 {
191  stringstream ss(ios_base::in | ios_base::out | ios_base::binary);
192  ss.exceptions(ios_base::badbit | ios_base::failbit);
193  char *delimChars = m_buffer, *buff = m_buffer + 2;
194  ConversionUtilities::BE::getBytes(termination, delimChars);
195  m_stream->get(buff[0]);
196  m_stream->get(buff[1]);
197  while (!((buff[0] == delimChars[0]) && (buff[1] == delimChars[1]))) {
198  ss.put(buff[0]);
199  ss.put(buff[1]);
200  m_stream->get(buff[0]);
201  m_stream->get(buff[1]);
202  }
203  return ss.str();
204 }
205 
217 {
218  stringstream ss(ios_base::in | ios_base::out | ios_base::binary);
219  ss.exceptions(ios_base::badbit | ios_base::failbit);
220  char *delimChars = m_buffer, *buff = m_buffer + 2;
221  ConversionUtilities::LE::getBytes(termination, delimChars);
222  m_stream->get(buff[0]);
223  m_stream->get(buff[1]);
224  while (!((buff[0] == delimChars[0]) && (buff[1] == delimChars[1]))) {
225  ss.put(buff[0]);
226  ss.put(buff[1]);
227  m_stream->get(buff[0]);
228  m_stream->get(buff[1]);
229  }
230  return ss.str();
231 }
232 
245 string BinaryReader::readMultibyteTerminatedStringBE(std::size_t maxBytesToRead, uint16 termination)
246 {
247  unique_ptr<char[]> buff = make_unique<char[]>(maxBytesToRead);
248  char *delimChars = m_buffer;
249  ConversionUtilities::BE::getBytes(termination, delimChars);
250  for (char *i = buff.get(), *end = i + maxBytesToRead; (i + 1) < end; i += 2) {
251  m_stream->get(*i);
252  m_stream->get(*(i + 1));
253  if ((*i == delimChars[0]) && (*(i + 1) == delimChars[1])) {
254  return string(buff.get(), i - buff.get());
255  }
256  }
257  return string(buff.get(), maxBytesToRead);
258 }
259 
272 string BinaryReader::readMultibyteTerminatedStringLE(std::size_t maxBytesToRead, uint16 termination)
273 {
274  unique_ptr<char[]> buff = make_unique<char[]>(maxBytesToRead);
275  char *delimChars = m_buffer;
276  ConversionUtilities::LE::getBytes(termination, delimChars);
277  for (char *i = buff.get(), *end = i + maxBytesToRead; (i + 1) < end; i += 2) {
278  m_stream->get(*i);
279  m_stream->get(*(i + 1));
280  if ((*i == delimChars[0]) && (*(i + 1) == delimChars[1])) {
281  return string(buff.get(), i - buff.get());
282  }
283  }
284  return string(buff.get(), maxBytesToRead);
285 }
286 
296 {
297  uint32 crc = 0x00;
298  for (uint32 i = 0; i < length; ++i) {
299  crc = (crc << 8) ^ crc32Table[((crc >> 24) & 0xff) ^ static_cast<byte>(m_stream->get())];
300  }
301  return crc;
302 }
303 
312 uint32 BinaryReader::computeCrc32(const char *buffer, size_t length)
313 {
314  uint32 crc = 0x00;
315  for (const char *i = buffer, *end = buffer + length; i != end; ++i) {
316  crc = (crc << 8) ^ crc32Table[((crc >> 24) & 0xff) ^ static_cast<byte>(*i)];
317  }
318  return crc;
319 }
320 
326 const uint32 BinaryReader::crc32Table[] = { 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
327  0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
328  0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
329  0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
330  0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
331  0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
332  0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
333  0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
334  0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
335  0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
336  0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
337  0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
338  0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
339  0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
340  0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
341  0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
342  0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
343  0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
344  0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
345  0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
346  0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
347  0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 };
Reads primitive data types from a std::istream.
Definition: binaryreader.h:11
The ConversionException class is thrown by the various conversion functions of this library when a co...
static const uint32 crc32Table[]
CRC-32 table.
Definition: binaryreader.h:81
BinaryReader(std::istream *stream)
Constructs a new BinaryReader.
uint32 readCrc32(std::size_t length)
Reads length bytes from the stream and computes the CRC-32 for that block of data.
Contains utility classes helping to read and write streams.
Definition: binaryreader.h:10
constexpr int i
Contains several functions providing conversions between different data types.
std::istream::pos_type readStreamsize()
Returns the size of the assigned stream.
std::uint32_t uint32
unsigned 32-bit integer
Definition: types.h:44
void giveOwnership()
The reader will take ownership over the assigned stream.
Definition: binaryreader.h:144
void setStream(std::istream *stream, bool giveOwnership=false)
Assigns the stream the reader will read from when calling one of the read-methods.
std::string readTerminatedString(byte termination=0)
Reads a terminated string from the current stream.
const std::istream * stream() const
Returns a pointer to the stream the reader will read from when calling one of the read-methods.
Definition: binaryreader.h:120
static uint32 computeCrc32(const char *buffer, std::size_t length)
Reads length bytes from the buffer and computes the CRC-32 for that block of data.
uint64 readVariableLengthUIntBE()
Reads an up to 8 byte long big endian unsigned integer from the current stream and advances the curre...
Definition: binaryreader.h:342
CPP_UTILITIES_EXPORT void getBytes(int16 value, char *outputbuffer)
Stores the specified 16-bit signed integer value at a specified position in a char array.
std::string readMultibyteTerminatedStringLE(uint16 termination=0)
Reads a multibyte-terminated string from the current stream.
std::string readLengthPrefixedString()
Reads a length prefixed string from the current stream.
~BinaryReader()
Destroys the BinaryReader.
std::string readMultibyteTerminatedStringBE(uint16 termination=0)
Reads a multibyte-terminated string from the current stream.
std::string readString(std::size_t length)
Reads a string from the current stream of the given length from the stream and advances the current p...
std::uint16_t uint16
unsigned 16-bit integer
Definition: types.h:39
CPP_UTILITIES_EXPORT void getBytes(int16 value, char *outputbuffer)
Stores the specified 16-bit signed integer value at a specified position in a char array.