cpp-msgpack-light 0.3.0
A light library to serialize MessagePack.
Loading...
Searching...
No Matches
serialization_buffer.h
Go to the documentation of this file.
1/*
2 * Copyright 2024 MusicScience37 (Kenta Kabashima)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
20#pragma once
21
22#include <cstddef> // IWYU pragma: keep
23#include <cstdint>
24#include <limits>
25#include <stdexcept>
26
29#include "msgpack_light/serialization_buffer_fwd.h" // IWYU pragma: keep
31
32namespace msgpack_light {
33
42public:
47
55 explicit serialization_buffer(output_stream& stream) : buffer_(stream) {}
56
59 serialization_buffer& operator=(const serialization_buffer&) = delete;
60 serialization_buffer& operator=(serialization_buffer&&) = delete;
61
67 ~serialization_buffer() noexcept { flush(); }
68
75 void flush() { buffer_.flush(); }
76
78
83
88 constexpr auto nil_byte = static_cast<unsigned char>(0xC0);
89 put(nil_byte);
90 }
91
93
98
104 void serialize_bool(bool value) {
105 constexpr auto false_byte = static_cast<unsigned char>(0xC2);
106 constexpr auto true_byte = static_cast<unsigned char>(0xC3);
107 if (value) {
108 put(true_byte);
109 } else {
110 put(false_byte);
111 }
112 }
113
115
125
134 void serialize_positive_fixint(std::uint8_t value) {
135 put(static_cast<unsigned char>(value));
136 }
137
146 void serialize_negative_fixint(std::int8_t value) {
147 put(static_cast<unsigned char>(value));
148 }
149
155 void serialize_uint8(std::uint8_t value) {
156 constexpr auto prefix = static_cast<unsigned char>(0xCC);
157 write_in_big_endian(prefix, value);
158 }
159
165 void serialize_uint16(std::uint16_t value) {
166 constexpr auto prefix = static_cast<unsigned char>(0xCD);
167 write_in_big_endian(prefix, value);
168 }
169
175 void serialize_uint32(std::uint32_t value) {
176 constexpr auto prefix = static_cast<unsigned char>(0xCE);
177 write_in_big_endian(prefix, value);
178 }
179
185 void serialize_uint64(std::uint64_t value) {
186 constexpr auto prefix = static_cast<unsigned char>(0xCF);
187 write_in_big_endian(prefix, value);
188 }
189
195 void serialize_int8(std::int8_t value) {
196 constexpr auto prefix = static_cast<unsigned char>(0xD0);
197 write_in_big_endian(prefix, value);
198 }
199
205 void serialize_int16(std::int16_t value) {
206 constexpr auto prefix = static_cast<unsigned char>(0xD1);
207 write_in_big_endian(prefix, value);
208 }
209
215 void serialize_int32(std::int32_t value) {
216 constexpr auto prefix = static_cast<unsigned char>(0xD2);
217 write_in_big_endian(prefix, value);
218 }
219
225 void serialize_int64(std::int64_t value) {
226 constexpr auto prefix = static_cast<unsigned char>(0xD3);
227 write_in_big_endian(prefix, value);
228 }
229
231
236
242 void serialize_float32(float value) {
243 static_assert(std::numeric_limits<float>::is_iec559,
244 "IEEE 754 single precision floating point number is required.");
245 static_assert(sizeof(float) == 4U,
246 "IEEE 754 single precision floating point number is required.");
247
248 constexpr auto prefix = static_cast<unsigned char>(0xCA);
249 write_in_big_endian(prefix, value);
250 }
251
257 void serialize_float64(double value) {
258 static_assert(std::numeric_limits<double>::is_iec559,
259 "IEEE 754 double precision floating point number is required.");
260 // NOLINTNEXTLINE(readability-magic-numbers)
261 static_assert(sizeof(double) == 8U,
262 "IEEE 754 double precision floating point number is required.");
263
264 constexpr auto prefix = static_cast<unsigned char>(0xCB);
265 write_in_big_endian(prefix, value);
266 }
267
269
277
286 void serialize_fixstr_size(std::uint8_t size) {
287 constexpr auto prefix = static_cast<unsigned char>(0xA0);
288 put(prefix | size);
289 }
290
296 void serialize_str8_size(std::uint8_t size) {
297 constexpr auto prefix = static_cast<unsigned char>(0xD9);
298 write_in_big_endian(prefix, size);
299 }
300
306 void serialize_str16_size(std::uint16_t size) {
307 constexpr auto prefix = static_cast<unsigned char>(0xDA);
308 write_in_big_endian(prefix, size);
309 }
310
316 void serialize_str32_size(std::uint32_t size) {
317 constexpr auto prefix = static_cast<unsigned char>(0xDB);
318 write_in_big_endian(prefix, size);
319 }
320
326 void serialize_str_size(std::size_t size) {
327 constexpr auto max_fixstr_size = static_cast<std::size_t>(0b11111U);
328 constexpr auto max_str8_size = static_cast<std::size_t>(0xFF);
329 constexpr auto max_str16_size = static_cast<std::size_t>(0xFFFF);
330
331 if (size <= max_str8_size) {
332 if (size <= max_fixstr_size) {
333 serialize_fixstr_size(static_cast<std::uint8_t>(size));
334 return;
335 }
336
337 serialize_str8_size(static_cast<std::uint8_t>(size));
338 return;
339 }
340
341 if (size <= max_str16_size) {
342 serialize_str16_size(static_cast<std::uint16_t>(size));
343 return;
344 }
345
346 if constexpr (sizeof(std::size_t) > 4U) {
347 constexpr auto max_str32_size =
348 static_cast<std::size_t>(0xFFFFFFFF);
349 if (size > max_str32_size) {
350 throw std::runtime_error("Size is too large.");
351 }
352 }
353
354 serialize_str32_size(static_cast<std::uint32_t>(size));
355 }
356
358
366
372 void serialize_bin8_size(std::uint8_t size) {
373 constexpr auto prefix = static_cast<unsigned char>(0xC4);
374 write_in_big_endian(prefix, size);
375 }
376
382 void serialize_bin16_size(std::uint16_t size) {
383 constexpr auto prefix = static_cast<unsigned char>(0xC5);
384 write_in_big_endian(prefix, size);
385 }
386
392 void serialize_bin32_size(std::uint32_t size) {
393 constexpr auto prefix = static_cast<unsigned char>(0xC6);
394 write_in_big_endian(prefix, size);
395 }
396
402 void serialize_bin_size(std::size_t size) {
403 constexpr auto max_bin8_size = static_cast<std::size_t>(0xFF);
404 constexpr auto max_bin16_size = static_cast<std::size_t>(0xFFFF);
405
406 if (size <= max_bin8_size) {
407 serialize_bin8_size(static_cast<std::uint8_t>(size));
408 return;
409 }
410
411 if (size <= max_bin16_size) {
412 serialize_bin16_size(static_cast<std::uint16_t>(size));
413 return;
414 }
415
416 if constexpr (sizeof(std::size_t) > 4U) {
417 constexpr auto max_bin32_size =
418 static_cast<std::size_t>(0xFFFFFFFF);
419 if (size > max_bin32_size) {
420 throw std::runtime_error("Size is too large.");
421 }
422 }
423
424 serialize_bin32_size(static_cast<std::uint32_t>(size));
425 }
426
428
436
444 void serialize_fixarray_size(std::uint8_t size) {
445 constexpr auto prefix = static_cast<unsigned char>(0x90);
446 put(prefix | size);
447 }
448
454 void serialize_array16_size(std::uint16_t size) {
455 constexpr auto prefix = static_cast<unsigned char>(0xDC);
456 write_in_big_endian(prefix, size);
457 }
458
464 void serialize_array32_size(std::uint32_t size) {
465 constexpr auto prefix = static_cast<unsigned char>(0xDD);
466 write_in_big_endian(prefix, size);
467 }
468
474 void serialize_array_size(std::size_t size) {
475 constexpr auto fixarray_mask = ~static_cast<std::size_t>(15);
476 if ((size & fixarray_mask) == static_cast<std::size_t>(0)) {
477 serialize_fixarray_size(static_cast<std::uint8_t>(size));
478 return;
479 }
480
481 constexpr auto array16_mask = ~static_cast<std::size_t>(0xFFFF);
482 if ((size & array16_mask) == static_cast<std::size_t>(0)) {
483 serialize_array16_size(static_cast<std::uint16_t>(size));
484 return;
485 }
486
487 if constexpr (sizeof(std::size_t) > 4U) {
488 constexpr auto array32_mask = ~static_cast<std::size_t>(0xFFFFFFFF);
489 if ((size & array32_mask) != static_cast<std::size_t>(0)) {
490 throw std::runtime_error("Size is too large.");
491 }
492 }
493
494 serialize_array32_size(static_cast<std::uint32_t>(size));
495 }
496
498
506
514 void serialize_fixmap_size(std::uint8_t size) {
515 constexpr auto prefix = static_cast<unsigned char>(0x80);
516 put(prefix | size);
517 }
518
524 void serialize_map16_size(std::uint16_t size) {
525 constexpr auto prefix = static_cast<unsigned char>(0xDE);
526 write_in_big_endian(prefix, size);
527 }
528
534 void serialize_map32_size(std::uint32_t size) {
535 constexpr auto prefix = static_cast<unsigned char>(0xDF);
536 write_in_big_endian(prefix, size);
537 }
538
544 void serialize_map_size(std::size_t size) {
545 constexpr auto fixmap_mask = ~static_cast<std::size_t>(15);
546 if ((size & fixmap_mask) == static_cast<std::size_t>(0)) {
547 serialize_fixmap_size(static_cast<std::uint8_t>(size));
548 return;
549 }
550
551 constexpr auto map16_mask = ~static_cast<std::size_t>(0xFFFF);
552 if ((size & map16_mask) == static_cast<std::size_t>(0)) {
553 serialize_map16_size(static_cast<std::uint16_t>(size));
554 return;
555 }
556
557 if constexpr (sizeof(std::size_t) > 4U) {
558 constexpr auto map32_mask = ~static_cast<std::size_t>(0xFFFFFFFF);
559 if ((size & map32_mask) != static_cast<std::size_t>(0)) {
560 throw std::runtime_error("Size is too large.");
561 }
562 }
563
564 serialize_map32_size(static_cast<std::uint32_t>(size));
565 }
566
568
576
585 void serialize_fixext1_header(std::int8_t ext_type) {
586 constexpr auto prefix = static_cast<unsigned char>(0xD4);
587 write_in_big_endian(prefix, ext_type);
588 }
589
598 void serialize_fixext2_header(std::int8_t ext_type) {
599 constexpr auto prefix = static_cast<unsigned char>(0xD5);
600 write_in_big_endian(prefix, ext_type);
601 }
602
611 void serialize_fixext4_header(std::int8_t ext_type) {
612 constexpr auto prefix = static_cast<unsigned char>(0xD6);
613 write_in_big_endian(prefix, ext_type);
614 }
615
624 void serialize_fixext8_header(std::int8_t ext_type) {
625 constexpr auto prefix = static_cast<unsigned char>(0xD7);
626 write_in_big_endian(prefix, ext_type);
627 }
628
637 void serialize_fixext16_header(std::int8_t ext_type) {
638 constexpr auto prefix = static_cast<unsigned char>(0xD8);
639 write_in_big_endian(prefix, ext_type);
640 }
641
650 void serialize_ext8_header(std::int8_t ext_type, std::uint8_t data_size) {
651 constexpr auto prefix = static_cast<unsigned char>(0xC7);
652 write_in_big_endian(prefix, data_size, ext_type);
653 }
654
664 void serialize_ext16_header(std::int8_t ext_type, std::uint16_t data_size) {
665 constexpr auto prefix = static_cast<unsigned char>(0xC8);
666 write_in_big_endian(prefix, data_size, ext_type);
667 }
668
678 void serialize_ext32_header(std::int8_t ext_type, std::uint32_t data_size) {
679 constexpr auto prefix = static_cast<unsigned char>(0xC9);
680 write_in_big_endian(prefix, data_size, ext_type);
681 }
682
691 void serialize_ext_header(std::int8_t ext_type, std::size_t data_size) {
692 constexpr auto ext8_data_size_mask = ~static_cast<std::size_t>(0xFF);
693 if ((data_size & ext8_data_size_mask) == static_cast<std::size_t>(0)) {
694 constexpr auto fixext1_data_size = static_cast<std::size_t>(1);
695 constexpr auto fixext2_data_size = static_cast<std::size_t>(2);
696 constexpr auto fixext4_data_size = static_cast<std::size_t>(4);
697 constexpr auto fixext8_data_size = static_cast<std::size_t>(8);
698 constexpr auto fixext16_data_size = static_cast<std::size_t>(16);
699 switch (data_size) {
700 case fixext1_data_size:
701 serialize_fixext1_header(ext_type);
702 return;
703 case fixext2_data_size:
704 serialize_fixext2_header(ext_type);
705 return;
706 case fixext4_data_size:
707 serialize_fixext4_header(ext_type);
708 return;
709 case fixext8_data_size:
710 serialize_fixext8_header(ext_type);
711 return;
712 case fixext16_data_size:
714 return;
715 default:
717 ext_type, static_cast<std::uint8_t>(data_size));
718 return;
719 }
720 }
721
722 constexpr auto ext16_data_size_mask = ~static_cast<std::size_t>(0xFFFF);
723 if ((data_size & ext16_data_size_mask) == static_cast<std::size_t>(0)) {
725 ext_type, static_cast<std::uint16_t>(data_size));
726 return;
727 }
728
729 if constexpr (sizeof(std::size_t) > 4U) {
730 constexpr auto ext32_data_size_mask =
731 ~static_cast<std::size_t>(0xFFFFFFFF);
732 if ((data_size & ext32_data_size_mask) !=
733 static_cast<std::size_t>(0)) {
734 throw std::runtime_error("Size is too large.");
735 }
736 }
737
738 serialize_ext32_header(ext_type, static_cast<std::uint32_t>(data_size));
739 }
740
742
747
757 template <typename T>
758 void serialize(const T& data) {
760 }
761
763
768
778 void write(const unsigned char* data, std::size_t size) {
779 buffer_.write(data, size);
780 }
781
787 void put(unsigned char data) { buffer_.put(data); }
788
795 template <typename... T>
796 void write_in_big_endian(T... values) {
797 buffer_.write_in_big_endian(values...);
798 }
799
801
802private:
805};
806
807} // namespace msgpack_light
Interface of streams to write data.
Class of buffers to serialize data.
void serialize_fixstr_size(std::uint8_t size)
Serialize a size of fixstr format.
void serialize(const T &data)
Serialize data.
void flush()
Flush the internal buffer in this instance.
void serialize_array32_size(std::uint32_t size)
Serialize a size of array 32 format.
void serialize_ext32_header(std::int8_t ext_type, std::uint32_t data_size)
Serialize the size and type of an extension value in ext 32 format.
void serialize_int16(std::int16_t value)
Serialize a value in int 16 format.
void serialize_fixext8_header(std::int8_t ext_type)
Serialize the size and type of an extension value in fixext 8 format.
void write_in_big_endian(T... values)
Write values in big endian.
void serialize_fixext2_header(std::int8_t ext_type)
Serialize the size and type of an extension value in fixext 2 format.
void serialize_fixext16_header(std::int8_t ext_type)
Serialize the size and type of an extension value in fixext 16 format.
void serialize_bin_size(std::size_t size)
Serialize a size of a binary.
void serialize_uint16(std::uint16_t value)
Serialize a value in uint 16 format.
details::serialization_buffer_impl buffer_
Instance to perform internal processing.
void write(const unsigned char *data, std::size_t size)
Write data.
void serialize_array_size(std::size_t size)
Serialize a size of an array.
void serialize_str16_size(std::uint16_t size)
Serialize a size of str 16 format.
void serialize_uint8(std::uint8_t value)
Serialize a value in uint 8 format.
void serialize_fixarray_size(std::uint8_t size)
Serialize a size of fixarray format.
void serialize_bin32_size(std::uint32_t size)
Serialize a size of bin 32 format.
void serialize_map32_size(std::uint32_t size)
Serialize a size of map 32 format.
void serialize_positive_fixint(std::uint8_t value)
Serialize a value in positive fixint format.
void serialize_fixext1_header(std::int8_t ext_type)
Serialize the size and type of an extension value in fixext 1 format.
void serialize_negative_fixint(std::int8_t value)
Serialize a value in negative fixint format.
void serialize_bin8_size(std::uint8_t size)
Serialize a size of bin 8 format.
void serialize_ext_header(std::int8_t ext_type, std::size_t data_size)
Serialize the size and type of an extension value.
void serialize_float64(double value)
Serialize a value in float 64 format.
void serialize_bool(bool value)
Serialize a boolean value.
void serialize_int64(std::int64_t value)
Serialize a value in int 64 format.
void serialize_nil()
Serialize a nli value.
void serialize_uint32(std::uint32_t value)
Serialize a value in uint 32 format.
void serialize_ext16_header(std::int8_t ext_type, std::uint16_t data_size)
Serialize the size and type of an extension value in ext 16 format.
void serialize_array16_size(std::uint16_t size)
Serialize a size of array 16 format.
void serialize_uint64(std::uint64_t value)
Serialize a value in uint 64 format.
void serialize_int32(std::int32_t value)
Serialize a value in int 32 format.
void put(unsigned char data)
Write a byte of data.
void serialize_map_size(std::size_t size)
Serialize a size of a map.
void serialize_fixext4_header(std::int8_t ext_type)
Serialize the size and type of an extension value in fixext 4 format.
void serialize_fixmap_size(std::uint8_t size)
Serialize a size of fixmap format.
serialization_buffer(output_stream &stream)
Constructor.
void serialize_str_size(std::size_t size)
Serialize a size of a string.
void serialize_ext8_header(std::int8_t ext_type, std::uint8_t data_size)
Serialize the size and type of an extension value in ext 8 format.
void serialize_float32(float value)
Serialize a value in float 32 format.
void serialize_str32_size(std::uint32_t size)
Serialize a size of str 32 format.
void serialize_str8_size(std::uint8_t size)
Serialize a size of str 8 format.
void serialize_int8(std::int8_t value)
Serialize a value in int 8 format.
void serialize_bin16_size(std::uint16_t size)
Serialize a size of bin 16 format.
void serialize_map16_size(std::uint16_t size)
Serialize a size of map 16 format.
Forward declaration of classes to support serialization of data types.
non_buffered_serialization_buffer_impl serialization_buffer_impl
Type of internal implementation of serialization_buffer class.
Namespace of this project.
Definition binary.h:33
Definition of output_stream class.
Forward declaration of serialization_buffer class.
Definition of serialization_buffer_impl alias.
Class to define functions to serialize data of various types.
Definition fwd.h:43