Coverage Report

Created: 2025-07-12 06:36

/src/poco/Foundation/include/Poco/BinaryWriter.h
Line
Count
Source (jump to first uncovered line)
1
//
2
// BinaryWriter.h
3
//
4
// Library: Foundation
5
// Package: Streams
6
// Module:  BinaryReaderWriter
7
//
8
// Definition of the BinaryWriter 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_BinaryWriter_INCLUDED
18
#define Foundation_BinaryWriter_INCLUDED
19
20
21
#include "Poco/Foundation.h"
22
#include "Poco/Buffer.h"
23
#include "Poco/MemoryStream.h"
24
#include <vector>
25
#include <ostream>
26
27
28
namespace Poco {
29
30
31
class TextEncoding;
32
class TextConverter;
33
34
35
class Foundation_API BinaryWriter
36
  /// This class writes basic types (and std::vectors of these)
37
  /// in binary form into an output stream.
38
  /// It provides an inserter-based interface similar to ostream.
39
  /// The writer also supports automatic conversion from big-endian
40
  /// (network byte order) to little-endian and vice-versa.
41
  /// Use a BinaryReader to read from a stream created by a BinaryWriter.
42
  /// Be careful when exchanging data between systems with different
43
  /// data type sizes (e.g., 32-bit and 64-bit architectures), as the sizes
44
  /// of some of the basic types may be different. For example, writing a
45
  /// long integer on a 64-bit system and reading it on a 32-bit system
46
  /// may yield an incorrent result. Use fixed-size types (Int32, Int64, etc.)
47
  /// in such a case.
48
{
49
public:
50
  enum StreamByteOrder
51
  {
52
    NATIVE_BYTE_ORDER        = 1, /// the host's native byte-order
53
    BIG_ENDIAN_BYTE_ORDER    = 2, /// big-endian (network) byte-order
54
    NETWORK_BYTE_ORDER       = 2, /// big-endian (network) byte-order
55
    LITTLE_ENDIAN_BYTE_ORDER = 3  /// little-endian byte-order
56
  };
57
58
  static const std::streamsize  DEFAULT_MAX_CSTR_LENGTH { 1024 };
59
60
  BinaryWriter(std::ostream& ostr, StreamByteOrder byteOrder = NATIVE_BYTE_ORDER);
61
    /// Creates the BinaryWriter.
62
63
  BinaryWriter(std::ostream& ostr, TextEncoding& encoding, StreamByteOrder byteOrder = NATIVE_BYTE_ORDER);
64
    /// Creates the BinaryWriter using the given TextEncoding.
65
    ///
66
    /// Strings will be converted from the currently set global encoding
67
    /// (see Poco::TextEncoding::global()) to the specified encoding.
68
69
  ~BinaryWriter();
70
    /// Destroys the BinaryWriter.
71
72
  BinaryWriter& operator << (bool value);
73
  BinaryWriter& operator << (char value);
74
  BinaryWriter& operator << (unsigned char value);
75
  BinaryWriter& operator << (signed char value);
76
  BinaryWriter& operator << (short value);
77
  BinaryWriter& operator << (unsigned short value);
78
  BinaryWriter& operator << (int value);
79
  BinaryWriter& operator << (unsigned int value);
80
  BinaryWriter& operator << (long value);
81
  BinaryWriter& operator << (unsigned long value);
82
  BinaryWriter& operator << (float value);
83
  BinaryWriter& operator << (double value);
84
85
#if defined(POCO_HAVE_INT64)
86
  BinaryWriter& operator << (long long value);
87
  BinaryWriter& operator << (unsigned long long value);
88
#endif
89
90
  BinaryWriter& operator << (const std::string& value);
91
  BinaryWriter& operator << (const char* value);
92
93
  template <typename T>
94
  BinaryWriter& operator << (const std::vector<T>& value)
95
  {
96
    Poco::UInt32 size(static_cast<Poco::UInt32>(value.size()));
97
98
    *this << size;
99
    for (const auto& v: value)
100
    {
101
      *this << v;
102
    }
103
104
    return *this;
105
  }
106
107
  void write7BitEncoded(UInt32 value);
108
    /// Writes a 32-bit unsigned integer in a compressed format.
109
    /// The value is written out seven bits at a time, starting
110
    /// with the seven least-significant bits.
111
    /// The high bit of a byte indicates whether there are more bytes to be
112
    /// written after this one.
113
    /// If value will fit in seven bits, it takes only one byte of space.
114
    /// If value will not fit in seven bits, the high bit is set on the first byte and
115
    /// written out. value is then shifted by seven bits and the next byte is written.
116
    /// This process is repeated until the entire integer has been written.
117
118
#if defined(POCO_HAVE_INT64)
119
  void write7BitEncoded(UInt64 value);
120
    /// Writes a 64-bit unsigned integer in a compressed format.
121
    /// The value written out seven bits at a time, starting
122
    /// with the seven least-significant bits.
123
    /// The high bit of a byte indicates whether there are more bytes to be
124
    /// written after this one.
125
    /// If value will fit in seven bits, it takes only one byte of space.
126
    /// If value will not fit in seven bits, the high bit is set on the first byte and
127
    /// written out. value is then shifted by seven bits and the next byte is written.
128
    /// This process is repeated until the entire integer has been written.
129
#endif
130
131
  void writeRaw(const std::string& rawData);
132
    /// Writes the string as-is to the stream.
133
134
  void writeRaw(const char* buffer, std::streamsize length);
135
    /// Writes length raw bytes from the given buffer to the stream.
136
137
  void writeCString(const char* cString, std::streamsize maxLength = DEFAULT_MAX_CSTR_LENGTH);
138
    /// Writes zero-terminated C-string.
139
140
  void writeBOM();
141
    /// Writes a byte-order mark to the stream. A byte order mark is
142
    /// a 16-bit integer with a value of 0xFEFF, written in host byte-order.
143
    /// A BinaryReader uses the byte-order mark to determine the byte-order
144
    /// of the stream.
145
146
  void flush();
147
    /// Flushes the underlying stream.
148
149
  bool good();
150
    /// Returns _ostr.good();
151
152
  bool fail();
153
    /// Returns _ostr.fail();
154
155
  bool bad();
156
    /// Returns _ostr.bad();
157
158
  std::ostream& stream() const;
159
    /// Returns the underlying stream.
160
161
  StreamByteOrder byteOrder() const;
162
    /// Returns the byte ordering used by the writer, which is
163
    /// either BIG_ENDIAN_BYTE_ORDER or LITTLE_ENDIAN_BYTE_ORDER.
164
165
private:
166
  std::ostream&  _ostr;
167
  bool           _flipBytes;
168
  TextConverter* _pTextConverter;
169
};
170
171
172
template <typename T>
173
class BasicMemoryBinaryWriter: public BinaryWriter
174
  /// A convenient wrapper for using Buffer and MemoryStream with BinarWriter.
175
{
176
public:
177
  BasicMemoryBinaryWriter(Buffer<T>& data, StreamByteOrder byteOrder = NATIVE_BYTE_ORDER):
178
    BinaryWriter(_ostr, byteOrder),
179
    _data(data),
180
    _ostr(data.begin(), data.capacity())
181
  {
182
  }
183
184
  BasicMemoryBinaryWriter(Buffer<T>& data, TextEncoding& encoding, StreamByteOrder byteOrder = NATIVE_BYTE_ORDER):
185
    BinaryWriter(_ostr, encoding, byteOrder),
186
    _data(data),
187
    _ostr(data.begin(), data.capacity())
188
  {
189
  }
190
191
  ~BasicMemoryBinaryWriter()
192
  {
193
    try
194
    {
195
      flush();
196
    }
197
    catch (...)
198
    {
199
      poco_unexpected();
200
    }
201
  }
202
203
  Buffer<T>& data()
204
  {
205
    return _data;
206
  }
207
208
  const Buffer<T>& data() const
209
  {
210
    return _data;
211
  }
212
213
  const MemoryOutputStream& stream() const
214
  {
215
    return _ostr;
216
  }
217
218
  MemoryOutputStream& stream()
219
  {
220
    return _ostr;
221
  }
222
223
private:
224
  Buffer<T>& _data;
225
  MemoryOutputStream _ostr;
226
};
227
228
using MemoryBinaryWriter = BasicMemoryBinaryWriter<char>;
229
230
//
231
// inlines
232
//
233
234
235
inline std::ostream& BinaryWriter::stream() const
236
0
{
237
0
  return _ostr;
238
0
}
239
240
241
inline bool BinaryWriter::good()
242
0
{
243
0
  return _ostr.good();
244
0
}
245
246
247
inline bool BinaryWriter::fail()
248
0
{
249
0
  return _ostr.fail();
250
0
}
251
252
253
inline bool BinaryWriter::bad()
254
0
{
255
0
  return _ostr.bad();
256
0
}
257
258
259
inline BinaryWriter::StreamByteOrder BinaryWriter::byteOrder() const
260
0
{
261
0
#if defined(POCO_ARCH_BIG_ENDIAN)
262
0
  return _flipBytes ? LITTLE_ENDIAN_BYTE_ORDER : BIG_ENDIAN_BYTE_ORDER;
263
0
#else
264
0
  return _flipBytes ? BIG_ENDIAN_BYTE_ORDER : LITTLE_ENDIAN_BYTE_ORDER;
265
0
#endif
266
0
}
267
268
269
} // namespace Poco
270
271
272
#endif // Foundation_BinaryWriter_INCLUDED