C++ Utilities  4.14.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 
28 BinaryReader::BinaryReader(istream *stream)
29  : m_stream(stream)
30  , m_ownership(false)
31 {
32 }
33 
39  : m_stream(other.m_stream)
40  , m_ownership(false)
41 {
42 }
43 
48 {
49  if (m_ownership) {
50  delete m_stream;
51  }
52 }
53 
65 void BinaryReader::setStream(istream *stream, bool giveOwnership)
66 {
67  if (m_ownership) {
68  delete m_stream;
69  }
70  if (stream) {
71  m_stream = stream;
72  m_ownership = giveOwnership;
73  } else {
74  m_stream = nullptr;
75  m_ownership = false;
76  }
77 }
78 
86 istream::pos_type BinaryReader::readStreamsize()
87 {
88  istream::pos_type cp = m_stream->tellg();
89  m_stream->seekg(0, ios_base::end);
90  const auto streamsize = m_stream->tellg();
91  m_stream->seekg(cp);
92  return streamsize;
93 }
94 
102 {
103  static constexpr int maxPrefixLength = 8;
104  int prefixLength = 1;
105  const byte beg = static_cast<byte>(m_stream->peek());
106  byte mask = 0x80;
107  while (prefixLength <= maxPrefixLength && (beg & mask) == 0) {
108  ++prefixLength;
109  mask >>= 1;
110  }
111  if (prefixLength > maxPrefixLength) {
112  throw ConversionException("Length denotation of length-prefixed string exceeds maximum.");
113  }
114  memset(m_buffer, 0, maxPrefixLength);
115  m_stream->read(m_buffer + (maxPrefixLength - prefixLength), prefixLength);
116  *(m_buffer + (maxPrefixLength - prefixLength)) ^= mask;
117  return readString(BE::toUInt64(m_buffer));
118 }
119 
123 string BinaryReader::readString(size_t length)
124 {
125  string res;
126  res.resize(length);
127  m_stream->read(&res[0], length);
128  return res;
129 }
130 
142 {
143  stringstream ss(ios_base::in | ios_base::out | ios_base::binary);
144  ss.exceptions(ios_base::badbit | ios_base::failbit);
145  m_stream->get(*ss.rdbuf(), termination); // delim byte is not extracted from the stream
146  m_stream->seekg(1, ios_base::cur); // "extract" delim byte manually
147  return ss.str();
148 }
149 
162 string BinaryReader::readTerminatedString(size_t maxBytesToRead, byte termination)
163 {
164  unique_ptr<char[]> buff = make_unique<char[]>(maxBytesToRead);
165  for (char *i = buff.get(), *end = i + maxBytesToRead; i < end; ++i) {
166  m_stream->get(*i);
167  if (*(reinterpret_cast<byte *>(i)) == termination) {
168  return string(buff.get(), i - buff.get());
169  }
170  }
171  return string(buff.get(), maxBytesToRead);
172 }
173 
185 {
186  stringstream ss(ios_base::in | ios_base::out | ios_base::binary);
187  ss.exceptions(ios_base::badbit | ios_base::failbit);
188  char *delimChars = m_buffer, *buff = m_buffer + 2;
189  ConversionUtilities::BE::getBytes(termination, delimChars);
190  m_stream->get(buff[0]);
191  m_stream->get(buff[1]);
192  while (!((buff[0] == delimChars[0]) && (buff[1] == delimChars[1]))) {
193  ss.put(buff[0]);
194  ss.put(buff[1]);
195  m_stream->get(buff[0]);
196  m_stream->get(buff[1]);
197  }
198  return ss.str();
199 }
200 
212 {
213  stringstream ss(ios_base::in | ios_base::out | ios_base::binary);
214  ss.exceptions(ios_base::badbit | ios_base::failbit);
215  char *delimChars = m_buffer, *buff = m_buffer + 2;
216  ConversionUtilities::LE::getBytes(termination, delimChars);
217  m_stream->get(buff[0]);
218  m_stream->get(buff[1]);
219  while (!((buff[0] == delimChars[0]) && (buff[1] == delimChars[1]))) {
220  ss.put(buff[0]);
221  ss.put(buff[1]);
222  m_stream->get(buff[0]);
223  m_stream->get(buff[1]);
224  }
225  return ss.str();
226 }
227 
240 string BinaryReader::readMultibyteTerminatedStringBE(std::size_t maxBytesToRead, uint16 termination)
241 {
242  unique_ptr<char[]> buff = make_unique<char[]>(maxBytesToRead);
243  char *delimChars = m_buffer;
244  ConversionUtilities::BE::getBytes(termination, delimChars);
245  for (char *i = buff.get(), *end = i + maxBytesToRead; (i + 1) < end; i += 2) {
246  m_stream->get(*i);
247  m_stream->get(*(i + 1));
248  if ((*i == delimChars[0]) && (*(i + 1) == delimChars[1])) {
249  return string(buff.get(), i - buff.get());
250  }
251  }
252  return string(buff.get(), maxBytesToRead);
253 }
254 
267 string BinaryReader::readMultibyteTerminatedStringLE(std::size_t maxBytesToRead, uint16 termination)
268 {
269  unique_ptr<char[]> buff = make_unique<char[]>(maxBytesToRead);
270  char *delimChars = m_buffer;
271  ConversionUtilities::LE::getBytes(termination, delimChars);
272  for (char *i = buff.get(), *end = i + maxBytesToRead; (i + 1) < end; i += 2) {
273  m_stream->get(*i);
274  m_stream->get(*(i + 1));
275  if ((*i == delimChars[0]) && (*(i + 1) == delimChars[1])) {
276  return string(buff.get(), i - buff.get());
277  }
278  }
279  return string(buff.get(), maxBytesToRead);
280 }
281 
291 {
292  uint32 crc = 0x00;
293  for (uint32 i = 0; i < length; ++i) {
294  crc = (crc << 8) ^ crc32Table[((crc >> 24) & 0xff) ^ static_cast<byte>(m_stream->get())];
295  }
296  return crc;
297 }
298 
307 uint32 BinaryReader::computeCrc32(const char *buffer, size_t length)
308 {
309  uint32 crc = 0x00;
310  for (const char *i = buffer, *end = buffer + length; i != end; ++i) {
311  crc = (crc << 8) ^ crc32Table[((crc >> 24) & 0xff) ^ static_cast<byte>(*i)];
312  }
313  return crc;
314 }
315 
321 const uint32 BinaryReader::crc32Table[] = { 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
322  0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
323  0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
324  0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
325  0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
326  0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
327  0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
328  0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
329  0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
330  0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
331  0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
332  0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
333  0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
334  0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
335  0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
336  0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
337  0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
338  0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
339  0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
340  0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
341  0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
342  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...
STL namespace.
static const uint32 crc32Table[]
CRC-32 table.
Definition: binaryreader.h:79
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
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:126
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:102
std::uint8_t byte
unsigned byte
Definition: types.h:14
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.
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