1//
2// BinaryReader.h
3//
4// Library: Foundation
5// Package: Streams
6// Module: BinaryReaderWriter
7//
8// Definition of the BinaryReader class.
9//
10// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Foundation_BinaryReader_INCLUDED
18#define Foundation_BinaryReader_INCLUDED
19
20
21#include "Poco/Foundation.h"
22#include "Poco/Buffer.h"
23#include "Poco/MemoryStream.h"
24#include "Poco/ByteOrder.h"
25#include <vector>
26#include <istream>
27
28
29namespace Poco {
30
31
32class TextEncoding;
33class TextConverter;
34
35
36class Foundation_API BinaryReader
37 /// This class reads basic types (and std::vectors thereof)
38 /// in binary form into an input stream.
39 /// It provides an extractor-based interface similar to istream.
40 /// The reader also supports automatic conversion from big-endian
41 /// (network byte order) to little-endian and vice-versa.
42 /// Use a BinaryWriter to create a stream suitable for a BinaryReader.
43{
44public:
45 enum StreamByteOrder
46 {
47 NATIVE_BYTE_ORDER = 1, /// the host's native byte-order
48 BIG_ENDIAN_BYTE_ORDER = 2, /// big-endian (network) byte-order
49 NETWORK_BYTE_ORDER = 2, /// big-endian (network) byte-order
50 LITTLE_ENDIAN_BYTE_ORDER = 3, /// little-endian byte-order
51 UNSPECIFIED_BYTE_ORDER = 4 /// unknown, byte-order will be determined by reading the byte-order mark
52 };
53
54 BinaryReader(std::istream& istr, StreamByteOrder byteOrder = NATIVE_BYTE_ORDER);
55 /// Creates the BinaryReader.
56
57 BinaryReader(std::istream& istr, TextEncoding& encoding, StreamByteOrder byteOrder = NATIVE_BYTE_ORDER);
58 /// Creates the BinaryReader using the given TextEncoding.
59 ///
60 /// Strings will be converted from the specified encoding
61 /// to the currently set global encoding (see Poco::TextEncoding::global()).
62
63 ~BinaryReader();
64 /// Destroys the BinaryReader.
65
66 BinaryReader& operator >> (bool& value);
67 BinaryReader& operator >> (char& value);
68 BinaryReader& operator >> (unsigned char& value);
69 BinaryReader& operator >> (signed char& value);
70 BinaryReader& operator >> (short& value);
71 BinaryReader& operator >> (unsigned short& value);
72 BinaryReader& operator >> (int& value);
73 BinaryReader& operator >> (unsigned int& value);
74#ifndef POCO_LONG_IS_64_BIT
75 BinaryReader& operator >> (long& value);
76 BinaryReader& operator >> (unsigned long& value);
77#endif // POCO_LONG_IS_64_BIT
78 BinaryReader& operator >> (float& value);
79 BinaryReader& operator >> (double& value);
80 BinaryReader& operator >> (Int64& value);
81 BinaryReader& operator >> (UInt64& value);
82 BinaryReader& operator >> (std::string& value);
83
84 template <typename T>
85 BinaryReader& operator >> (std::vector<T>& value)
86 {
87 Poco::UInt32 size(0);
88 T elem;
89
90 *this >> size;
91 if (!good()) return *this;
92 value.reserve(size);
93 while (this->good() && size-- > 0)
94 {
95 *this >> elem;
96 value.push_back(elem);
97 }
98 return *this;
99 }
100
101 void read7BitEncoded(UInt32& value);
102 /// Reads a 32-bit unsigned integer in compressed format.
103 /// See BinaryWriter::write7BitEncoded() for a description
104 /// of the compression algorithm.
105
106 void read7BitEncoded(UInt64& value);
107 /// Reads a 64-bit unsigned integer in compressed format.
108 /// See BinaryWriter::write7BitEncoded() for a description
109 /// of the compression algorithm.
110
111 void readRaw(std::streamsize length, std::string& value);
112 /// Reads length bytes of raw data into value.
113
114 void readRaw(char* buffer, std::streamsize length);
115 /// Reads length bytes of raw data into buffer.
116
117 void readBOM();
118 /// Reads a byte-order mark from the stream and configures
119 /// the reader for the encountered byte order.
120 /// A byte-order mark is a 16-bit integer with a value of 0xFEFF,
121 /// written in host byte order.
122
123 bool good();
124 /// Returns _istr.good();
125
126 bool fail();
127 /// Returns _istr.fail();
128
129 bool bad();
130 /// Returns _istr.bad();
131
132 bool eof();
133 /// Returns _istr.eof();
134
135 std::istream& stream() const;
136 /// Returns the underlying stream.
137
138 StreamByteOrder byteOrder() const;
139 /// Returns the byte-order used by the reader, which is
140 /// either BIG_ENDIAN_BYTE_ORDER or LITTLE_ENDIAN_BYTE_ORDER.
141
142 void setExceptions(std::ios_base::iostate st = (std::istream::failbit | std::istream::badbit));
143 /// Sets the stream to throw exception on specified state (default failbit and badbit);
144
145 std::streamsize available() const;
146 /// Returns the number of available bytes in the stream.
147
148private:
149
150#ifdef POCO_OS_FAMILY_WINDOWS
151#pragma warning(push)
152#pragma warning(disable : 4800) // forcing value to bool 'true' or 'false' (performance warning)
153#endif
154
155 template<typename T>
156 BinaryReader& read(T& value, bool flipBytes)
157 {
158 _istr.read((char*) &value, sizeof(value));
159 if (flipBytes) value = ByteOrder::flipBytes(value);
160 return *this;
161 }
162
163#ifdef POCO_OS_FAMILY_WINDOWS
164#pragma warning(pop)
165#endif
166
167 template<typename T>
168 void read7BitEncoded(T& value)
169 {
170 char c;
171 value = 0;
172 int s = 0;
173 do
174 {
175 c = 0;
176 _istr.read(&c, 1);
177 T x = (c & 0x7F);
178 x <<= s;
179 value += x;
180 s += 7;
181 }
182 while (c & 0x80);
183 }
184
185 std::istream& _istr;
186 bool _flipBytes;
187 TextConverter* _pTextConverter;
188};
189
190
191template <typename T>
192class BasicMemoryBinaryReader : public BinaryReader
193 /// A convenient wrapper for using Buffer and MemoryStream with BinaryReader.
194{
195public:
196 BasicMemoryBinaryReader(const Buffer<T>& dataBuffer, StreamByteOrder order = NATIVE_BYTE_ORDER):
197 BinaryReader(_istr, order),
198 _data(dataBuffer),
199 _istr(dataBuffer.begin(), dataBuffer.capacity())
200 {
201 }
202
203 BasicMemoryBinaryReader(const Buffer<T>& dataBuffer, TextEncoding& encoding, StreamByteOrder order = NATIVE_BYTE_ORDER):
204 BinaryReader(_istr, encoding, order),
205 _data(dataBuffer),
206 _istr(dataBuffer.begin(), dataBuffer.capacity())
207 {
208 }
209
210 ~BasicMemoryBinaryReader()
211 {
212 }
213
214 const Buffer<T>& data() const
215 {
216 return _data;
217 }
218
219 const MemoryInputStream& stream() const
220 {
221 return _istr;
222 }
223
224 MemoryInputStream& stream()
225 {
226 return _istr;
227 }
228
229private:
230 const Buffer<T>& _data;
231 MemoryInputStream _istr;
232};
233
234
235typedef BasicMemoryBinaryReader<char> MemoryBinaryReader;
236
237
238//
239// inlines
240//
241
242
243inline bool BinaryReader::good()
244{
245 return _istr.good();
246}
247
248
249inline bool BinaryReader::fail()
250{
251 return _istr.fail();
252}
253
254
255inline bool BinaryReader::bad()
256{
257 return _istr.bad();
258}
259
260
261inline bool BinaryReader::eof()
262{
263 return _istr.eof();
264}
265
266
267inline std::istream& BinaryReader::stream() const
268{
269 return _istr;
270}
271
272
273inline BinaryReader::StreamByteOrder BinaryReader::byteOrder() const
274{
275#if defined(POCO_ARCH_BIG_ENDIAN)
276 return _flipBytes ? LITTLE_ENDIAN_BYTE_ORDER : BIG_ENDIAN_BYTE_ORDER;
277#else
278 return _flipBytes ? BIG_ENDIAN_BYTE_ORDER : LITTLE_ENDIAN_BYTE_ORDER;
279#endif
280}
281
282
283inline void BinaryReader::setExceptions(std::ios_base::iostate st)
284{
285 _istr.exceptions(st);
286}
287
288
289inline std::streamsize BinaryReader::available() const
290{
291 return _istr.rdbuf()->in_avail();
292}
293
294
295} // namespace Poco
296
297
298#endif // Foundation_BinaryReader_INCLUDED
299