1 #pragma once
2 
3 #include <algorithm> // reverse
4 #include <array> // array
5 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6 #include <cstring> // memcpy
7 #include <limits> // numeric_limits
8 #include <string> // string
9 
10 #include <nlohmann/detail/input/binary_reader.hpp>
11 #include <nlohmann/detail/output/output_adapters.hpp>
12 
13 namespace nlohmann
14 {
15 namespace detail
16 {
17 ///////////////////
18 // binary writer //
19 ///////////////////
20 
21 /*!
22 @brief serialization to CBOR and MessagePack values
23 */
24 template<typename BasicJsonType, typename CharType>
25 class binary_writer
26 {
27     using string_t = typename BasicJsonType::string_t;
28 
29   public:
30     /*!
31     @brief create a binary writer
32 
33     @param[in] adapter  output adapter to write to
34     */
binary_writer(output_adapter_t<CharType> adapter)35     explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
36     {
37         assert(oa);
38     }
39 
40     /*!
41     @param[in] j  JSON value to serialize
42     @pre       j.type() == value_t::object
43     */
write_bson(const BasicJsonType & j)44     void write_bson(const BasicJsonType& j)
45     {
46         switch (j.type())
47         {
48             case value_t::object:
49             {
50                 write_bson_object(*j.m_value.object);
51                 break;
52             }
53 
54             default:
55             {
56                 JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name())));
57             }
58         }
59     }
60 
61     /*!
62     @param[in] j  JSON value to serialize
63     */
write_cbor(const BasicJsonType & j)64     void write_cbor(const BasicJsonType& j)
65     {
66         switch (j.type())
67         {
68             case value_t::null:
69             {
70                 oa->write_character(to_char_type(0xF6));
71                 break;
72             }
73 
74             case value_t::boolean:
75             {
76                 oa->write_character(j.m_value.boolean
77                                     ? to_char_type(0xF5)
78                                     : to_char_type(0xF4));
79                 break;
80             }
81 
82             case value_t::number_integer:
83             {
84                 if (j.m_value.number_integer >= 0)
85                 {
86                     // CBOR does not differentiate between positive signed
87                     // integers and unsigned integers. Therefore, we used the
88                     // code from the value_t::number_unsigned case here.
89                     if (j.m_value.number_integer <= 0x17)
90                     {
91                         write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
92                     }
93                     else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
94                     {
95                         oa->write_character(to_char_type(0x18));
96                         write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
97                     }
98                     else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
99                     {
100                         oa->write_character(to_char_type(0x19));
101                         write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
102                     }
103                     else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
104                     {
105                         oa->write_character(to_char_type(0x1A));
106                         write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
107                     }
108                     else
109                     {
110                         oa->write_character(to_char_type(0x1B));
111                         write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
112                     }
113                 }
114                 else
115                 {
116                     // The conversions below encode the sign in the first
117                     // byte, and the value is converted to a positive number.
118                     const auto positive_number = -1 - j.m_value.number_integer;
119                     if (j.m_value.number_integer >= -24)
120                     {
121                         write_number(static_cast<std::uint8_t>(0x20 + positive_number));
122                     }
123                     else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
124                     {
125                         oa->write_character(to_char_type(0x38));
126                         write_number(static_cast<std::uint8_t>(positive_number));
127                     }
128                     else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
129                     {
130                         oa->write_character(to_char_type(0x39));
131                         write_number(static_cast<std::uint16_t>(positive_number));
132                     }
133                     else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
134                     {
135                         oa->write_character(to_char_type(0x3A));
136                         write_number(static_cast<std::uint32_t>(positive_number));
137                     }
138                     else
139                     {
140                         oa->write_character(to_char_type(0x3B));
141                         write_number(static_cast<std::uint64_t>(positive_number));
142                     }
143                 }
144                 break;
145             }
146 
147             case value_t::number_unsigned:
148             {
149                 if (j.m_value.number_unsigned <= 0x17)
150                 {
151                     write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
152                 }
153                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
154                 {
155                     oa->write_character(to_char_type(0x18));
156                     write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
157                 }
158                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
159                 {
160                     oa->write_character(to_char_type(0x19));
161                     write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
162                 }
163                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
164                 {
165                     oa->write_character(to_char_type(0x1A));
166                     write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
167                 }
168                 else
169                 {
170                     oa->write_character(to_char_type(0x1B));
171                     write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
172                 }
173                 break;
174             }
175 
176             case value_t::number_float:
177             {
178                 oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
179                 write_number(j.m_value.number_float);
180                 break;
181             }
182 
183             case value_t::string:
184             {
185                 // step 1: write control byte and the string length
186                 const auto N = j.m_value.string->size();
187                 if (N <= 0x17)
188                 {
189                     write_number(static_cast<std::uint8_t>(0x60 + N));
190                 }
191                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
192                 {
193                     oa->write_character(to_char_type(0x78));
194                     write_number(static_cast<std::uint8_t>(N));
195                 }
196                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
197                 {
198                     oa->write_character(to_char_type(0x79));
199                     write_number(static_cast<std::uint16_t>(N));
200                 }
201                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
202                 {
203                     oa->write_character(to_char_type(0x7A));
204                     write_number(static_cast<std::uint32_t>(N));
205                 }
206                 // LCOV_EXCL_START
207                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
208                 {
209                     oa->write_character(to_char_type(0x7B));
210                     write_number(static_cast<std::uint64_t>(N));
211                 }
212                 // LCOV_EXCL_STOP
213 
214                 // step 2: write the string
215                 oa->write_characters(
216                     reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
217                     j.m_value.string->size());
218                 break;
219             }
220 
221             case value_t::array:
222             {
223                 // step 1: write control byte and the array size
224                 const auto N = j.m_value.array->size();
225                 if (N <= 0x17)
226                 {
227                     write_number(static_cast<std::uint8_t>(0x80 + N));
228                 }
229                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
230                 {
231                     oa->write_character(to_char_type(0x98));
232                     write_number(static_cast<std::uint8_t>(N));
233                 }
234                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
235                 {
236                     oa->write_character(to_char_type(0x99));
237                     write_number(static_cast<std::uint16_t>(N));
238                 }
239                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
240                 {
241                     oa->write_character(to_char_type(0x9A));
242                     write_number(static_cast<std::uint32_t>(N));
243                 }
244                 // LCOV_EXCL_START
245                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
246                 {
247                     oa->write_character(to_char_type(0x9B));
248                     write_number(static_cast<std::uint64_t>(N));
249                 }
250                 // LCOV_EXCL_STOP
251 
252                 // step 2: write each element
253                 for (const auto& el : *j.m_value.array)
254                 {
255                     write_cbor(el);
256                 }
257                 break;
258             }
259 
260             case value_t::object:
261             {
262                 // step 1: write control byte and the object size
263                 const auto N = j.m_value.object->size();
264                 if (N <= 0x17)
265                 {
266                     write_number(static_cast<std::uint8_t>(0xA0 + N));
267                 }
268                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
269                 {
270                     oa->write_character(to_char_type(0xB8));
271                     write_number(static_cast<std::uint8_t>(N));
272                 }
273                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
274                 {
275                     oa->write_character(to_char_type(0xB9));
276                     write_number(static_cast<std::uint16_t>(N));
277                 }
278                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
279                 {
280                     oa->write_character(to_char_type(0xBA));
281                     write_number(static_cast<std::uint32_t>(N));
282                 }
283                 // LCOV_EXCL_START
284                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
285                 {
286                     oa->write_character(to_char_type(0xBB));
287                     write_number(static_cast<std::uint64_t>(N));
288                 }
289                 // LCOV_EXCL_STOP
290 
291                 // step 2: write each element
292                 for (const auto& el : *j.m_value.object)
293                 {
294                     write_cbor(el.first);
295                     write_cbor(el.second);
296                 }
297                 break;
298             }
299 
300             default:
301                 break;
302         }
303     }
304 
305     /*!
306     @param[in] j  JSON value to serialize
307     */
write_msgpack(const BasicJsonType & j)308     void write_msgpack(const BasicJsonType& j)
309     {
310         switch (j.type())
311         {
312             case value_t::null: // nil
313             {
314                 oa->write_character(to_char_type(0xC0));
315                 break;
316             }
317 
318             case value_t::boolean: // true and false
319             {
320                 oa->write_character(j.m_value.boolean
321                                     ? to_char_type(0xC3)
322                                     : to_char_type(0xC2));
323                 break;
324             }
325 
326             case value_t::number_integer:
327             {
328                 if (j.m_value.number_integer >= 0)
329                 {
330                     // MessagePack does not differentiate between positive
331                     // signed integers and unsigned integers. Therefore, we used
332                     // the code from the value_t::number_unsigned case here.
333                     if (j.m_value.number_unsigned < 128)
334                     {
335                         // positive fixnum
336                         write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
337                     }
338                     else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
339                     {
340                         // uint 8
341                         oa->write_character(to_char_type(0xCC));
342                         write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
343                     }
344                     else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
345                     {
346                         // uint 16
347                         oa->write_character(to_char_type(0xCD));
348                         write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
349                     }
350                     else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
351                     {
352                         // uint 32
353                         oa->write_character(to_char_type(0xCE));
354                         write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
355                     }
356                     else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
357                     {
358                         // uint 64
359                         oa->write_character(to_char_type(0xCF));
360                         write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
361                     }
362                 }
363                 else
364                 {
365                     if (j.m_value.number_integer >= -32)
366                     {
367                         // negative fixnum
368                         write_number(static_cast<std::int8_t>(j.m_value.number_integer));
369                     }
370                     else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() and
371                              j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
372                     {
373                         // int 8
374                         oa->write_character(to_char_type(0xD0));
375                         write_number(static_cast<std::int8_t>(j.m_value.number_integer));
376                     }
377                     else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() and
378                              j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
379                     {
380                         // int 16
381                         oa->write_character(to_char_type(0xD1));
382                         write_number(static_cast<std::int16_t>(j.m_value.number_integer));
383                     }
384                     else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() and
385                              j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
386                     {
387                         // int 32
388                         oa->write_character(to_char_type(0xD2));
389                         write_number(static_cast<std::int32_t>(j.m_value.number_integer));
390                     }
391                     else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() and
392                              j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
393                     {
394                         // int 64
395                         oa->write_character(to_char_type(0xD3));
396                         write_number(static_cast<std::int64_t>(j.m_value.number_integer));
397                     }
398                 }
399                 break;
400             }
401 
402             case value_t::number_unsigned:
403             {
404                 if (j.m_value.number_unsigned < 128)
405                 {
406                     // positive fixnum
407                     write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
408                 }
409                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
410                 {
411                     // uint 8
412                     oa->write_character(to_char_type(0xCC));
413                     write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
414                 }
415                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
416                 {
417                     // uint 16
418                     oa->write_character(to_char_type(0xCD));
419                     write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
420                 }
421                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
422                 {
423                     // uint 32
424                     oa->write_character(to_char_type(0xCE));
425                     write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
426                 }
427                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
428                 {
429                     // uint 64
430                     oa->write_character(to_char_type(0xCF));
431                     write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
432                 }
433                 break;
434             }
435 
436             case value_t::number_float:
437             {
438                 oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
439                 write_number(j.m_value.number_float);
440                 break;
441             }
442 
443             case value_t::string:
444             {
445                 // step 1: write control byte and the string length
446                 const auto N = j.m_value.string->size();
447                 if (N <= 31)
448                 {
449                     // fixstr
450                     write_number(static_cast<std::uint8_t>(0xA0 | N));
451                 }
452                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
453                 {
454                     // str 8
455                     oa->write_character(to_char_type(0xD9));
456                     write_number(static_cast<std::uint8_t>(N));
457                 }
458                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
459                 {
460                     // str 16
461                     oa->write_character(to_char_type(0xDA));
462                     write_number(static_cast<std::uint16_t>(N));
463                 }
464                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
465                 {
466                     // str 32
467                     oa->write_character(to_char_type(0xDB));
468                     write_number(static_cast<std::uint32_t>(N));
469                 }
470 
471                 // step 2: write the string
472                 oa->write_characters(
473                     reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
474                     j.m_value.string->size());
475                 break;
476             }
477 
478             case value_t::array:
479             {
480                 // step 1: write control byte and the array size
481                 const auto N = j.m_value.array->size();
482                 if (N <= 15)
483                 {
484                     // fixarray
485                     write_number(static_cast<std::uint8_t>(0x90 | N));
486                 }
487                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
488                 {
489                     // array 16
490                     oa->write_character(to_char_type(0xDC));
491                     write_number(static_cast<std::uint16_t>(N));
492                 }
493                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
494                 {
495                     // array 32
496                     oa->write_character(to_char_type(0xDD));
497                     write_number(static_cast<std::uint32_t>(N));
498                 }
499 
500                 // step 2: write each element
501                 for (const auto& el : *j.m_value.array)
502                 {
503                     write_msgpack(el);
504                 }
505                 break;
506             }
507 
508             case value_t::object:
509             {
510                 // step 1: write control byte and the object size
511                 const auto N = j.m_value.object->size();
512                 if (N <= 15)
513                 {
514                     // fixmap
515                     write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
516                 }
517                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
518                 {
519                     // map 16
520                     oa->write_character(to_char_type(0xDE));
521                     write_number(static_cast<std::uint16_t>(N));
522                 }
523                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
524                 {
525                     // map 32
526                     oa->write_character(to_char_type(0xDF));
527                     write_number(static_cast<std::uint32_t>(N));
528                 }
529 
530                 // step 2: write each element
531                 for (const auto& el : *j.m_value.object)
532                 {
533                     write_msgpack(el.first);
534                     write_msgpack(el.second);
535                 }
536                 break;
537             }
538 
539             default:
540                 break;
541         }
542     }
543 
544     /*!
545     @param[in] j  JSON value to serialize
546     @param[in] use_count   whether to use '#' prefixes (optimized format)
547     @param[in] use_type    whether to use '$' prefixes (optimized format)
548     @param[in] add_prefix  whether prefixes need to be used for this value
549     */
write_ubjson(const BasicJsonType & j,const bool use_count,const bool use_type,const bool add_prefix=true)550     void write_ubjson(const BasicJsonType& j, const bool use_count,
551                       const bool use_type, const bool add_prefix = true)
552     {
553         switch (j.type())
554         {
555             case value_t::null:
556             {
557                 if (add_prefix)
558                 {
559                     oa->write_character(to_char_type('Z'));
560                 }
561                 break;
562             }
563 
564             case value_t::boolean:
565             {
566                 if (add_prefix)
567                 {
568                     oa->write_character(j.m_value.boolean
569                                         ? to_char_type('T')
570                                         : to_char_type('F'));
571                 }
572                 break;
573             }
574 
575             case value_t::number_integer:
576             {
577                 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
578                 break;
579             }
580 
581             case value_t::number_unsigned:
582             {
583                 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
584                 break;
585             }
586 
587             case value_t::number_float:
588             {
589                 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
590                 break;
591             }
592 
593             case value_t::string:
594             {
595                 if (add_prefix)
596                 {
597                     oa->write_character(to_char_type('S'));
598                 }
599                 write_number_with_ubjson_prefix(j.m_value.string->size(), true);
600                 oa->write_characters(
601                     reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
602                     j.m_value.string->size());
603                 break;
604             }
605 
606             case value_t::array:
607             {
608                 if (add_prefix)
609                 {
610                     oa->write_character(to_char_type('['));
611                 }
612 
613                 bool prefix_required = true;
614                 if (use_type and not j.m_value.array->empty())
615                 {
616                     assert(use_count);
617                     const CharType first_prefix = ubjson_prefix(j.front());
618                     const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
619                                                          [this, first_prefix](const BasicJsonType & v)
620                     {
621                         return ubjson_prefix(v) == first_prefix;
622                     });
623 
624                     if (same_prefix)
625                     {
626                         prefix_required = false;
627                         oa->write_character(to_char_type('$'));
628                         oa->write_character(first_prefix);
629                     }
630                 }
631 
632                 if (use_count)
633                 {
634                     oa->write_character(to_char_type('#'));
635                     write_number_with_ubjson_prefix(j.m_value.array->size(), true);
636                 }
637 
638                 for (const auto& el : *j.m_value.array)
639                 {
640                     write_ubjson(el, use_count, use_type, prefix_required);
641                 }
642 
643                 if (not use_count)
644                 {
645                     oa->write_character(to_char_type(']'));
646                 }
647 
648                 break;
649             }
650 
651             case value_t::object:
652             {
653                 if (add_prefix)
654                 {
655                     oa->write_character(to_char_type('{'));
656                 }
657 
658                 bool prefix_required = true;
659                 if (use_type and not j.m_value.object->empty())
660                 {
661                     assert(use_count);
662                     const CharType first_prefix = ubjson_prefix(j.front());
663                     const bool same_prefix = std::all_of(j.begin(), j.end(),
664                                                          [this, first_prefix](const BasicJsonType & v)
665                     {
666                         return ubjson_prefix(v) == first_prefix;
667                     });
668 
669                     if (same_prefix)
670                     {
671                         prefix_required = false;
672                         oa->write_character(to_char_type('$'));
673                         oa->write_character(first_prefix);
674                     }
675                 }
676 
677                 if (use_count)
678                 {
679                     oa->write_character(to_char_type('#'));
680                     write_number_with_ubjson_prefix(j.m_value.object->size(), true);
681                 }
682 
683                 for (const auto& el : *j.m_value.object)
684                 {
685                     write_number_with_ubjson_prefix(el.first.size(), true);
686                     oa->write_characters(
687                         reinterpret_cast<const CharType*>(el.first.c_str()),
688                         el.first.size());
689                     write_ubjson(el.second, use_count, use_type, prefix_required);
690                 }
691 
692                 if (not use_count)
693                 {
694                     oa->write_character(to_char_type('}'));
695                 }
696 
697                 break;
698             }
699 
700             default:
701                 break;
702         }
703     }
704 
705   private:
706     //////////
707     // BSON //
708     //////////
709 
710     /*!
711     @return The size of a BSON document entry header, including the id marker
712             and the entry name size (and its null-terminator).
713     */
calc_bson_entry_header_size(const string_t & name)714     static std::size_t calc_bson_entry_header_size(const string_t& name)
715     {
716         const auto it = name.find(static_cast<typename string_t::value_type>(0));
717         if (JSON_UNLIKELY(it != BasicJsonType::string_t::npos))
718         {
719             JSON_THROW(out_of_range::create(409,
720                                             "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
721         }
722 
723         return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
724     }
725 
726     /*!
727     @brief Writes the given @a element_type and @a name to the output adapter
728     */
write_bson_entry_header(const string_t & name,const std::uint8_t element_type)729     void write_bson_entry_header(const string_t& name,
730                                  const std::uint8_t element_type)
731     {
732         oa->write_character(to_char_type(element_type)); // boolean
733         oa->write_characters(
734             reinterpret_cast<const CharType*>(name.c_str()),
735             name.size() + 1u);
736     }
737 
738     /*!
739     @brief Writes a BSON element with key @a name and boolean value @a value
740     */
write_bson_boolean(const string_t & name,const bool value)741     void write_bson_boolean(const string_t& name,
742                             const bool value)
743     {
744         write_bson_entry_header(name, 0x08);
745         oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
746     }
747 
748     /*!
749     @brief Writes a BSON element with key @a name and double value @a value
750     */
write_bson_double(const string_t & name,const double value)751     void write_bson_double(const string_t& name,
752                            const double value)
753     {
754         write_bson_entry_header(name, 0x01);
755         write_number<double, true>(value);
756     }
757 
758     /*!
759     @return The size of the BSON-encoded string in @a value
760     */
calc_bson_string_size(const string_t & value)761     static std::size_t calc_bson_string_size(const string_t& value)
762     {
763         return sizeof(std::int32_t) + value.size() + 1ul;
764     }
765 
766     /*!
767     @brief Writes a BSON element with key @a name and string value @a value
768     */
write_bson_string(const string_t & name,const string_t & value)769     void write_bson_string(const string_t& name,
770                            const string_t& value)
771     {
772         write_bson_entry_header(name, 0x02);
773 
774         write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
775         oa->write_characters(
776             reinterpret_cast<const CharType*>(value.c_str()),
777             value.size() + 1);
778     }
779 
780     /*!
781     @brief Writes a BSON element with key @a name and null value
782     */
write_bson_null(const string_t & name)783     void write_bson_null(const string_t& name)
784     {
785         write_bson_entry_header(name, 0x0A);
786     }
787 
788     /*!
789     @return The size of the BSON-encoded integer @a value
790     */
calc_bson_integer_size(const std::int64_t value)791     static std::size_t calc_bson_integer_size(const std::int64_t value)
792     {
793         return (std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()
794                ? sizeof(std::int32_t)
795                : sizeof(std::int64_t);
796     }
797 
798     /*!
799     @brief Writes a BSON element with key @a name and integer @a value
800     */
write_bson_integer(const string_t & name,const std::int64_t value)801     void write_bson_integer(const string_t& name,
802                             const std::int64_t value)
803     {
804         if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
805         {
806             write_bson_entry_header(name, 0x10); // int32
807             write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
808         }
809         else
810         {
811             write_bson_entry_header(name, 0x12); // int64
812             write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
813         }
814     }
815 
816     /*!
817     @return The size of the BSON-encoded unsigned integer in @a j
818     */
calc_bson_unsigned_size(const std::uint64_t value)819     static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
820     {
821         return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
822                ? sizeof(std::int32_t)
823                : sizeof(std::int64_t);
824     }
825 
826     /*!
827     @brief Writes a BSON element with key @a name and unsigned @a value
828     */
write_bson_unsigned(const string_t & name,const std::uint64_t value)829     void write_bson_unsigned(const string_t& name,
830                              const std::uint64_t value)
831     {
832         if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
833         {
834             write_bson_entry_header(name, 0x10 /* int32 */);
835             write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
836         }
837         else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
838         {
839             write_bson_entry_header(name, 0x12 /* int64 */);
840             write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
841         }
842         else
843         {
844             JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64"));
845         }
846     }
847 
848     /*!
849     @brief Writes a BSON element with key @a name and object @a value
850     */
write_bson_object_entry(const string_t & name,const typename BasicJsonType::object_t & value)851     void write_bson_object_entry(const string_t& name,
852                                  const typename BasicJsonType::object_t& value)
853     {
854         write_bson_entry_header(name, 0x03); // object
855         write_bson_object(value);
856     }
857 
858     /*!
859     @return The size of the BSON-encoded array @a value
860     */
calc_bson_array_size(const typename BasicJsonType::array_t & value)861     static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
862     {
863         std::size_t embedded_document_size = 0ul;
864         std::size_t array_index = 0ul;
865 
866         for (const auto& el : value)
867         {
868             embedded_document_size += calc_bson_element_size(std::to_string(array_index++), el);
869         }
870 
871         return sizeof(std::int32_t) + embedded_document_size + 1ul;
872     }
873 
874     /*!
875     @brief Writes a BSON element with key @a name and array @a value
876     */
write_bson_array(const string_t & name,const typename BasicJsonType::array_t & value)877     void write_bson_array(const string_t& name,
878                           const typename BasicJsonType::array_t& value)
879     {
880         write_bson_entry_header(name, 0x04); // array
881         write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
882 
883         std::size_t array_index = 0ul;
884 
885         for (const auto& el : value)
886         {
887             write_bson_element(std::to_string(array_index++), el);
888         }
889 
890         oa->write_character(to_char_type(0x00));
891     }
892 
893     /*!
894     @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
895     @return The calculated size for the BSON document entry for @a j with the given @a name.
896     */
calc_bson_element_size(const string_t & name,const BasicJsonType & j)897     static std::size_t calc_bson_element_size(const string_t& name,
898             const BasicJsonType& j)
899     {
900         const auto header_size = calc_bson_entry_header_size(name);
901         switch (j.type())
902         {
903             case value_t::object:
904                 return header_size + calc_bson_object_size(*j.m_value.object);
905 
906             case value_t::array:
907                 return header_size + calc_bson_array_size(*j.m_value.array);
908 
909             case value_t::boolean:
910                 return header_size + 1ul;
911 
912             case value_t::number_float:
913                 return header_size + 8ul;
914 
915             case value_t::number_integer:
916                 return header_size + calc_bson_integer_size(j.m_value.number_integer);
917 
918             case value_t::number_unsigned:
919                 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
920 
921             case value_t::string:
922                 return header_size + calc_bson_string_size(*j.m_value.string);
923 
924             case value_t::null:
925                 return header_size + 0ul;
926 
927             // LCOV_EXCL_START
928             default:
929                 assert(false);
930                 return 0ul;
931                 // LCOV_EXCL_STOP
932         }
933     }
934 
935     /*!
936     @brief Serializes the JSON value @a j to BSON and associates it with the
937            key @a name.
938     @param name The name to associate with the JSON entity @a j within the
939                 current BSON document
940     @return The size of the BSON entry
941     */
write_bson_element(const string_t & name,const BasicJsonType & j)942     void write_bson_element(const string_t& name,
943                             const BasicJsonType& j)
944     {
945         switch (j.type())
946         {
947             case value_t::object:
948                 return write_bson_object_entry(name, *j.m_value.object);
949 
950             case value_t::array:
951                 return write_bson_array(name, *j.m_value.array);
952 
953             case value_t::boolean:
954                 return write_bson_boolean(name, j.m_value.boolean);
955 
956             case value_t::number_float:
957                 return write_bson_double(name, j.m_value.number_float);
958 
959             case value_t::number_integer:
960                 return write_bson_integer(name, j.m_value.number_integer);
961 
962             case value_t::number_unsigned:
963                 return write_bson_unsigned(name, j.m_value.number_unsigned);
964 
965             case value_t::string:
966                 return write_bson_string(name, *j.m_value.string);
967 
968             case value_t::null:
969                 return write_bson_null(name);
970 
971             // LCOV_EXCL_START
972             default:
973                 assert(false);
974                 return;
975                 // LCOV_EXCL_STOP
976         }
977     }
978 
979     /*!
980     @brief Calculates the size of the BSON serialization of the given
981            JSON-object @a j.
982     @param[in] j  JSON value to serialize
983     @pre       j.type() == value_t::object
984     */
calc_bson_object_size(const typename BasicJsonType::object_t & value)985     static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
986     {
987         std::size_t document_size = std::accumulate(value.begin(), value.end(), 0ul,
988                                     [](size_t result, const typename BasicJsonType::object_t::value_type & el)
989         {
990             return result += calc_bson_element_size(el.first, el.second);
991         });
992 
993         return sizeof(std::int32_t) + document_size + 1ul;
994     }
995 
996     /*!
997     @param[in] j  JSON value to serialize
998     @pre       j.type() == value_t::object
999     */
write_bson_object(const typename BasicJsonType::object_t & value)1000     void write_bson_object(const typename BasicJsonType::object_t& value)
1001     {
1002         write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
1003 
1004         for (const auto& el : value)
1005         {
1006             write_bson_element(el.first, el.second);
1007         }
1008 
1009         oa->write_character(to_char_type(0x00));
1010     }
1011 
1012     //////////
1013     // CBOR //
1014     //////////
1015 
get_cbor_float_prefix(float)1016     static constexpr CharType get_cbor_float_prefix(float /*unused*/)
1017     {
1018         return to_char_type(0xFA);  // Single-Precision Float
1019     }
1020 
get_cbor_float_prefix(double)1021     static constexpr CharType get_cbor_float_prefix(double /*unused*/)
1022     {
1023         return to_char_type(0xFB);  // Double-Precision Float
1024     }
1025 
1026     /////////////
1027     // MsgPack //
1028     /////////////
1029 
get_msgpack_float_prefix(float)1030     static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
1031     {
1032         return to_char_type(0xCA);  // float 32
1033     }
1034 
get_msgpack_float_prefix(double)1035     static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
1036     {
1037         return to_char_type(0xCB);  // float 64
1038     }
1039 
1040     ////////////
1041     // UBJSON //
1042     ////////////
1043 
1044     // UBJSON: write number (floating point)
1045     template<typename NumberType, typename std::enable_if<
1046                  std::is_floating_point<NumberType>::value, int>::type = 0>
write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix)1047     void write_number_with_ubjson_prefix(const NumberType n,
1048                                          const bool add_prefix)
1049     {
1050         if (add_prefix)
1051         {
1052             oa->write_character(get_ubjson_float_prefix(n));
1053         }
1054         write_number(n);
1055     }
1056 
1057     // UBJSON: write number (unsigned integer)
1058     template<typename NumberType, typename std::enable_if<
1059                  std::is_unsigned<NumberType>::value, int>::type = 0>
write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix)1060     void write_number_with_ubjson_prefix(const NumberType n,
1061                                          const bool add_prefix)
1062     {
1063         if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
1064         {
1065             if (add_prefix)
1066             {
1067                 oa->write_character(to_char_type('i'));  // int8
1068             }
1069             write_number(static_cast<std::uint8_t>(n));
1070         }
1071         else if (n <= (std::numeric_limits<std::uint8_t>::max)())
1072         {
1073             if (add_prefix)
1074             {
1075                 oa->write_character(to_char_type('U'));  // uint8
1076             }
1077             write_number(static_cast<std::uint8_t>(n));
1078         }
1079         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
1080         {
1081             if (add_prefix)
1082             {
1083                 oa->write_character(to_char_type('I'));  // int16
1084             }
1085             write_number(static_cast<std::int16_t>(n));
1086         }
1087         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
1088         {
1089             if (add_prefix)
1090             {
1091                 oa->write_character(to_char_type('l'));  // int32
1092             }
1093             write_number(static_cast<std::int32_t>(n));
1094         }
1095         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
1096         {
1097             if (add_prefix)
1098             {
1099                 oa->write_character(to_char_type('L'));  // int64
1100             }
1101             write_number(static_cast<std::int64_t>(n));
1102         }
1103         else
1104         {
1105             JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
1106         }
1107     }
1108 
1109     // UBJSON: write number (signed integer)
1110     template<typename NumberType, typename std::enable_if<
1111                  std::is_signed<NumberType>::value and
1112                  not std::is_floating_point<NumberType>::value, int>::type = 0>
write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix)1113     void write_number_with_ubjson_prefix(const NumberType n,
1114                                          const bool add_prefix)
1115     {
1116         if ((std::numeric_limits<std::int8_t>::min)() <= n and n <= (std::numeric_limits<std::int8_t>::max)())
1117         {
1118             if (add_prefix)
1119             {
1120                 oa->write_character(to_char_type('i'));  // int8
1121             }
1122             write_number(static_cast<std::int8_t>(n));
1123         }
1124         else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n and n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
1125         {
1126             if (add_prefix)
1127             {
1128                 oa->write_character(to_char_type('U'));  // uint8
1129             }
1130             write_number(static_cast<std::uint8_t>(n));
1131         }
1132         else if ((std::numeric_limits<std::int16_t>::min)() <= n and n <= (std::numeric_limits<std::int16_t>::max)())
1133         {
1134             if (add_prefix)
1135             {
1136                 oa->write_character(to_char_type('I'));  // int16
1137             }
1138             write_number(static_cast<std::int16_t>(n));
1139         }
1140         else if ((std::numeric_limits<std::int32_t>::min)() <= n and n <= (std::numeric_limits<std::int32_t>::max)())
1141         {
1142             if (add_prefix)
1143             {
1144                 oa->write_character(to_char_type('l'));  // int32
1145             }
1146             write_number(static_cast<std::int32_t>(n));
1147         }
1148         else if ((std::numeric_limits<std::int64_t>::min)() <= n and n <= (std::numeric_limits<std::int64_t>::max)())
1149         {
1150             if (add_prefix)
1151             {
1152                 oa->write_character(to_char_type('L'));  // int64
1153             }
1154             write_number(static_cast<std::int64_t>(n));
1155         }
1156         // LCOV_EXCL_START
1157         else
1158         {
1159             JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
1160         }
1161         // LCOV_EXCL_STOP
1162     }
1163 
1164     /*!
1165     @brief determine the type prefix of container values
1166 
1167     @note This function does not need to be 100% accurate when it comes to
1168           integer limits. In case a number exceeds the limits of int64_t,
1169           this will be detected by a later call to function
1170           write_number_with_ubjson_prefix. Therefore, we return 'L' for any
1171           value that does not fit the previous limits.
1172     */
ubjson_prefix(const BasicJsonType & j) const1173     CharType ubjson_prefix(const BasicJsonType& j) const noexcept
1174     {
1175         switch (j.type())
1176         {
1177             case value_t::null:
1178                 return 'Z';
1179 
1180             case value_t::boolean:
1181                 return j.m_value.boolean ? 'T' : 'F';
1182 
1183             case value_t::number_integer:
1184             {
1185                 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
1186                 {
1187                     return 'i';
1188                 }
1189                 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
1190                 {
1191                     return 'U';
1192                 }
1193                 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
1194                 {
1195                     return 'I';
1196                 }
1197                 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
1198                 {
1199                     return 'l';
1200                 }
1201                 // no check and assume int64_t (see note above)
1202                 return 'L';
1203             }
1204 
1205             case value_t::number_unsigned:
1206             {
1207                 if (j.m_value.number_unsigned <= (std::numeric_limits<std::int8_t>::max)())
1208                 {
1209                     return 'i';
1210                 }
1211                 if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
1212                 {
1213                     return 'U';
1214                 }
1215                 if (j.m_value.number_unsigned <= (std::numeric_limits<std::int16_t>::max)())
1216                 {
1217                     return 'I';
1218                 }
1219                 if (j.m_value.number_unsigned <= (std::numeric_limits<std::int32_t>::max)())
1220                 {
1221                     return 'l';
1222                 }
1223                 // no check and assume int64_t (see note above)
1224                 return 'L';
1225             }
1226 
1227             case value_t::number_float:
1228                 return get_ubjson_float_prefix(j.m_value.number_float);
1229 
1230             case value_t::string:
1231                 return 'S';
1232 
1233             case value_t::array:
1234                 return '[';
1235 
1236             case value_t::object:
1237                 return '{';
1238 
1239             default:  // discarded values
1240                 return 'N';
1241         }
1242     }
1243 
get_ubjson_float_prefix(float)1244     static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
1245     {
1246         return 'd';  // float 32
1247     }
1248 
get_ubjson_float_prefix(double)1249     static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
1250     {
1251         return 'D';  // float 64
1252     }
1253 
1254     ///////////////////////
1255     // Utility functions //
1256     ///////////////////////
1257 
1258     /*
1259     @brief write a number to output input
1260     @param[in] n number of type @a NumberType
1261     @tparam NumberType the type of the number
1262     @tparam OutputIsLittleEndian Set to true if output data is
1263                                  required to be little endian
1264 
1265     @note This function needs to respect the system's endianess, because bytes
1266           in CBOR, MessagePack, and UBJSON are stored in network order (big
1267           endian) and therefore need reordering on little endian systems.
1268     */
1269     template<typename NumberType, bool OutputIsLittleEndian = false>
write_number(const NumberType n)1270     void write_number(const NumberType n)
1271     {
1272         // step 1: write number to array of length NumberType
1273         std::array<CharType, sizeof(NumberType)> vec;
1274         std::memcpy(vec.data(), &n, sizeof(NumberType));
1275 
1276         // step 2: write array to output (with possible reordering)
1277         if (is_little_endian != OutputIsLittleEndian)
1278         {
1279             // reverse byte order prior to conversion if necessary
1280             std::reverse(vec.begin(), vec.end());
1281         }
1282 
1283         oa->write_characters(vec.data(), sizeof(NumberType));
1284     }
1285 
1286   public:
1287     // The following to_char_type functions are implement the conversion
1288     // between uint8_t and CharType. In case CharType is not unsigned,
1289     // such a conversion is required to allow values greater than 128.
1290     // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
1291     template < typename C = CharType,
1292                enable_if_t < std::is_signed<C>::value and std::is_signed<char>::value > * = nullptr >
to_char_type(std::uint8_t x)1293     static constexpr CharType to_char_type(std::uint8_t x) noexcept
1294     {
1295         return *reinterpret_cast<char*>(&x);
1296     }
1297 
1298     template < typename C = CharType,
1299                enable_if_t < std::is_signed<C>::value and std::is_unsigned<char>::value > * = nullptr >
to_char_type(std::uint8_t x)1300     static CharType to_char_type(std::uint8_t x) noexcept
1301     {
1302         static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
1303         static_assert(std::is_pod<CharType>::value, "CharType must be POD");
1304         CharType result;
1305         std::memcpy(&result, &x, sizeof(x));
1306         return result;
1307     }
1308 
1309     template<typename C = CharType,
1310              enable_if_t<std::is_unsigned<C>::value>* = nullptr>
to_char_type(std::uint8_t x)1311     static constexpr CharType to_char_type(std::uint8_t x) noexcept
1312     {
1313         return x;
1314     }
1315 
1316     template < typename InputCharType, typename C = CharType,
1317                enable_if_t <
1318                    std::is_signed<C>::value and
1319                    std::is_signed<char>::value and
1320                    std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
1321                    > * = nullptr >
to_char_type(InputCharType x)1322     static constexpr CharType to_char_type(InputCharType x) noexcept
1323     {
1324         return x;
1325     }
1326 
1327   private:
1328     /// whether we can assume little endianess
1329     const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
1330 
1331     /// the output
1332     output_adapter_t<CharType> oa = nullptr;
1333 };
1334 }  // namespace detail
1335 }  // namespace nlohmann
1336