Thea
BinaryInputStream.hpp
1 //============================================================================
2 //
3 // This file is part of the Thea toolkit.
4 //
5 // This software is distributed under the BSD license, as detailed in the
6 // accompanying LICENSE.txt file. Portions are derived from other works:
7 // their respective licenses and copyright information are reproduced in
8 // LICENSE.txt and/or in the relevant source files.
9 //
10 // Author: Siddhartha Chaudhuri
11 // First version: 2013
12 //
13 //============================================================================
14 
15 /*
16  ORIGINAL HEADER
17 
18  @file BinaryInput.h
19 
20  @maintainer Morgan McGuire, http://graphics.cs.williams.edu
21 
22  @created 2001-08-09
23  @edited 2010-03-19
24 
25  Copyright 2000-2010, Morgan McGuire.
26  All rights reserved.
27 */
28 
29 #ifndef __Thea_BinaryInputStream_hpp__
30 #define __Thea_BinaryInputStream_hpp__
31 
32 #ifdef _MSC_VER
33 // Disable conditional expression is constant, which occurs incorrectly on inlined functions
34 # pragma warning(push)
35 # pragma warning( disable : 4127 )
36 #endif
37 
38 #include "Common.hpp"
39 #include "Array.hpp"
40 #include "Codec.hpp"
41 #include "Colors.hpp"
42 #include "CoordinateFrame3.hpp"
43 #include "MatVec.hpp"
44 #include "NamedObject.hpp"
45 #include "Noncopyable.hpp"
46 #include "Plane3.hpp"
47 
48 namespace Thea {
49 
59 class THEA_API BinaryInputStream : public NamedObject, private Noncopyable
60 {
61  private:
63  Endianness m_fileEndian;
64 
66  std::string m_path;
67 
69  bool m_swapBytes;
70 
72  int m_bitPos;
73 
77  uint32 m_bitString;
78 
80  int m_beginEndBits;
81 
86  int64 m_alreadyRead;
87 
89  int64 m_length;
90 
92  int64 m_bufferLength;
93 
95  uint8 * m_buffer;
96 
98  int64 m_pos;
99 
101  bool m_freeBuffer;
102 
104  void loadIntoMemory(int64 start_position, int64 min_length = 0);
105 
107  void prepareToRead(int64 nbytes)
108  {
109  if (m_pos + nbytes + m_alreadyRead > m_length)
110  throw Error(getNameStr() + ": Read past end of stream");
111 
112  if (m_pos + nbytes > m_bufferLength)
113  loadIntoMemory(m_pos + m_alreadyRead, nbytes);
114  }
115 
116  // Not implemented on purpose, don't use.
117  bool operator==(BinaryInputStream const &) const;
118 
119  public:
120  THEA_DECL_SMART_POINTERS(BinaryInputStream)
121 
122 
123  static bool const NO_COPY;
124 
130  {
131  public:
134  : stream(stream_), saved_endian(stream_.getEndianness())
135  {}
136 
139  : stream(stream_), saved_endian(stream_.getEndianness())
140  {
141  stream.setEndianness(new_endian);
142  }
143 
145  ~EndiannessScope() { stream.setEndianness(saved_endian); }
146 
147  private:
148  BinaryInputStream & stream;
149  Endianness saved_endian;
150 
151  }; // class EndiannessScope
152 
154  BinaryInputStream(std::string const & path, Endianness file_endian);
155 
160  BinaryInputStream(uint8 const * data, int64 data_len, Endianness data_endian, bool copy_memory = true);
161 
168  BinaryInputStream(BinaryInputStream & src, int64 block_len);
169 
172 
178  void setEndianness(Endianness endian);
179 
182  {
183  return m_fileEndian;
184  }
185 
187  std::string getPath() const
188  {
189  return m_path;
190  }
191 
193  int64 size() const
194  {
195  return m_length;
196  }
197 
199  bool hasMore() const
200  {
201  return m_pos + m_alreadyRead < m_length;
202  }
203 
205  int64 getPosition() const
206  {
207  return m_pos + m_alreadyRead;
208  }
209 
214  void setPosition(int64 p)
215  {
216  if (p > m_length)
217  throw Error("Read past end of stream");
218 
219  m_pos = p - m_alreadyRead;
220 
221  if ((m_pos < 0) || (m_pos > m_bufferLength))
222  loadIntoMemory(m_pos + m_alreadyRead);
223  }
224 
226  void reset()
227  {
228  setPosition(0);
229  }
230 
232  void skip(int64 n)
233  {
234  setPosition(m_pos + m_alreadyRead + n);
235  }
236 
238  uint8 readUInt8()
239  {
240  prepareToRead(1);
241  return ((uint8 *)m_buffer)[m_pos++];
242  }
243 
245  int8 readInt8()
246  {
247  prepareToRead(1);
248  return m_buffer[m_pos++];
249  }
250 
252  bool readBool8()
253  {
254  return (readInt8() != 0);
255  }
256 
258  uint16 readUInt16()
259  {
260  prepareToRead(2);
261  m_pos += 2;
262 
263  if (m_swapBytes)
264  {
265  uint8 out[2];
266  out[0] = m_buffer[m_pos - 1];
267  out[1] = m_buffer[m_pos - 2];
268  return *(uint16 *)out;
269  }
270  else
271  {
272 #ifdef THEA_ALLOW_UNALIGNED_READS
273  return *(uint16 *)(&m_buffer[m_pos - 2]);
274 #else
275  uint8 out[2];
276  out[0] = m_buffer[m_pos - 2];
277  out[1] = m_buffer[m_pos - 1];
278  return *(uint16 *)out;
279 #endif
280  }
281  }
282 
284  int16 readInt16()
285  {
286  uint16 a = readUInt16();
287  return *(int16 *)&a;
288  }
289 
291  uint32 readUInt32()
292  {
293  prepareToRead(4);
294  m_pos += 4;
295 
296  if (m_swapBytes)
297  {
298  uint8 out[4];
299  out[0] = m_buffer[m_pos - 1];
300  out[1] = m_buffer[m_pos - 2];
301  out[2] = m_buffer[m_pos - 3];
302  out[3] = m_buffer[m_pos - 4];
303  return *(uint32 *)out;
304  }
305  else
306  {
307 #ifdef THEA_ALLOW_UNALIGNED_READS
308  return *(uint32 *)(&m_buffer[m_pos - 4]);
309 #else
310  uint8 out[4];
311  out[0] = m_buffer[m_pos - 4];
312  out[1] = m_buffer[m_pos - 3];
313  out[2] = m_buffer[m_pos - 2];
314  out[3] = m_buffer[m_pos - 1];
315  return *(uint32 *)out;
316 #endif
317  }
318  }
319 
321  int32 readInt32()
322  {
323  uint32 a = readUInt32();
324  return *(int32 *)&a;
325  }
326 
328  uint64 readUInt64();
329 
331  int64 readInt64()
332  {
333  uint64 a = readUInt64();
334  return *(int64 *)&a;
335  }
336 
338  float32 readFloat32()
339  {
340  union
341  {
342  uint32 a;
343  float32 b;
344  };
345 
346  a = readUInt32();
347  return b;
348  }
349 
351  float64 readFloat64()
352  {
353  union
354  {
355  uint64 a;
356  float64 b;
357  };
358 
359  a = readUInt64();
360  return b;
361  }
362 
364  void readBytes(int64 n, void * bytes);
365 
369  std::string readLine();
370 
378  std::string readString()
379  {
380  return readAlignedString(1);
381  }
382 
391  std::string readAlignedString(int alignment = 4);
392 
397  std::string readString(int64 n);
398 
402  std::string readNullTerminatedString();
403 
408  void beginBits();
409 
411  uint32 readBits(int num_bits);
412 
414  void endBits();
415 
417  Vector2 readVector2()
418  {
419  Vector2 v;
420  v[0] = readFloat32();
421  v[1] = readFloat32();
422  return v;
423  }
424 
426  Vector3 readVector3()
427  {
428  Vector3 v;
429  v[0] = readFloat32();
430  v[1] = readFloat32();
431  v[2] = readFloat32();
432  return v;
433  }
434 
436  Vector4 readVector4()
437  {
438  Vector4 v;
439  v[0] = readFloat32();
440  v[1] = readFloat32();
441  v[2] = readFloat32();
442  v[3] = readFloat32();
443  return v;
444  }
445 
448  {
449  return ColorL8(readUInt8());
450  }
451 
454  {
455  return ColorL(readFloat32());
456  }
457 
460  {
461  ColorRgb8 c;
462  c.r() = readUInt8();
463  c.g() = readUInt8();
464  c.b() = readUInt8();
465  return c;
466  }
467 
470  {
471  ColorRgb c;
472  c.r() = readFloat32();
473  c.g() = readFloat32();
474  c.b() = readFloat32();
475  return c;
476  }
477 
480  {
481  ColorRgba8 c;
482  c.r() = readUInt8();
483  c.g() = readUInt8();
484  c.b() = readUInt8();
485  c.a() = readUInt8();
486  return c;
487  }
488 
491  {
492  ColorRgba c;
493  c.r() = readFloat32();
494  c.g() = readFloat32();
495  c.b() = readFloat32();
496  c.a() = readFloat32();
497  return c;
498  }
499 
501  Matrix2 readMatrix2()
502  {
503  Matrix2 m;
504  m(0, 0) = readFloat32();
505  m(0, 1) = readFloat32();
506  m(1, 0) = readFloat32();
507  m(1, 1) = readFloat32();
508  return m;
509  }
510 
512  Matrix3 readMatrix3()
513  {
514  Matrix3 m;
515  for (int r = 0; r < 3; ++r)
516  for (int c = 0; c < 3; ++c)
517  m(r, c) = readFloat32();
518 
519  return m;
520  }
521 
523  Matrix4 readMatrix4()
524  {
525  Matrix4 m;
526  for (int r = 0; r < 4; ++r)
527  for (int c = 0; c < 4; ++c)
528  m(r, c) = readFloat32();
529 
530  return m;
531  }
532 
535  {
536  Matrix3 rot = readMatrix3();
537  Vector3 trn = readVector3();
539  }
540 
543  {
544  Real a = readFloat32();
545  Real b = readFloat32();
546  Real c = readFloat32();
547  Real d = readFloat32();
548  return Plane3::fromEquation(a, b, c, d);
549  }
550 
567  template <typename MatrixT>
568  intx readMatrix(bool read_block_header, MatrixT & m, Codec const & codec = CodecAuto());
569 
590  template < typename CandidateMatrixType0, typename CandidateMatrixType1, typename... MoreMatrixTypes,
591  typename std::enable_if< !std::is_base_of<Codec, CandidateMatrixType1>::value, int >::type * = nullptr >
592  intx readMatrix(bool read_block_header, CandidateMatrixType0 & m0, CandidateMatrixType1 & m1, MoreMatrixTypes & ... rest)
593  {
594  return readMatrixHelper(0, read_block_header, m0, m1, rest...);
595  }
596 
597 # define THEA_BINARY_INPUT_STREAM_DECLARE_READER(fname, tname) \
598  void read##fname(int64 n, tname * out); \
599  void read##fname(int64 n, Array<tname> & out);
600 
601  THEA_BINARY_INPUT_STREAM_DECLARE_READER(Bool8, bool)
602  THEA_BINARY_INPUT_STREAM_DECLARE_READER(UInt8, uint8)
603  THEA_BINARY_INPUT_STREAM_DECLARE_READER(Int8, int8)
604  THEA_BINARY_INPUT_STREAM_DECLARE_READER(UInt16, uint16)
605  THEA_BINARY_INPUT_STREAM_DECLARE_READER(Int16, int16)
606  THEA_BINARY_INPUT_STREAM_DECLARE_READER(UInt32, uint32)
607  THEA_BINARY_INPUT_STREAM_DECLARE_READER(Int32, int32)
608  THEA_BINARY_INPUT_STREAM_DECLARE_READER(UInt64, uint64)
609  THEA_BINARY_INPUT_STREAM_DECLARE_READER(Int64, int64)
610  THEA_BINARY_INPUT_STREAM_DECLARE_READER(Float32, float32)
611  THEA_BINARY_INPUT_STREAM_DECLARE_READER(Float64, float64)
612  THEA_BINARY_INPUT_STREAM_DECLARE_READER(Vector2, Vector2)
613  THEA_BINARY_INPUT_STREAM_DECLARE_READER(Vector3, Vector3)
614  THEA_BINARY_INPUT_STREAM_DECLARE_READER(Vector4, Vector4)
615  THEA_BINARY_INPUT_STREAM_DECLARE_READER(ColorL8, ColorL8)
616  THEA_BINARY_INPUT_STREAM_DECLARE_READER(ColorL, ColorL)
617  THEA_BINARY_INPUT_STREAM_DECLARE_READER(ColorRgb8, ColorRgb8)
618  THEA_BINARY_INPUT_STREAM_DECLARE_READER(ColorRgb, ColorRgb)
619  THEA_BINARY_INPUT_STREAM_DECLARE_READER(ColorRgba8, ColorRgba8)
620  THEA_BINARY_INPUT_STREAM_DECLARE_READER(ColorRgba, ColorRgba)
621  THEA_BINARY_INPUT_STREAM_DECLARE_READER(Matrix2, Matrix2)
622  THEA_BINARY_INPUT_STREAM_DECLARE_READER(Matrix3, Matrix3)
623  THEA_BINARY_INPUT_STREAM_DECLARE_READER(Matrix4, Matrix4)
624  THEA_BINARY_INPUT_STREAM_DECLARE_READER(CoordinateFrame3, CoordinateFrame3)
625  THEA_BINARY_INPUT_STREAM_DECLARE_READER(Plane3, Plane3)
626 # undef THEA_BINARY_INPUT_STREAM_DECLARE_READER
627 
628  private:
633  intx readMatrixHelper(intx index, bool read_block_header);
634 
636  template <typename CandidateMatrixT, typename... MoreMatrixTypes>
637  intx readMatrixHelper(intx index, bool read_block_header, CandidateMatrixT & m, MoreMatrixTypes & ... rest);
638 
639 }; // class BinaryInputStream
640 
641 } // namespace Thea
642 
643 #ifdef _MSC_VER
644 # pragma warning(pop)
645 #endif
646 
647 THEA_DECL_EXTERN_SMART_POINTERS(Thea::BinaryInputStream)
648 
649 #include "MatrixIO.hpp"
650 
651 #endif
A base class for objects that should never be copied.
Definition: Noncopyable.hpp:28
Endianness values (little-endian and big-endian) (enum class).
A color with three floating-point channels: red, green and blue, each in [0, 1].
Definition: ColorRgb.hpp:51
uint8 r() const
The value of the red channel.
Definition: ColorRgba8.hpp:74
Real g() const
The value of the green channel.
Definition: ColorRgb.hpp:111
Real b() const
The value of the blue channel.
Definition: ColorRgba.hpp:97
An object that saves the current endianness state of a stream upon construction, and restores the pre...
std::ptrdiff_t intx
A signed integer suitable for indexing a structure held in memory.
Definition: Platform.hpp:161
ColorRgb readColorRgb()
Read a color with 3 floating-point channels.
Matrix3 readMatrix3()
Read a 3x3 matrix.
int8 readInt8()
Read an 8-bit signed integer (a signed byte).
uint8 g() const
The value of the green channel.
Definition: ColorRgb8.hpp:83
bool readBool8()
Read an 8-bit boolean (0 is false, non-zero is true).
Indicates that the appropriate codec should be autodetected.
Definition: Codec.hpp:164
Root namespace for the Thea library.
int64 readInt64()
Read a 64-bit signed integer.
Matrix4 readMatrix4()
Read a 4x4 matrix.
uint32 readUInt32()
Read a 32-bit unsigned integer.
Real g() const
The value of the green channel.
Definition: ColorRgba.hpp:91
void reset()
Set the read position at the beginning of the file.
ColorRgba readColorRgba()
Read a color with 4 floating-point channels.
Monochrome luminance value represented as a single byte value in [0, 255], with automatic scaling by ...
Definition: ColorL8.hpp:46
An object wrapping a name string.
Definition: NamedObject.hpp:58
ColorL readColorL()
Read a color with 1 floating-point channel.
A color with three byte-sized channels: red, green and blue, each in [0, 255].
Definition: ColorRgb8.hpp:47
A color with four byte-sized channels: red, green, blue and alpha, each in [0, 255].
Definition: ColorRgba8.hpp:47
ColorRgba8 readColorRgba8()
Read a color with 4 8-bit channels.
float32 readFloat32()
Read a 32-bit floating point number.
uint8 b() const
The value of the blue channel.
Definition: ColorRgb8.hpp:89
Real b() const
The value of the blue channel.
Definition: ColorRgb.hpp:117
uint8 b() const
The value of the blue channel.
Definition: ColorRgba8.hpp:86
EndiannessScope(BinaryInputStream &stream_, Endianness new_endian)
Constructor, saves the endianness state of a stream and sets a new endianness.
Vector4 readVector4()
Read a 4-vector.
Real a() const
The value of the alpha channel.
Definition: ColorRgba.hpp:103
static RigidTransformT _fromAffine(AffineTransformT const &aff_)
Construct from an affine transform, assuming it is rigid (use with caution since it can break the rig...
intx readMatrix(bool read_block_header, CandidateMatrixType0 &m0, CandidateMatrixType1 &m1, MoreMatrixTypes &...rest)
Given a set of candidate matrices of different types, read that one whose format best matches the inp...
uint8 r() const
The value of the red channel.
Definition: ColorRgb8.hpp:77
std::string getPath() const
Get the path to the current file being read ("<memory>" for memory streams).
int32 readInt32()
Read a 32-bit signed integer.
Plane3 readPlane3()
Read a 3D plane.
int64 getPosition() const
Get the current byte position in the stream, where 0 is the beginning and size() - 1 is the end...
AffineTransformN< 3, Real > AffineTransform3
The default affine transform class in real 3-space.
ColorRgb8 readColorRgb8()
Read a color with 3 8-bit channels.
Monochrome luminance value in [0, 1], with automatic scaling by 255 when switching between integer (C...
Definition: ColorL.hpp:46
A serialization codec.
Definition: Codec.hpp:33
Sequential or random access input from binary files/memory.
Real r() const
The value of the red channel.
Definition: ColorRgba.hpp:85
Vector2 readVector2()
Read a 2-vector.
CoordinateFrame3 readCoordinateFrame3()
Read a coordinate frame.
~EndiannessScope()
Destructor, restores the saved endianness of the stream.
uint8 readUInt8()
Read an 8-bit unsigned integer (an unsigned byte).
bool hasMore() const
Check if there are more bytes to be read.
int64 size() const
Get the number of bytes in the stream.
void skip(int64 n)
Skips ahead n bytes.
std::string readString()
Read a string.
void setPosition(int64 p)
Set the current byte position in the stream.
uint16 readUInt16()
Read a 16-bit unsigned integer.
uint8 g() const
The value of the green channel.
Definition: ColorRgba8.hpp:80
Endianness getEndianness() const
Get the current endianness setting for reading multi-byte data.
A color with four floating-point channels: red, green and blue, each in [0, 1].
Definition: ColorRgba.hpp:52
Matrix2 readMatrix2()
Read a 2x2 matrix.
std::runtime_error Error
An error class.
Definition: Error.hpp:27
int16 readInt16()
Read a 16-bit signed integer.
uint8 a() const
The value of the alpha channel.
Definition: ColorRgba8.hpp:92
CoordinateFrameN< 3, Real > CoordinateFrame3
The default coordinate frame class in real 3-space.
float64 readFloat64()
Read a 64-bit floating point number.
ColorL8 readColorL8()
Read a color with 1 8-bit channel.
Vector3 readVector3()
Read a 3-vector.
Real r() const
The value of the red channel.
Definition: ColorRgb.hpp:105
EndiannessScope(BinaryInputStream &stream_)
Constructor, saves the endianness state of a stream.