Ocean
Bitstream.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_IO_BITSTREAM_H
9 #define META_OCEAN_IO_BITSTREAM_H
10 
11 #include "ocean/io/IO.h"
12 
13 #include <istream>
14 #include <ostream>
15 
16 namespace Ocean
17 {
18 
19 namespace IO
20 {
21 
22 /**
23  * This class implements an input bitstream.
24  * The implementation of the input bitstream is not thread-safe, thus ensure that the internal input stream object is not used within several threads concurrently.<br>
25  * The following data types are supported:
26  * <pre>
27  * Data type: Number of bytes: Description:
28  * bool 1
29  * char 1
30  * wchar_t 4 Depending on the platform wchar_t has 1, 2 or 4 bytes thus this stream object stores 4 bytes per wchar_t object (see also std::wstring)
31  * unsigned char 1
32  * short 2
33  * unsigned short 2
34  * int 4
35  * unsigned int 4
36  * float 4
37  * double 8
38  * long long 8
39  * unsigned long long 8
40  * std::string 4 + 1 * size Four bytes for the size of the string and 1 byte for each character
41  * std::wstring 4 + 4 * size Four bytes for the size of the string and 4 bytes for each character
42  * </pre>
43  * The following data types are not supported as they have individual size on individual platforms and thus must not be used:
44  * <pre>
45  * Data type: Description:
46  * size_t size_t has 4 bytes on 32 bit platforms and 8 bytes on 64 bit platforms
47  * </pre>
48  * @ingroup io
49  */
50 class OCEAN_IO_EXPORT InputBitstream
51 {
52  public:
53 
54  /**
55  * Creates a new bitstream object.
56  * @param stream The input stream object that is encapsulated by this object
57  */
58  InputBitstream(std::istream& stream);
59 
60  /**
61  * Reads a value from the bitstream and moves the internal position inside the bitstream accordingly.
62  * If the read process fails, the new position of the bitstream may be arbitrary.<br>
63  * Beware: It's recommended to provide the template argument explicitly to avoid type ambiguities.<br>
64  * @param value The resulting value that is read
65  * @return True, if the value could be read successfully
66  * @tparam T The data type that is read, ensure that only supported data types are applied
67  * @see readDefault().
68  */
69  template <typename T>
70  bool read(T& value);
71 
72  /**
73  * Reads a value from the bitstream and moves the internal position inside the bitstream accordingly.
74  * If the read process fails, the new position of the bitstream may be arbitrary.<br>
75  * This function does not provide a success value but returns a given default value if the read process fails.<br>
76  * Beware: It's recommended to provide the template argument explicitly to avoid type ambiguities.<br>
77  * @param defaultValue The default value that is returned if the read process fails
78  * @return The resulting value that has been read
79  * @tparam T The data type that is read, ensure that only supported data types are applied
80  * @see read().
81  */
82  template <typename T>
83  T readDefault(const T& defaultValue);
84 
85  /**
86  * Reads a defined memory block from the stream into a given buffer and moves the internal position inside the bitstream accordingly.
87  * If the read process fails, the new position of the bitstream may be arbitrary.
88  * @param data The buffer that will receive the memory block, ensure that this buffer is large enough, may be nullptr if size is 0
89  * @param size The number of bytes that will be read into the memory block, with range [0, infinity)
90  * @return True, if succeeded
91  */
92  bool read(void* data, const size_t size);
93 
94  /**
95  * Reads a value from the bitstream but does not move the internal position inside the bitstream.
96  * Beware: It's recommended to provide the template argument explicitly to avoid type ambiguities.<br>
97  * @param value The resulting value that is looked-up
98  * @return True, if the value could be looked-up successfully
99  * @tparam T The data type that is read, ensure that only supported data types are applied
100  */
101  template <typename T>
102  bool look(T& value);
103 
104  /**
105  * Returns the current position inside the bitstream, in bytes counting from the beginning of the stream.
106  * @return The current stream position in bytes, -1 if the current position cannot be determined
107  */
108  unsigned long long position() const;
109 
110  /**
111  * Returns the current size of the bitstream, in bytes.
112  * @return The current stream size in bytes, -1 if the current size cannot be determined
113  */
114  unsigned long long size() const;
115 
116  /**
117  * Sets the current position inside the bitstream explicitly.
118  * @param position The new position inside the bitstream, in bytes counting from the beginning of the stream; with range [0, size())
119  * @return True, if succeeded
120  */
121  bool setPosition(const unsigned long long position);
122 
123  /**
124  * Returns whether this bitstream object is valid and can be used.
125  * @return True, if so
126  */
127  explicit inline operator bool() const;
128 
129  protected:
130 
131  /// The internal input stream object that this object encapsulates.
132  std::istream& inputStream;
133 };
134 
135 /**
136  * This class implements a scoped input bitstream that allows to read content from a bitstream while the stream position is restored if this object is disposed.
137  * The implementation of this scoped input bitstream object is not thread-safe.
138  * @see InputBitstream
139  * @ingroup io
140  */
142 {
143  public:
144 
145  /**
146  * Creates a new scoped input bitstream object from a given input bitstream object and stores the current stream position of the given stream object.
147  */
148  inline ScopedInputBitstream(InputBitstream& stream);
149 
150  /**
151  * Destructs this scoped object and restores the stream position of the original input bitstream object.
152  */
153  inline ~ScopedInputBitstream();
154 
155  protected:
156 
157  /// The original stream position of the original bitstream object.
158  unsigned long long streamStartPosition_;
159 };
160 
161 /**
162  * This class implements an output bitstream.
163  * The implementation of the input bitstream is not thread-safe, thus ensure that the internal input stream object is not used within several threads concurrently.<br>
164  * The bitstream support specific data type, see InputBitstream for detailed information.
165  * @ingroup io
166  */
167 class OCEAN_IO_EXPORT OutputBitstream
168 {
169  public:
170 
171  /**
172  * Creates a new output bitstream object.
173  * @param stream The output stream object that is encapsulated by this object
174  */
175  OutputBitstream(std::ostream& stream);
176 
177  /**
178  * Writes a data object to the stream and moves the internal position inside the bitstream accordingly.
179  * If the write process fails, the new position of the bitstream may be arbitrary.<br>
180  * Beware: It's recommended to provide the template argument explicitly to avoid type ambiguities.<br>
181  * @param value The value that will be written
182  * @return True, if the value could be written successfully
183  * @tparam T the data type that is written, ensure that only supported data types are applied
184  */
185  template <typename T>
186  bool write(const T& value);
187 
188  /**
189  * Writes a defined memory block from a given buffer into the stream and moves the internal position inside the bitstream accordingly.
190  * If the write process fails, the new position of the bitstream may be arbitrary.
191  * @param data The buffer that will be written, may be nullptr if size is 0
192  * @param size The number of bytes that will be written, with range [0, infinity
193  * @return True, if succeeded
194  */
195  bool write(const void* data, const size_t size);
196 
197  /**
198  * Returns the current size of the bitstream, in bytes.
199  * @return The current stream size in bytes, -1 if the current size cannot be determined
200  */
201  unsigned long long size() const;
202 
203  /**
204  * Returns whether this bitstream object is valid and can be used.
205  * @return True, if so
206  */
207  explicit inline operator bool() const;
208 
209  protected:
210 
211  /// The internal output stream object that this object encapsulates.
212  std::ostream& outputStream;
213 };
214 
215 /**
216  * This class implements a tag that allows to identify specific objects in an input/output stream.
217  * A tag is an 64bit identifier that identifies one unique object type.<br>
218  * @ingroup io
219  */
220 class OCEAN_IO_EXPORT Tag
221 {
222  protected:
223 
224 #ifdef OCEAN_DEBUG
225 
226  /**
227  * This class implements a tag manager that allows to ensure that tags are not defined twice.
228  */
230  {
231  protected:
232 
233  /**
234  * Definition of a set holding tag values.
235  */
236  typedef std::set<unsigned long long> TagSet;
237 
238  public:
239 
240  /**
241  * Registers a new tag value.
242  * @param tag The tag value that will be registered
243  * @return True, if the tag value hasn't been registered before
244  */
245  static inline bool registerTag(const unsigned long long tag);
246 
247  protected:
248 
249  /// The set of registered tag values.
251  };
252 
253 #endif // OCEAN_DEBUG
254 
255  public:
256 
257  /**
258  * Creates a new invalid tag object.
259  */
260  inline Tag();
261 
262  /**
263  * Creates a new tag object by a given eight character string.
264  * Use this constructor only for the definition of a tag.
265  * @param tagString A string with exactly eight characters which are used to define the unique tag value
266  */
267  inline explicit Tag(const char tagString[8]);
268 
269  /**
270  * Returns whether two tag objects are identical.
271  * @param tag The second tag to be compared
272  * @return True, if so
273  */
274  inline bool operator==(const Tag& tag) const;
275 
276  /**
277  * Returns whether two tag objects are not identical.
278  * @param tag The second tag to be compared
279  * @return True, if so
280  */
281  inline bool operator!=(const Tag& tag) const;
282 
283  /**
284  * Returns the unique 64 bit tag value of this tag object.
285  * @return The tag value
286  */
287  inline unsigned long long value() const;
288 
289  /**
290  * Returns the unique 64 bit tag value of this tag object.
291  * @return The tag value
292  */
293  inline unsigned long long& value();
294 
295  /**
296  * Writes a tag to a bitstream.
297  * @param bitstream The bitstream to which the tag is written
298  * @param tag The tag to be written
299  * @return True, if succeeded
300  */
301  static bool writeTag(OutputBitstream& bitstream, const Tag& tag);
302 
303  /**
304  * Reads a tag from a bitstream.
305  * The position in the bitstream is moved forward after the tag has been read.<br>
306  * @param bitstream The bitstream from which the tag is read
307  * @param tag The resulting bitstream
308  * @return True, if succeeded
309  */
310  static bool readTag(InputBitstream& bitstream, Tag& tag);
311 
312  /**
313  * Reads (only a look) a tag from a bitstream.
314  * The position in the bitstream is not modified.<br>
315  * @param bitstream The bitstream from which the tag is read
316  * @param tag The resulting bitstream
317  * @return True, if succeeded
318  */
319  static bool lookTag(InputBitstream& bitstream, Tag& tag);
320 
321  /**
322  * Reads a tag from a bitstream and checks whether the tag is identical with an expectedTag tag.<br>
323  * The position in the bitstream is moved forward after the tag has been read.<br>
324  * @param bitstream The bitstream from which the tag is read
325  * @param expectedTag The expected tag that should match the tag that has been read
326  * @return True, if received tag and the expected tag are identical
327  */
328  static bool readAndCheckTag(InputBitstream& bitstream, const Tag& expectedTag);
329 
330  /**
331  * Reads (only a look) a tag from a bitstream and checks whether the tag is identical with an expectedTag tag.<br>
332  * The position in the bitstream is not modified.<br>
333  * @param bitstream The bitstream from which the tag is read
334  * @param expectedTag The expected tag that should match the tag that has been read
335  * @return True, if received tag and the expected tag are identical
336  */
337  static bool lookAndCheckTag(InputBitstream& bitstream, const Tag& expectedTag);
338 
339  /**
340  * Converts a string with exactly eight characters to a unique tag value.
341  * @param tagString The string with eight characters to be converted
342  * @return The resulting tag value
343  */
344  static constexpr unsigned long long string2tag(const char tagString[8]);
345 
346  protected:
347 
348  /// The tag value of this tag object.
349  unsigned long long tagValue_;
350 };
351 
353  InputBitstream(stream),
354  streamStartPosition_((unsigned long long)(-1))
355 {
357 }
358 
360 {
361  if (streamStartPosition_ != (unsigned long long)(-1))
362  {
364  }
365 }
366 
367 inline InputBitstream::operator bool() const
368 {
369  return inputStream.good();
370 }
371 
372 inline OutputBitstream::operator bool() const
373 {
374  return outputStream.good();
375 }
376 
377 inline Tag::Tag() :
378  tagValue_(0ull)
379 {
380  // nothing to do here
381 }
382 
383 inline Tag::Tag(const char tagString[8]) :
384  tagValue_(string2tag(tagString))
385 {
386  ocean_assert(TagManager::registerTag(tagValue_));
387 }
388 
389 inline bool Tag::operator==(const Tag& tag) const
390 {
391  return tagValue_ == tag.tagValue_;
392 }
393 
394 inline bool Tag::operator!=(const Tag& tag) const
395 {
396  return !(*this == tag);
397 }
398 
399 inline unsigned long long Tag::value() const
400 {
401  return tagValue_;
402 }
403 
404 inline unsigned long long& Tag::value()
405 {
406  return tagValue_;
407 }
408 
409 constexpr unsigned long long Tag::string2tag(const char tagString[8])
410 {
411  ocean_assert(tagString[0] != 0 && tagString[1] != 0 && tagString[2] != 0 && tagString[3] != 0
412  && tagString[4] != 0 && tagString[5] != 0 && tagString[6] != 0 && tagString[7] != 0);
413 
414  return ((unsigned long long)tagString[0] << 0ull)
415  | ((unsigned long long)tagString[1] << 8ull)
416  | ((unsigned long long)tagString[2] << 16ull)
417  | ((unsigned long long)tagString[3] << 24ull)
418  | ((unsigned long long)tagString[4] << 32ull)
419  | ((unsigned long long)tagString[5] << 40ull)
420  | ((unsigned long long)tagString[6] << 48ull)
421  | ((unsigned long long)tagString[7] << 56ull);
422 }
423 
424 #ifdef OCEAN_DEBUG
425 
426 inline bool Tag::TagManager::registerTag(const unsigned long long tag)
427 {
428  static TagManager manager;
429 
430  const bool newTag = manager.tagsSet.find(tag) == manager.tagsSet.end();
431  manager.tagsSet.insert(tag);
432 
433  return newTag;
434 }
435 
436 #endif // OCEAN_DEBUG
437 
438 }
439 
440 }
441 
442 #endif // META_OCEAN_IO_BITSTREAM_H
This class implements an input bitstream.
Definition: Bitstream.h:51
T readDefault(const T &defaultValue)
Reads a value from the bitstream and moves the internal position inside the bitstream accordingly.
std::istream & inputStream
The internal input stream object that this object encapsulates.
Definition: Bitstream.h:132
bool read(T &value)
Reads a value from the bitstream and moves the internal position inside the bitstream accordingly.
unsigned long long position() const
Returns the current position inside the bitstream, in bytes counting from the beginning of the stream...
bool read(void *data, const size_t size)
Reads a defined memory block from the stream into a given buffer and moves the internal position insi...
unsigned long long size() const
Returns the current size of the bitstream, in bytes.
InputBitstream(std::istream &stream)
Creates a new bitstream object.
bool look(T &value)
Reads a value from the bitstream but does not move the internal position inside the bitstream.
bool setPosition(const unsigned long long position)
Sets the current position inside the bitstream explicitly.
This class implements an output bitstream.
Definition: Bitstream.h:168
unsigned long long size() const
Returns the current size of the bitstream, in bytes.
OutputBitstream(std::ostream &stream)
Creates a new output bitstream object.
bool write(const void *data, const size_t size)
Writes a defined memory block from a given buffer into the stream and moves the internal position ins...
bool write(const T &value)
Writes a data object to the stream and moves the internal position inside the bitstream accordingly.
std::ostream & outputStream
The internal output stream object that this object encapsulates.
Definition: Bitstream.h:212
This class implements a scoped input bitstream that allows to read content from a bitstream while the...
Definition: Bitstream.h:142
~ScopedInputBitstream()
Destructs this scoped object and restores the stream position of the original input bitstream object.
Definition: Bitstream.h:359
unsigned long long streamStartPosition_
The original stream position of the original bitstream object.
Definition: Bitstream.h:158
ScopedInputBitstream(InputBitstream &stream)
Creates a new scoped input bitstream object from a given input bitstream object and stores the curren...
Definition: Bitstream.h:352
This class implements a tag manager that allows to ensure that tags are not defined twice.
Definition: Bitstream.h:230
std::set< unsigned long long > TagSet
Definition of a set holding tag values.
Definition: Bitstream.h:236
TagSet tagsSet
The set of registered tag values.
Definition: Bitstream.h:250
static bool registerTag(const unsigned long long tag)
Registers a new tag value.
Definition: Bitstream.h:426
This class implements a tag that allows to identify specific objects in an input/output stream.
Definition: Bitstream.h:221
static bool writeTag(OutputBitstream &bitstream, const Tag &tag)
Writes a tag to a bitstream.
static constexpr unsigned long long string2tag(const char tagString[8])
Converts a string with exactly eight characters to a unique tag value.
Definition: Bitstream.h:409
static bool lookTag(InputBitstream &bitstream, Tag &tag)
Reads (only a look) a tag from a bitstream.
static bool lookAndCheckTag(InputBitstream &bitstream, const Tag &expectedTag)
Reads (only a look) a tag from a bitstream and checks whether the tag is identical with an expectedTa...
static bool readAndCheckTag(InputBitstream &bitstream, const Tag &expectedTag)
Reads a tag from a bitstream and checks whether the tag is identical with an expectedTag tag.
bool operator==(const Tag &tag) const
Returns whether two tag objects are identical.
Definition: Bitstream.h:389
unsigned long long value() const
Returns the unique 64 bit tag value of this tag object.
Definition: Bitstream.h:399
bool operator!=(const Tag &tag) const
Returns whether two tag objects are not identical.
Definition: Bitstream.h:394
Tag()
Creates a new invalid tag object.
Definition: Bitstream.h:377
static bool readTag(InputBitstream &bitstream, Tag &tag)
Reads a tag from a bitstream.
unsigned long long tagValue_
The tag value of this tag object.
Definition: Bitstream.h:349
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15