roo_io
API Documentation for roo_io
Loading...
Searching...
No Matches
write.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstring>
4#include <limits>
5#include <string>
6
7#include "roo_backport.h"
8#include "roo_backport/string_view.h"
11#include "roo_io/data/ieee754.h"
12
13namespace roo_io {
14
15// Unsigned.
16
17// Writes an unsigned 8-bit int to the specified iterator.
18template <typename OutputIterator>
19constexpr void WriteU8(OutputIterator& out, uint8_t v) {
20 out.write((byte)(v >> 0));
21}
22
23// Writes a big-endian unsigned 16-bit int to the specified iterator.
24template <typename OutputIterator>
26 out.write((byte)(v >> 8));
27 out.write((byte)(v >> 0));
28}
29
30// Writes a little-endian unsigned 16-bit int to the specified iterator.
31template <typename OutputIterator>
33 out.write((byte)(v >> 0));
34 out.write((byte)(v >> 8));
35}
36
37// Writes a big-endian unsigned 24-bit int to the specified iterator.
38template <typename OutputIterator>
40 out.write((byte)(v >> 16));
41 out.write((byte)(v >> 8));
42 out.write((byte)(v >> 0));
43}
44
45// Writes a little-endian unsigned 24-bit int to the specified iterator.
46template <typename OutputIterator>
48 out.write((byte)(v >> 0));
49 out.write((byte)(v >> 8));
50 out.write((byte)(v >> 16));
51}
52
53// Writes a big-endian unsigned 32-bit int to the specified iterator.
54template <typename OutputIterator>
56 out.write((byte)(v >> 24));
57 out.write((byte)(v >> 16));
58 out.write((byte)(v >> 8));
59 out.write((byte)(v >> 0));
60}
61
62// Writes a little-endian unsigned 32-bit int to the specified iterator.
63template <typename OutputIterator>
65 out.write((byte)(v >> 0));
66 out.write((byte)(v >> 8));
67 out.write((byte)(v >> 16));
68 out.write((byte)(v >> 24));
69}
70
71// Writes a big-endian unsigned 64-bit int to the specified iterator.
72template <typename OutputIterator>
74 WriteBeU32(out, (v >> 32) & 0xFFFFFFFFLL);
75 WriteBeU32(out, (v >> 0) & 0xFFFFFFFFLL);
76}
77
78// Writes a little-endian unsigned 64-bit int to the specified iterator.
79template <typename OutputIterator>
81 WriteLeU32(out, (v >> 0) & 0xFFFFFFFFLL);
82 WriteLeU32(out, (v >> 32) & 0xFFFFFFFFLL);
83}
84
85// Signed.
86
87// Writes a signed 8-bit int to the specified iterator.
88template <typename OutputIterator>
89constexpr void WriteS8(OutputIterator& out, int8_t v) {
91}
92
93// Writes a big-endian signed 16-bit int to the specified iterator.
94template <typename OutputIterator>
97}
98
99// Writes a little-endian signed 16-bit int to the specified iterator.
100template <typename OutputIterator>
103}
104
105// Writes a big-endian signed 24-bit int to the specified iterator.
106template <typename OutputIterator>
109}
110
111// Writes a little-endian signed 24-bit int to the specified iterator.
112template <typename OutputIterator>
115}
116
117// Writes a big-endian signed 32-bit int to the specified iterator.
118template <typename OutputIterator>
121}
122
123// Writes a little-endian signed 32-bit int to the specified iterator.
124template <typename OutputIterator>
127}
128
129// Writes a big-endian signed 64-bit int to the specified iterator.
130template <typename OutputIterator>
133}
134
135// Writes a little-endian signed 64-bit int to the specified iterator.
136template <typename OutputIterator>
139}
140
141#if ROO_IO_IEEE754
142// Writes a big-endian IEEE754 float to the specified iterator.
143template <typename OutputIterator>
144inline void WriteBeFloat(OutputIterator& out, float v) {
145 static_assert(sizeof(float) == sizeof(uint32_t),
146 "WriteBeFloat requires 32-bit float.");
147 static_assert(std::numeric_limits<float>::is_iec559,
148 "WriteBeFloat requires IEEE754 float.");
150 memcpy(&bits, &v, sizeof(bits));
152}
153
154// Writes a little-endian IEEE754 float to the specified iterator.
155template <typename OutputIterator>
156inline void WriteLeFloat(OutputIterator& out, float v) {
157 static_assert(sizeof(float) == sizeof(uint32_t),
158 "WriteLeFloat requires 32-bit float.");
159 static_assert(std::numeric_limits<float>::is_iec559,
160 "WriteLeFloat requires IEEE754 float.");
162 memcpy(&bits, &v, sizeof(bits));
164}
165
166// Writes a big-endian IEEE754 double to the specified iterator.
167template <typename OutputIterator>
168inline void WriteBeDouble(OutputIterator& out, double v) {
169 static_assert(sizeof(double) == sizeof(uint64_t),
170 "WriteBeDouble requires 64-bit double.");
171 static_assert(std::numeric_limits<double>::is_iec559,
172 "WriteBeDouble requires IEEE754 double.");
174 memcpy(&bits, &v, sizeof(bits));
176}
177
178// Writes a little-endian IEEE754 double to the specified iterator.
179template <typename OutputIterator>
180inline void WriteLeDouble(OutputIterator& out, double v) {
181 static_assert(sizeof(double) == sizeof(uint64_t),
182 "WriteLeDouble requires 64-bit double.");
183 static_assert(std::numeric_limits<double>::is_iec559,
184 "WriteLeDouble requires IEEE754 double.");
186 memcpy(&bits, &v, sizeof(bits));
188}
189#endif // ROO_IO_IEEE754
190
191// Writes `count` bytes from the `source` to the output iterator. Returns the
192// number of bytes successfully written. If the returned value is smaller than
193// `count`, it indicates that an I/O error has occurred. The `status()` of the
194// underlying iterator can be used to determine the cause.
195template <typename OutputIterator>
196size_t WriteByteArray(OutputIterator& out, const byte* source, size_t count) {
197 size_t written_total = 0;
198 while (count > 0) {
199 size_t written_now = out.write(source, count);
200 if (written_now == 0) break;
204 }
205 return written_total;
206}
207
208// Writes an unsigned 64-bit integer, encoded using variable-length encoding as
209// defined by Google protocol buffers. (Small numbers take little space; numbers
210// up to 127 take 1 byte).
211template <typename OutputIterator>
213 byte buffer[10];
214 if (data <= 0x7F) {
215 // Fast-path and special-case for single-byte data.
216 out.write((byte)data);
217 return;
218 }
219
220 size_t size = 0;
221 while (data > 0) {
222 buffer[size++] = ((byte)data & byte{0x7F}) | byte{0x80};
223 data >>= 7;
224 }
225 buffer[size - 1] &= byte{0x7F};
226 out.write(buffer, size);
227}
228
229// Write a string view, using a portable string representation (varint length
230// followed by the character array). Works for std::string.
231template <typename OutputIterator>
232void WriteString(OutputIterator& itr, roo::string_view data) {
233 WriteVarU64(itr, data.size());
234 if (!data.empty()) {
235 WriteByteArray(itr, (const byte*)data.data(), data.size());
236 }
237}
238
239// Write a C string, using a portable string representation (varint length
240// followed by the character array). Disambiguation of WriteString, since
241// both the string view and an Arduino String can be implicitly constructed from
242// a C string.
243template <typename OutputIterator>
244void WriteString(OutputIterator& itr, const char* data) {
245 WriteString(itr, roo::string_view(data));
246}
247
248// Helper to write numbers to output iterators, templated on a byte order.
249template <int ByteOrder>
251
252template <>
254 public:
255 template <typename OutputIterator>
256 constexpr void writeU16(OutputIterator& out, uint16_t v) const {
257 WriteBeU16(out, v);
258 }
259
260 template <typename OutputIterator>
261 constexpr void writeU24(OutputIterator& out, uint32_t v) const {
262 WriteBeU24(out, v);
263 }
264
265 template <typename OutputIterator>
266 constexpr void writeU32(OutputIterator& out, uint32_t v) const {
267 WriteBeU32(out, v);
268 }
269
270 template <typename OutputIterator>
271 constexpr void writeU64(OutputIterator& out, uint64_t v) const {
272 WriteBeU32(out, (v >> 32) & 0xFFFFFFFFLL);
273 WriteBeU32(out, (v >> 0) & 0xFFFFFFFFLL);
274 }
275};
276
277template <>
279 public:
280 template <typename OutputIterator>
281 constexpr void writeU16(OutputIterator& out, uint16_t v) const {
282 WriteLeU16(out, v);
283 }
284
285 template <typename OutputIterator>
286 constexpr void writeU24(OutputIterator& out, uint32_t v) const {
287 WriteLeU24(out, v);
288 }
289
290 template <typename OutputIterator>
291 constexpr void writeU32(OutputIterator& out, uint32_t v) const {
292 WriteLeU32(out, v);
293 }
294
295 template <typename OutputIterator>
296 constexpr void writeU64(OutputIterator& out, uint64_t v) const {
297 WriteLeU32(out, (v >> 0) & 0xFFFFFFFFLL);
298 WriteLeU32(out, (v >> 32) & 0xFFFFFFFFLL);
299 }
300};
301
302#if ROO_IO_IEEE754
303// Helper to write IEEE754 floats/doubles templated on byte order.
304template <int ByteOrder>
305class FloatWriter;
306
307template <>
308class FloatWriter<kBigEndian> {
309 public:
310 template <typename OutputIterator>
311 inline void writeFloat(OutputIterator& out, float v) const {
313 }
314
315 template <typename OutputIterator>
316 inline void writeDouble(OutputIterator& out, double v) const {
318 }
319};
320
321template <>
323 public:
324 template <typename OutputIterator>
325 inline void writeFloat(OutputIterator& out, float v) const {
327 }
328
329 template <typename OutputIterator>
330 inline void writeDouble(OutputIterator& out, double v) const {
332 }
333};
334#endif // ROO_IO_IEEE754
335
336template <typename OutputIterator, ByteOrder byte_order>
338 NumberWriter<byte_order>().writeU16(in, v);
339}
340
341template <typename OutputIterator, ByteOrder byte_order>
343 NumberWriter<byte_order>().writeU24(in, v);
344}
345
346template <typename OutputIterator, ByteOrder byte_order>
348 NumberWriter<byte_order>().writeU32(in, v);
349}
350
351#if ROO_IO_IEEE754
352template <typename OutputIterator, ByteOrder byte_order>
353inline void WriteFloat(OutputIterator& in, float v) {
354 FloatWriter<byte_order>().writeFloat(in, v);
355}
356
357template <typename OutputIterator, ByteOrder byte_order>
358inline void WriteDouble(OutputIterator& in, double v) {
359 FloatWriter<byte_order>().writeDouble(in, v);
360}
361#endif // ROO_IO_IEEE754
362
363// Allows writing platform-native (implementation-dependent) data to an input
364// iterator. T must be default-constructible and have trivial destructor.
365template <typename T>
367 public:
368 // Writes T to the iterator. On failure, the iterator status is updated as
369 // appropriate.
370 template <typename OutputIterator>
371 void write(OutputIterator& out, const T& v) const {
372 WriteByteArray(out, (const byte*)&v, sizeof(v));
373 }
374};
375
376} // namespace roo_io
377
378#if defined(ARDUINO) || defined(String_class_h)
379
380#include "Arduino.h"
381
382// Write an Arduino string, using a portable string representation (varint
383// length followed by the character array).
384namespace roo_io {
385template <typename OutputIterator>
386void WriteString(OutputIterator& itr, const ::String& data) {
387 WriteVarU64(itr, data.length());
388 if (!data.isEmpty()) {
389 WriteByteArray(itr, (const byte*)data.c_str(), data.length());
390 }
391}
392} // namespace roo_io
393#endif
constexpr void writeU24(OutputIterator &out, uint32_t v) const
Definition write.h:261
constexpr void writeU16(OutputIterator &out, uint16_t v) const
Definition write.h:256
constexpr void writeU64(OutputIterator &out, uint64_t v) const
Definition write.h:271
constexpr void writeU32(OutputIterator &out, uint32_t v) const
Definition write.h:266
constexpr void writeU64(OutputIterator &out, uint64_t v) const
Definition write.h:296
constexpr void writeU32(OutputIterator &out, uint32_t v) const
Definition write.h:291
constexpr void writeU24(OutputIterator &out, uint32_t v) const
Definition write.h:286
constexpr void writeU16(OutputIterator &out, uint16_t v) const
Definition write.h:281
Definition byte.h:6
constexpr void WriteLeS64(OutputIterator &out, int64_t v)
Definition write.h:137
constexpr void WriteBeU16(OutputIterator &out, uint16_t v)
Definition write.h:25
constexpr void WriteLeU16(OutputIterator &out, uint16_t v)
Definition write.h:32
constexpr void WriteBeS32(OutputIterator &out, int32_t v)
Definition write.h:119
constexpr void WriteU8(OutputIterator &out, uint8_t v)
Definition write.h:19
constexpr void WriteLeS24(OutputIterator &out, int32_t v)
Definition write.h:113
constexpr void WriteLeS16(OutputIterator &out, int16_t v)
Definition write.h:101
roo::basic_string_view< CharT, Traits > basic_string_view
Definition string_view.h:8
constexpr void WriteU24(OutputIterator &in, uint32_t v)
Definition write.h:342
size_t count
Definition compare.h:45
size_t WriteByteArray(OutputIterator &out, const byte *source, size_t count)
Definition write.h:196
constexpr void WriteBeS24(OutputIterator &out, int32_t v)
Definition write.h:107
constexpr void WriteBeS64(OutputIterator &out, int64_t v)
Definition write.h:131
constexpr void WriteLeU24(OutputIterator &out, uint32_t v)
Definition write.h:47
void WriteVarU64(OutputIterator &out, uint64_t data)
Definition write.h:212
constexpr void WriteLeU32(OutputIterator &out, uint32_t v)
Definition write.h:64
constexpr void WriteBeU64(OutputIterator &out, uint64_t v)
Definition write.h:73
constexpr void WriteBeU24(OutputIterator &out, uint32_t v)
Definition write.h:39
constexpr void WriteU32(OutputIterator &in, uint32_t v)
Definition write.h:347
constexpr void WriteBeU32(OutputIterator &out, uint32_t v)
Definition write.h:55
constexpr void WriteLeS32(OutputIterator &out, int32_t v)
Definition write.h:125
constexpr void WriteU16(OutputIterator &in, uint16_t v)
Definition write.h:337
constexpr void WriteBeS16(OutputIterator &out, int16_t v)
Definition write.h:95
roo::byte byte
Definition byte.h:8
@ kLittleEndian
Definition byte_order.h:16
@ kBigEndian
Definition byte_order.h:17
void WriteString(OutputIterator &itr, roo::string_view data)
Definition write.h:232
constexpr void WriteLeU64(OutputIterator &out, uint64_t v)
Definition write.h:80
constexpr void WriteS8(OutputIterator &out, int8_t v)
Definition write.h:89
void write(OutputIterator &out, const T &v) const
Definition write.h:371