Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-17 09:18:06

0001 //     __ _____ _____ _____
0002 //  __|  |   __|     |   | |  JSON for Modern C++
0003 // |  |  |__   |  |  | | | |  version 3.12.0
0004 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
0005 //
0006 // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
0007 // SPDX-License-Identifier: MIT
0008 
0009 #pragma once
0010 
0011 #include <algorithm> // reverse
0012 #include <array> // array
0013 #include <map> // map
0014 #include <cmath> // isnan, isinf
0015 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
0016 #include <cstring> // memcpy
0017 #include <limits> // numeric_limits
0018 #include <string> // string
0019 #include <utility> // move
0020 #include <vector> // vector
0021 
0022 #include <nlohmann/detail/input/binary_reader.hpp>
0023 #include <nlohmann/detail/macro_scope.hpp>
0024 #include <nlohmann/detail/output/output_adapters.hpp>
0025 #include <nlohmann/detail/string_concat.hpp>
0026 
0027 NLOHMANN_JSON_NAMESPACE_BEGIN
0028 namespace detail
0029 {
0030 
0031 /// how to encode BJData
0032 enum class bjdata_version_t
0033 {
0034     draft2,
0035     draft3,
0036 };
0037 
0038 ///////////////////
0039 // binary writer //
0040 ///////////////////
0041 
0042 /*!
0043 @brief serialization to CBOR and MessagePack values
0044 */
0045 template<typename BasicJsonType, typename CharType>
0046 class binary_writer
0047 {
0048     using string_t = typename BasicJsonType::string_t;
0049     using binary_t = typename BasicJsonType::binary_t;
0050     using number_float_t = typename BasicJsonType::number_float_t;
0051 
0052   public:
0053     /*!
0054     @brief create a binary writer
0055 
0056     @param[in] adapter  output adapter to write to
0057     */
0058     explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
0059     {
0060         JSON_ASSERT(oa);
0061     }
0062 
0063     /*!
0064     @param[in] j  JSON value to serialize
0065     @pre       j.type() == value_t::object
0066     */
0067     void write_bson(const BasicJsonType& j)
0068     {
0069         switch (j.type())
0070         {
0071             case value_t::object:
0072             {
0073                 write_bson_object(*j.m_data.m_value.object);
0074                 break;
0075             }
0076 
0077             case value_t::null:
0078             case value_t::array:
0079             case value_t::string:
0080             case value_t::boolean:
0081             case value_t::number_integer:
0082             case value_t::number_unsigned:
0083             case value_t::number_float:
0084             case value_t::binary:
0085             case value_t::discarded:
0086             default:
0087             {
0088                 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
0089             }
0090         }
0091     }
0092 
0093     /*!
0094     @param[in] j  JSON value to serialize
0095     */
0096     void write_cbor(const BasicJsonType& j)
0097     {
0098         switch (j.type())
0099         {
0100             case value_t::null:
0101             {
0102                 oa->write_character(to_char_type(0xF6));
0103                 break;
0104             }
0105 
0106             case value_t::boolean:
0107             {
0108                 oa->write_character(j.m_data.m_value.boolean
0109                                     ? to_char_type(0xF5)
0110                                     : to_char_type(0xF4));
0111                 break;
0112             }
0113 
0114             case value_t::number_integer:
0115             {
0116                 if (j.m_data.m_value.number_integer >= 0)
0117                 {
0118                     // CBOR does not differentiate between positive signed
0119                     // integers and unsigned integers. Therefore, we used the
0120                     // code from the value_t::number_unsigned case here.
0121                     if (j.m_data.m_value.number_integer <= 0x17)
0122                     {
0123                         write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
0124                     }
0125                     else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
0126                     {
0127                         oa->write_character(to_char_type(0x18));
0128                         write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
0129                     }
0130                     else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
0131                     {
0132                         oa->write_character(to_char_type(0x19));
0133                         write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
0134                     }
0135                     else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
0136                     {
0137                         oa->write_character(to_char_type(0x1A));
0138                         write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
0139                     }
0140                     else
0141                     {
0142                         oa->write_character(to_char_type(0x1B));
0143                         write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
0144                     }
0145                 }
0146                 else
0147                 {
0148                     // The conversions below encode the sign in the first
0149                     // byte, and the value is converted to a positive number.
0150                     const auto positive_number = -1 - j.m_data.m_value.number_integer;
0151                     if (j.m_data.m_value.number_integer >= -24)
0152                     {
0153                         write_number(static_cast<std::uint8_t>(0x20 + positive_number));
0154                     }
0155                     else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
0156                     {
0157                         oa->write_character(to_char_type(0x38));
0158                         write_number(static_cast<std::uint8_t>(positive_number));
0159                     }
0160                     else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
0161                     {
0162                         oa->write_character(to_char_type(0x39));
0163                         write_number(static_cast<std::uint16_t>(positive_number));
0164                     }
0165                     else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
0166                     {
0167                         oa->write_character(to_char_type(0x3A));
0168                         write_number(static_cast<std::uint32_t>(positive_number));
0169                     }
0170                     else
0171                     {
0172                         oa->write_character(to_char_type(0x3B));
0173                         write_number(static_cast<std::uint64_t>(positive_number));
0174                     }
0175                 }
0176                 break;
0177             }
0178 
0179             case value_t::number_unsigned:
0180             {
0181                 if (j.m_data.m_value.number_unsigned <= 0x17)
0182                 {
0183                     write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
0184                 }
0185                 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
0186                 {
0187                     oa->write_character(to_char_type(0x18));
0188                     write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
0189                 }
0190                 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
0191                 {
0192                     oa->write_character(to_char_type(0x19));
0193                     write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
0194                 }
0195                 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
0196                 {
0197                     oa->write_character(to_char_type(0x1A));
0198                     write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
0199                 }
0200                 else
0201                 {
0202                     oa->write_character(to_char_type(0x1B));
0203                     write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
0204                 }
0205                 break;
0206             }
0207 
0208             case value_t::number_float:
0209             {
0210                 if (std::isnan(j.m_data.m_value.number_float))
0211                 {
0212                     // NaN is 0xf97e00 in CBOR
0213                     oa->write_character(to_char_type(0xF9));
0214                     oa->write_character(to_char_type(0x7E));
0215                     oa->write_character(to_char_type(0x00));
0216                 }
0217                 else if (std::isinf(j.m_data.m_value.number_float))
0218                 {
0219                     // Infinity is 0xf97c00, -Infinity is 0xf9fc00
0220                     oa->write_character(to_char_type(0xf9));
0221                     oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
0222                     oa->write_character(to_char_type(0x00));
0223                 }
0224                 else
0225                 {
0226                     write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
0227                 }
0228                 break;
0229             }
0230 
0231             case value_t::string:
0232             {
0233                 // step 1: write control byte and the string length
0234                 const auto N = j.m_data.m_value.string->size();
0235                 if (N <= 0x17)
0236                 {
0237                     write_number(static_cast<std::uint8_t>(0x60 + N));
0238                 }
0239                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
0240                 {
0241                     oa->write_character(to_char_type(0x78));
0242                     write_number(static_cast<std::uint8_t>(N));
0243                 }
0244                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
0245                 {
0246                     oa->write_character(to_char_type(0x79));
0247                     write_number(static_cast<std::uint16_t>(N));
0248                 }
0249                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
0250                 {
0251                     oa->write_character(to_char_type(0x7A));
0252                     write_number(static_cast<std::uint32_t>(N));
0253                 }
0254                 // LCOV_EXCL_START
0255                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
0256                 {
0257                     oa->write_character(to_char_type(0x7B));
0258                     write_number(static_cast<std::uint64_t>(N));
0259                 }
0260                 // LCOV_EXCL_STOP
0261 
0262                 // step 2: write the string
0263                 oa->write_characters(
0264                     reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
0265                     j.m_data.m_value.string->size());
0266                 break;
0267             }
0268 
0269             case value_t::array:
0270             {
0271                 // step 1: write control byte and the array size
0272                 const auto N = j.m_data.m_value.array->size();
0273                 if (N <= 0x17)
0274                 {
0275                     write_number(static_cast<std::uint8_t>(0x80 + N));
0276                 }
0277                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
0278                 {
0279                     oa->write_character(to_char_type(0x98));
0280                     write_number(static_cast<std::uint8_t>(N));
0281                 }
0282                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
0283                 {
0284                     oa->write_character(to_char_type(0x99));
0285                     write_number(static_cast<std::uint16_t>(N));
0286                 }
0287                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
0288                 {
0289                     oa->write_character(to_char_type(0x9A));
0290                     write_number(static_cast<std::uint32_t>(N));
0291                 }
0292                 // LCOV_EXCL_START
0293                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
0294                 {
0295                     oa->write_character(to_char_type(0x9B));
0296                     write_number(static_cast<std::uint64_t>(N));
0297                 }
0298                 // LCOV_EXCL_STOP
0299 
0300                 // step 2: write each element
0301                 for (const auto& el : *j.m_data.m_value.array)
0302                 {
0303                     write_cbor(el);
0304                 }
0305                 break;
0306             }
0307 
0308             case value_t::binary:
0309             {
0310                 if (j.m_data.m_value.binary->has_subtype())
0311                 {
0312                     if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
0313                     {
0314                         write_number(static_cast<std::uint8_t>(0xd8));
0315                         write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
0316                     }
0317                     else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
0318                     {
0319                         write_number(static_cast<std::uint8_t>(0xd9));
0320                         write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
0321                     }
0322                     else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
0323                     {
0324                         write_number(static_cast<std::uint8_t>(0xda));
0325                         write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
0326                     }
0327                     else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
0328                     {
0329                         write_number(static_cast<std::uint8_t>(0xdb));
0330                         write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
0331                     }
0332                 }
0333 
0334                 // step 1: write control byte and the binary array size
0335                 const auto N = j.m_data.m_value.binary->size();
0336                 if (N <= 0x17)
0337                 {
0338                     write_number(static_cast<std::uint8_t>(0x40 + N));
0339                 }
0340                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
0341                 {
0342                     oa->write_character(to_char_type(0x58));
0343                     write_number(static_cast<std::uint8_t>(N));
0344                 }
0345                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
0346                 {
0347                     oa->write_character(to_char_type(0x59));
0348                     write_number(static_cast<std::uint16_t>(N));
0349                 }
0350                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
0351                 {
0352                     oa->write_character(to_char_type(0x5A));
0353                     write_number(static_cast<std::uint32_t>(N));
0354                 }
0355                 // LCOV_EXCL_START
0356                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
0357                 {
0358                     oa->write_character(to_char_type(0x5B));
0359                     write_number(static_cast<std::uint64_t>(N));
0360                 }
0361                 // LCOV_EXCL_STOP
0362 
0363                 // step 2: write each element
0364                 oa->write_characters(
0365                     reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
0366                     N);
0367 
0368                 break;
0369             }
0370 
0371             case value_t::object:
0372             {
0373                 // step 1: write control byte and the object size
0374                 const auto N = j.m_data.m_value.object->size();
0375                 if (N <= 0x17)
0376                 {
0377                     write_number(static_cast<std::uint8_t>(0xA0 + N));
0378                 }
0379                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
0380                 {
0381                     oa->write_character(to_char_type(0xB8));
0382                     write_number(static_cast<std::uint8_t>(N));
0383                 }
0384                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
0385                 {
0386                     oa->write_character(to_char_type(0xB9));
0387                     write_number(static_cast<std::uint16_t>(N));
0388                 }
0389                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
0390                 {
0391                     oa->write_character(to_char_type(0xBA));
0392                     write_number(static_cast<std::uint32_t>(N));
0393                 }
0394                 // LCOV_EXCL_START
0395                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
0396                 {
0397                     oa->write_character(to_char_type(0xBB));
0398                     write_number(static_cast<std::uint64_t>(N));
0399                 }
0400                 // LCOV_EXCL_STOP
0401 
0402                 // step 2: write each element
0403                 for (const auto& el : *j.m_data.m_value.object)
0404                 {
0405                     write_cbor(el.first);
0406                     write_cbor(el.second);
0407                 }
0408                 break;
0409             }
0410 
0411             case value_t::discarded:
0412             default:
0413                 break;
0414         }
0415     }
0416 
0417     /*!
0418     @param[in] j  JSON value to serialize
0419     */
0420     void write_msgpack(const BasicJsonType& j)
0421     {
0422         switch (j.type())
0423         {
0424             case value_t::null: // nil
0425             {
0426                 oa->write_character(to_char_type(0xC0));
0427                 break;
0428             }
0429 
0430             case value_t::boolean: // true and false
0431             {
0432                 oa->write_character(j.m_data.m_value.boolean
0433                                     ? to_char_type(0xC3)
0434                                     : to_char_type(0xC2));
0435                 break;
0436             }
0437 
0438             case value_t::number_integer:
0439             {
0440                 if (j.m_data.m_value.number_integer >= 0)
0441                 {
0442                     // MessagePack does not differentiate between positive
0443                     // signed integers and unsigned integers. Therefore, we used
0444                     // the code from the value_t::number_unsigned case here.
0445                     if (j.m_data.m_value.number_unsigned < 128)
0446                     {
0447                         // positive fixnum
0448                         write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
0449                     }
0450                     else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
0451                     {
0452                         // uint 8
0453                         oa->write_character(to_char_type(0xCC));
0454                         write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
0455                     }
0456                     else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
0457                     {
0458                         // uint 16
0459                         oa->write_character(to_char_type(0xCD));
0460                         write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
0461                     }
0462                     else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
0463                     {
0464                         // uint 32
0465                         oa->write_character(to_char_type(0xCE));
0466                         write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
0467                     }
0468                     else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
0469                     {
0470                         // uint 64
0471                         oa->write_character(to_char_type(0xCF));
0472                         write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
0473                     }
0474                 }
0475                 else
0476                 {
0477                     if (j.m_data.m_value.number_integer >= -32)
0478                     {
0479                         // negative fixnum
0480                         write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
0481                     }
0482                     else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
0483                              j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
0484                     {
0485                         // int 8
0486                         oa->write_character(to_char_type(0xD0));
0487                         write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
0488                     }
0489                     else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
0490                              j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
0491                     {
0492                         // int 16
0493                         oa->write_character(to_char_type(0xD1));
0494                         write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
0495                     }
0496                     else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
0497                              j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
0498                     {
0499                         // int 32
0500                         oa->write_character(to_char_type(0xD2));
0501                         write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
0502                     }
0503                     else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
0504                              j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
0505                     {
0506                         // int 64
0507                         oa->write_character(to_char_type(0xD3));
0508                         write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
0509                     }
0510                 }
0511                 break;
0512             }
0513 
0514             case value_t::number_unsigned:
0515             {
0516                 if (j.m_data.m_value.number_unsigned < 128)
0517                 {
0518                     // positive fixnum
0519                     write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
0520                 }
0521                 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
0522                 {
0523                     // uint 8
0524                     oa->write_character(to_char_type(0xCC));
0525                     write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
0526                 }
0527                 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
0528                 {
0529                     // uint 16
0530                     oa->write_character(to_char_type(0xCD));
0531                     write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
0532                 }
0533                 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
0534                 {
0535                     // uint 32
0536                     oa->write_character(to_char_type(0xCE));
0537                     write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
0538                 }
0539                 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
0540                 {
0541                     // uint 64
0542                     oa->write_character(to_char_type(0xCF));
0543                     write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
0544                 }
0545                 break;
0546             }
0547 
0548             case value_t::number_float:
0549             {
0550                 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
0551                 break;
0552             }
0553 
0554             case value_t::string:
0555             {
0556                 // step 1: write control byte and the string length
0557                 const auto N = j.m_data.m_value.string->size();
0558                 if (N <= 31)
0559                 {
0560                     // fixstr
0561                     write_number(static_cast<std::uint8_t>(0xA0 | N));
0562                 }
0563                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
0564                 {
0565                     // str 8
0566                     oa->write_character(to_char_type(0xD9));
0567                     write_number(static_cast<std::uint8_t>(N));
0568                 }
0569                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
0570                 {
0571                     // str 16
0572                     oa->write_character(to_char_type(0xDA));
0573                     write_number(static_cast<std::uint16_t>(N));
0574                 }
0575                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
0576                 {
0577                     // str 32
0578                     oa->write_character(to_char_type(0xDB));
0579                     write_number(static_cast<std::uint32_t>(N));
0580                 }
0581 
0582                 // step 2: write the string
0583                 oa->write_characters(
0584                     reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
0585                     j.m_data.m_value.string->size());
0586                 break;
0587             }
0588 
0589             case value_t::array:
0590             {
0591                 // step 1: write control byte and the array size
0592                 const auto N = j.m_data.m_value.array->size();
0593                 if (N <= 15)
0594                 {
0595                     // fixarray
0596                     write_number(static_cast<std::uint8_t>(0x90 | N));
0597                 }
0598                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
0599                 {
0600                     // array 16
0601                     oa->write_character(to_char_type(0xDC));
0602                     write_number(static_cast<std::uint16_t>(N));
0603                 }
0604                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
0605                 {
0606                     // array 32
0607                     oa->write_character(to_char_type(0xDD));
0608                     write_number(static_cast<std::uint32_t>(N));
0609                 }
0610 
0611                 // step 2: write each element
0612                 for (const auto& el : *j.m_data.m_value.array)
0613                 {
0614                     write_msgpack(el);
0615                 }
0616                 break;
0617             }
0618 
0619             case value_t::binary:
0620             {
0621                 // step 0: determine if the binary type has a set subtype to
0622                 // determine whether to use the ext or fixext types
0623                 const bool use_ext = j.m_data.m_value.binary->has_subtype();
0624 
0625                 // step 1: write control byte and the byte string length
0626                 const auto N = j.m_data.m_value.binary->size();
0627                 if (N <= (std::numeric_limits<std::uint8_t>::max)())
0628                 {
0629                     std::uint8_t output_type{};
0630                     bool fixed = true;
0631                     if (use_ext)
0632                     {
0633                         switch (N)
0634                         {
0635                             case 1:
0636                                 output_type = 0xD4; // fixext 1
0637                                 break;
0638                             case 2:
0639                                 output_type = 0xD5; // fixext 2
0640                                 break;
0641                             case 4:
0642                                 output_type = 0xD6; // fixext 4
0643                                 break;
0644                             case 8:
0645                                 output_type = 0xD7; // fixext 8
0646                                 break;
0647                             case 16:
0648                                 output_type = 0xD8; // fixext 16
0649                                 break;
0650                             default:
0651                                 output_type = 0xC7; // ext 8
0652                                 fixed = false;
0653                                 break;
0654                         }
0655 
0656                     }
0657                     else
0658                     {
0659                         output_type = 0xC4; // bin 8
0660                         fixed = false;
0661                     }
0662 
0663                     oa->write_character(to_char_type(output_type));
0664                     if (!fixed)
0665                     {
0666                         write_number(static_cast<std::uint8_t>(N));
0667                     }
0668                 }
0669                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
0670                 {
0671                     const std::uint8_t output_type = use_ext
0672                                                      ? 0xC8 // ext 16
0673                                                      : 0xC5; // bin 16
0674 
0675                     oa->write_character(to_char_type(output_type));
0676                     write_number(static_cast<std::uint16_t>(N));
0677                 }
0678                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
0679                 {
0680                     const std::uint8_t output_type = use_ext
0681                                                      ? 0xC9 // ext 32
0682                                                      : 0xC6; // bin 32
0683 
0684                     oa->write_character(to_char_type(output_type));
0685                     write_number(static_cast<std::uint32_t>(N));
0686                 }
0687 
0688                 // step 1.5: if this is an ext type, write the subtype
0689                 if (use_ext)
0690                 {
0691                     write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
0692                 }
0693 
0694                 // step 2: write the byte string
0695                 oa->write_characters(
0696                     reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
0697                     N);
0698 
0699                 break;
0700             }
0701 
0702             case value_t::object:
0703             {
0704                 // step 1: write control byte and the object size
0705                 const auto N = j.m_data.m_value.object->size();
0706                 if (N <= 15)
0707                 {
0708                     // fixmap
0709                     write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
0710                 }
0711                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
0712                 {
0713                     // map 16
0714                     oa->write_character(to_char_type(0xDE));
0715                     write_number(static_cast<std::uint16_t>(N));
0716                 }
0717                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
0718                 {
0719                     // map 32
0720                     oa->write_character(to_char_type(0xDF));
0721                     write_number(static_cast<std::uint32_t>(N));
0722                 }
0723 
0724                 // step 2: write each element
0725                 for (const auto& el : *j.m_data.m_value.object)
0726                 {
0727                     write_msgpack(el.first);
0728                     write_msgpack(el.second);
0729                 }
0730                 break;
0731             }
0732 
0733             case value_t::discarded:
0734             default:
0735                 break;
0736         }
0737     }
0738 
0739     /*!
0740     @param[in] j  JSON value to serialize
0741     @param[in] use_count   whether to use '#' prefixes (optimized format)
0742     @param[in] use_type    whether to use '$' prefixes (optimized format)
0743     @param[in] add_prefix  whether prefixes need to be used for this value
0744     @param[in] use_bjdata  whether write in BJData format, default is false
0745     @param[in] bjdata_version  which BJData version to use, default is draft2
0746     */
0747     void write_ubjson(const BasicJsonType& j, const bool use_count,
0748                       const bool use_type, const bool add_prefix = true,
0749                       const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2)
0750     {
0751         const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3;
0752 
0753         switch (j.type())
0754         {
0755             case value_t::null:
0756             {
0757                 if (add_prefix)
0758                 {
0759                     oa->write_character(to_char_type('Z'));
0760                 }
0761                 break;
0762             }
0763 
0764             case value_t::boolean:
0765             {
0766                 if (add_prefix)
0767                 {
0768                     oa->write_character(j.m_data.m_value.boolean
0769                                         ? to_char_type('T')
0770                                         : to_char_type('F'));
0771                 }
0772                 break;
0773             }
0774 
0775             case value_t::number_integer:
0776             {
0777                 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
0778                 break;
0779             }
0780 
0781             case value_t::number_unsigned:
0782             {
0783                 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
0784                 break;
0785             }
0786 
0787             case value_t::number_float:
0788             {
0789                 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
0790                 break;
0791             }
0792 
0793             case value_t::string:
0794             {
0795                 if (add_prefix)
0796                 {
0797                     oa->write_character(to_char_type('S'));
0798                 }
0799                 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
0800                 oa->write_characters(
0801                     reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
0802                     j.m_data.m_value.string->size());
0803                 break;
0804             }
0805 
0806             case value_t::array:
0807             {
0808                 if (add_prefix)
0809                 {
0810                     oa->write_character(to_char_type('['));
0811                 }
0812 
0813                 bool prefix_required = true;
0814                 if (use_type && !j.m_data.m_value.array->empty())
0815                 {
0816                     JSON_ASSERT(use_count);
0817                     const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
0818                     const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
0819                                                          [this, first_prefix, use_bjdata](const BasicJsonType & v)
0820                     {
0821                         return ubjson_prefix(v, use_bjdata) == first_prefix;
0822                     });
0823 
0824                     std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
0825 
0826                     if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
0827                     {
0828                         prefix_required = false;
0829                         oa->write_character(to_char_type('$'));
0830                         oa->write_character(first_prefix);
0831                     }
0832                 }
0833 
0834                 if (use_count)
0835                 {
0836                     oa->write_character(to_char_type('#'));
0837                     write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
0838                 }
0839 
0840                 for (const auto& el : *j.m_data.m_value.array)
0841                 {
0842                     write_ubjson(el, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
0843                 }
0844 
0845                 if (!use_count)
0846                 {
0847                     oa->write_character(to_char_type(']'));
0848                 }
0849 
0850                 break;
0851             }
0852 
0853             case value_t::binary:
0854             {
0855                 if (add_prefix)
0856                 {
0857                     oa->write_character(to_char_type('['));
0858                 }
0859 
0860                 if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
0861                 {
0862                     JSON_ASSERT(use_count);
0863                     oa->write_character(to_char_type('$'));
0864                     oa->write_character(bjdata_draft3 ? 'B' : 'U');
0865                 }
0866 
0867                 if (use_count)
0868                 {
0869                     oa->write_character(to_char_type('#'));
0870                     write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
0871                 }
0872 
0873                 if (use_type)
0874                 {
0875                     oa->write_characters(
0876                         reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
0877                         j.m_data.m_value.binary->size());
0878                 }
0879                 else
0880                 {
0881                     for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
0882                     {
0883                         oa->write_character(to_char_type(bjdata_draft3 ? 'B' : 'U'));
0884                         oa->write_character(j.m_data.m_value.binary->data()[i]);
0885                     }
0886                 }
0887 
0888                 if (!use_count)
0889                 {
0890                     oa->write_character(to_char_type(']'));
0891                 }
0892 
0893                 break;
0894             }
0895 
0896             case value_t::object:
0897             {
0898                 if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
0899                 {
0900                     if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type, bjdata_version))  // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
0901                     {
0902                         break;
0903                     }
0904                 }
0905 
0906                 if (add_prefix)
0907                 {
0908                     oa->write_character(to_char_type('{'));
0909                 }
0910 
0911                 bool prefix_required = true;
0912                 if (use_type && !j.m_data.m_value.object->empty())
0913                 {
0914                     JSON_ASSERT(use_count);
0915                     const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
0916                     const bool same_prefix = std::all_of(j.begin(), j.end(),
0917                                                          [this, first_prefix, use_bjdata](const BasicJsonType & v)
0918                     {
0919                         return ubjson_prefix(v, use_bjdata) == first_prefix;
0920                     });
0921 
0922                     std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
0923 
0924                     if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
0925                     {
0926                         prefix_required = false;
0927                         oa->write_character(to_char_type('$'));
0928                         oa->write_character(first_prefix);
0929                     }
0930                 }
0931 
0932                 if (use_count)
0933                 {
0934                     oa->write_character(to_char_type('#'));
0935                     write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
0936                 }
0937 
0938                 for (const auto& el : *j.m_data.m_value.object)
0939                 {
0940                     write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
0941                     oa->write_characters(
0942                         reinterpret_cast<const CharType*>(el.first.c_str()),
0943                         el.first.size());
0944                     write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
0945                 }
0946 
0947                 if (!use_count)
0948                 {
0949                     oa->write_character(to_char_type('}'));
0950                 }
0951 
0952                 break;
0953             }
0954 
0955             case value_t::discarded:
0956             default:
0957                 break;
0958         }
0959     }
0960 
0961   private:
0962     //////////
0963     // BSON //
0964     //////////
0965 
0966     /*!
0967     @return The size of a BSON document entry header, including the id marker
0968             and the entry name size (and its null-terminator).
0969     */
0970     static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
0971     {
0972         const auto it = name.find(static_cast<typename string_t::value_type>(0));
0973         if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
0974         {
0975             JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
0976             static_cast<void>(j);
0977         }
0978 
0979         return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
0980     }
0981 
0982     /*!
0983     @brief Writes the given @a element_type and @a name to the output adapter
0984     */
0985     void write_bson_entry_header(const string_t& name,
0986                                  const std::uint8_t element_type)
0987     {
0988         oa->write_character(to_char_type(element_type)); // boolean
0989         oa->write_characters(
0990             reinterpret_cast<const CharType*>(name.c_str()),
0991             name.size() + 1u);
0992     }
0993 
0994     /*!
0995     @brief Writes a BSON element with key @a name and boolean value @a value
0996     */
0997     void write_bson_boolean(const string_t& name,
0998                             const bool value)
0999     {
1000         write_bson_entry_header(name, 0x08);
1001         oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
1002     }
1003 
1004     /*!
1005     @brief Writes a BSON element with key @a name and double value @a value
1006     */
1007     void write_bson_double(const string_t& name,
1008                            const double value)
1009     {
1010         write_bson_entry_header(name, 0x01);
1011         write_number<double>(value, true);
1012     }
1013 
1014     /*!
1015     @return The size of the BSON-encoded string in @a value
1016     */
1017     static std::size_t calc_bson_string_size(const string_t& value)
1018     {
1019         return sizeof(std::int32_t) + value.size() + 1ul;
1020     }
1021 
1022     /*!
1023     @brief Writes a BSON element with key @a name and string value @a value
1024     */
1025     void write_bson_string(const string_t& name,
1026                            const string_t& value)
1027     {
1028         write_bson_entry_header(name, 0x02);
1029 
1030         write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
1031         oa->write_characters(
1032             reinterpret_cast<const CharType*>(value.c_str()),
1033             value.size() + 1);
1034     }
1035 
1036     /*!
1037     @brief Writes a BSON element with key @a name and null value
1038     */
1039     void write_bson_null(const string_t& name)
1040     {
1041         write_bson_entry_header(name, 0x0A);
1042     }
1043 
1044     /*!
1045     @return The size of the BSON-encoded integer @a value
1046     */
1047     static std::size_t calc_bson_integer_size(const std::int64_t value)
1048     {
1049         return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
1050                ? sizeof(std::int32_t)
1051                : sizeof(std::int64_t);
1052     }
1053 
1054     /*!
1055     @brief Writes a BSON element with key @a name and integer @a value
1056     */
1057     void write_bson_integer(const string_t& name,
1058                             const std::int64_t value)
1059     {
1060         if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
1061         {
1062             write_bson_entry_header(name, 0x10); // int32
1063             write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
1064         }
1065         else
1066         {
1067             write_bson_entry_header(name, 0x12); // int64
1068             write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
1069         }
1070     }
1071 
1072     /*!
1073     @return The size of the BSON-encoded unsigned integer in @a j
1074     */
1075     static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
1076     {
1077         return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
1078                ? sizeof(std::int32_t)
1079                : sizeof(std::int64_t);
1080     }
1081 
1082     /*!
1083     @brief Writes a BSON element with key @a name and unsigned @a value
1084     */
1085     void write_bson_unsigned(const string_t& name,
1086                              const BasicJsonType& j)
1087     {
1088         if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
1089         {
1090             write_bson_entry_header(name, 0x10 /* int32 */);
1091             write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
1092         }
1093         else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
1094         {
1095             write_bson_entry_header(name, 0x12 /* int64 */);
1096             write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
1097         }
1098         else
1099         {
1100             write_bson_entry_header(name, 0x11 /* uint64 */);
1101             write_number<std::uint64_t>(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned), true);
1102         }
1103     }
1104 
1105     /*!
1106     @brief Writes a BSON element with key @a name and object @a value
1107     */
1108     void write_bson_object_entry(const string_t& name,
1109                                  const typename BasicJsonType::object_t& value)
1110     {
1111         write_bson_entry_header(name, 0x03); // object
1112         write_bson_object(value);
1113     }
1114 
1115     /*!
1116     @return The size of the BSON-encoded array @a value
1117     */
1118     static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
1119     {
1120         std::size_t array_index = 0ul;
1121 
1122         const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
1123         {
1124             return result + calc_bson_element_size(std::to_string(array_index++), el);
1125         });
1126 
1127         return sizeof(std::int32_t) + embedded_document_size + 1ul;
1128     }
1129 
1130     /*!
1131     @return The size of the BSON-encoded binary array @a value
1132     */
1133     static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
1134     {
1135         return sizeof(std::int32_t) + value.size() + 1ul;
1136     }
1137 
1138     /*!
1139     @brief Writes a BSON element with key @a name and array @a value
1140     */
1141     void write_bson_array(const string_t& name,
1142                           const typename BasicJsonType::array_t& value)
1143     {
1144         write_bson_entry_header(name, 0x04); // array
1145         write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
1146 
1147         std::size_t array_index = 0ul;
1148 
1149         for (const auto& el : value)
1150         {
1151             write_bson_element(std::to_string(array_index++), el);
1152         }
1153 
1154         oa->write_character(to_char_type(0x00));
1155     }
1156 
1157     /*!
1158     @brief Writes a BSON element with key @a name and binary value @a value
1159     */
1160     void write_bson_binary(const string_t& name,
1161                            const binary_t& value)
1162     {
1163         write_bson_entry_header(name, 0x05);
1164 
1165         write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
1166         write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
1167 
1168         oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
1169     }
1170 
1171     /*!
1172     @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
1173     @return The calculated size for the BSON document entry for @a j with the given @a name.
1174     */
1175     static std::size_t calc_bson_element_size(const string_t& name,
1176             const BasicJsonType& j)
1177     {
1178         const auto header_size = calc_bson_entry_header_size(name, j);
1179         switch (j.type())
1180         {
1181             case value_t::object:
1182                 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
1183 
1184             case value_t::array:
1185                 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
1186 
1187             case value_t::binary:
1188                 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
1189 
1190             case value_t::boolean:
1191                 return header_size + 1ul;
1192 
1193             case value_t::number_float:
1194                 return header_size + 8ul;
1195 
1196             case value_t::number_integer:
1197                 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
1198 
1199             case value_t::number_unsigned:
1200                 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
1201 
1202             case value_t::string:
1203                 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
1204 
1205             case value_t::null:
1206                 return header_size + 0ul;
1207 
1208             // LCOV_EXCL_START
1209             case value_t::discarded:
1210             default:
1211                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
1212                 return 0ul;
1213                 // LCOV_EXCL_STOP
1214         }
1215     }
1216 
1217     /*!
1218     @brief Serializes the JSON value @a j to BSON and associates it with the
1219            key @a name.
1220     @param name The name to associate with the JSON entity @a j within the
1221                 current BSON document
1222     */
1223     void write_bson_element(const string_t& name,
1224                             const BasicJsonType& j)
1225     {
1226         switch (j.type())
1227         {
1228             case value_t::object:
1229                 return write_bson_object_entry(name, *j.m_data.m_value.object);
1230 
1231             case value_t::array:
1232                 return write_bson_array(name, *j.m_data.m_value.array);
1233 
1234             case value_t::binary:
1235                 return write_bson_binary(name, *j.m_data.m_value.binary);
1236 
1237             case value_t::boolean:
1238                 return write_bson_boolean(name, j.m_data.m_value.boolean);
1239 
1240             case value_t::number_float:
1241                 return write_bson_double(name, j.m_data.m_value.number_float);
1242 
1243             case value_t::number_integer:
1244                 return write_bson_integer(name, j.m_data.m_value.number_integer);
1245 
1246             case value_t::number_unsigned:
1247                 return write_bson_unsigned(name, j);
1248 
1249             case value_t::string:
1250                 return write_bson_string(name, *j.m_data.m_value.string);
1251 
1252             case value_t::null:
1253                 return write_bson_null(name);
1254 
1255             // LCOV_EXCL_START
1256             case value_t::discarded:
1257             default:
1258                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
1259                 return;
1260                 // LCOV_EXCL_STOP
1261         }
1262     }
1263 
1264     /*!
1265     @brief Calculates the size of the BSON serialization of the given
1266            JSON-object @a j.
1267     @param[in] value  JSON value to serialize
1268     @pre       value.type() == value_t::object
1269     */
1270     static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
1271     {
1272         const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
1273                                           [](size_t result, const typename BasicJsonType::object_t::value_type & el)
1274         {
1275             return result += calc_bson_element_size(el.first, el.second);
1276         });
1277 
1278         return sizeof(std::int32_t) + document_size + 1ul;
1279     }
1280 
1281     /*!
1282     @param[in] value  JSON value to serialize
1283     @pre       value.type() == value_t::object
1284     */
1285     void write_bson_object(const typename BasicJsonType::object_t& value)
1286     {
1287         write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
1288 
1289         for (const auto& el : value)
1290         {
1291             write_bson_element(el.first, el.second);
1292         }
1293 
1294         oa->write_character(to_char_type(0x00));
1295     }
1296 
1297     //////////
1298     // CBOR //
1299     //////////
1300 
1301     static constexpr CharType get_cbor_float_prefix(float /*unused*/)
1302     {
1303         return to_char_type(0xFA);  // Single-Precision Float
1304     }
1305 
1306     static constexpr CharType get_cbor_float_prefix(double /*unused*/)
1307     {
1308         return to_char_type(0xFB);  // Double-Precision Float
1309     }
1310 
1311     /////////////
1312     // MsgPack //
1313     /////////////
1314 
1315     static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
1316     {
1317         return to_char_type(0xCA);  // float 32
1318     }
1319 
1320     static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
1321     {
1322         return to_char_type(0xCB);  // float 64
1323     }
1324 
1325     ////////////
1326     // UBJSON //
1327     ////////////
1328 
1329     // UBJSON: write number (floating point)
1330     template<typename NumberType, typename std::enable_if<
1331                  std::is_floating_point<NumberType>::value, int>::type = 0>
1332     void write_number_with_ubjson_prefix(const NumberType n,
1333                                          const bool add_prefix,
1334                                          const bool use_bjdata)
1335     {
1336         if (add_prefix)
1337         {
1338             oa->write_character(get_ubjson_float_prefix(n));
1339         }
1340         write_number(n, use_bjdata);
1341     }
1342 
1343     // UBJSON: write number (unsigned integer)
1344     template<typename NumberType, typename std::enable_if<
1345                  std::is_unsigned<NumberType>::value, int>::type = 0>
1346     void write_number_with_ubjson_prefix(const NumberType n,
1347                                          const bool add_prefix,
1348                                          const bool use_bjdata)
1349     {
1350         if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
1351         {
1352             if (add_prefix)
1353             {
1354                 oa->write_character(to_char_type('i'));  // int8
1355             }
1356             write_number(static_cast<std::uint8_t>(n), use_bjdata);
1357         }
1358         else if (n <= (std::numeric_limits<std::uint8_t>::max)())
1359         {
1360             if (add_prefix)
1361             {
1362                 oa->write_character(to_char_type('U'));  // uint8
1363             }
1364             write_number(static_cast<std::uint8_t>(n), use_bjdata);
1365         }
1366         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
1367         {
1368             if (add_prefix)
1369             {
1370                 oa->write_character(to_char_type('I'));  // int16
1371             }
1372             write_number(static_cast<std::int16_t>(n), use_bjdata);
1373         }
1374         else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
1375         {
1376             if (add_prefix)
1377             {
1378                 oa->write_character(to_char_type('u'));  // uint16 - bjdata only
1379             }
1380             write_number(static_cast<std::uint16_t>(n), use_bjdata);
1381         }
1382         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
1383         {
1384             if (add_prefix)
1385             {
1386                 oa->write_character(to_char_type('l'));  // int32
1387             }
1388             write_number(static_cast<std::int32_t>(n), use_bjdata);
1389         }
1390         else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
1391         {
1392             if (add_prefix)
1393             {
1394                 oa->write_character(to_char_type('m'));  // uint32 - bjdata only
1395             }
1396             write_number(static_cast<std::uint32_t>(n), use_bjdata);
1397         }
1398         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
1399         {
1400             if (add_prefix)
1401             {
1402                 oa->write_character(to_char_type('L'));  // int64
1403             }
1404             write_number(static_cast<std::int64_t>(n), use_bjdata);
1405         }
1406         else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
1407         {
1408             if (add_prefix)
1409             {
1410                 oa->write_character(to_char_type('M'));  // uint64 - bjdata only
1411             }
1412             write_number(static_cast<std::uint64_t>(n), use_bjdata);
1413         }
1414         else
1415         {
1416             if (add_prefix)
1417             {
1418                 oa->write_character(to_char_type('H'));  // high-precision number
1419             }
1420 
1421             const auto number = BasicJsonType(n).dump();
1422             write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
1423             for (std::size_t i = 0; i < number.size(); ++i)
1424             {
1425                 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
1426             }
1427         }
1428     }
1429 
1430     // UBJSON: write number (signed integer)
1431     template < typename NumberType, typename std::enable_if <
1432                    std::is_signed<NumberType>::value&&
1433                    !std::is_floating_point<NumberType>::value, int >::type = 0 >
1434     void write_number_with_ubjson_prefix(const NumberType n,
1435                                          const bool add_prefix,
1436                                          const bool use_bjdata)
1437     {
1438         if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
1439         {
1440             if (add_prefix)
1441             {
1442                 oa->write_character(to_char_type('i'));  // int8
1443             }
1444             write_number(static_cast<std::int8_t>(n), use_bjdata);
1445         }
1446         else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
1447         {
1448             if (add_prefix)
1449             {
1450                 oa->write_character(to_char_type('U'));  // uint8
1451             }
1452             write_number(static_cast<std::uint8_t>(n), use_bjdata);
1453         }
1454         else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
1455         {
1456             if (add_prefix)
1457             {
1458                 oa->write_character(to_char_type('I'));  // int16
1459             }
1460             write_number(static_cast<std::int16_t>(n), use_bjdata);
1461         }
1462         else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
1463         {
1464             if (add_prefix)
1465             {
1466                 oa->write_character(to_char_type('u'));  // uint16 - bjdata only
1467             }
1468             write_number(static_cast<uint16_t>(n), use_bjdata);
1469         }
1470         else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
1471         {
1472             if (add_prefix)
1473             {
1474                 oa->write_character(to_char_type('l'));  // int32
1475             }
1476             write_number(static_cast<std::int32_t>(n), use_bjdata);
1477         }
1478         else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
1479         {
1480             if (add_prefix)
1481             {
1482                 oa->write_character(to_char_type('m'));  // uint32 - bjdata only
1483             }
1484             write_number(static_cast<uint32_t>(n), use_bjdata);
1485         }
1486         else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
1487         {
1488             if (add_prefix)
1489             {
1490                 oa->write_character(to_char_type('L'));  // int64
1491             }
1492             write_number(static_cast<std::int64_t>(n), use_bjdata);
1493         }
1494         // LCOV_EXCL_START
1495         else
1496         {
1497             if (add_prefix)
1498             {
1499                 oa->write_character(to_char_type('H'));  // high-precision number
1500             }
1501 
1502             const auto number = BasicJsonType(n).dump();
1503             write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
1504             for (std::size_t i = 0; i < number.size(); ++i)
1505             {
1506                 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
1507             }
1508         }
1509         // LCOV_EXCL_STOP
1510     }
1511 
1512     /*!
1513     @brief determine the type prefix of container values
1514     */
1515     CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
1516     {
1517         switch (j.type())
1518         {
1519             case value_t::null:
1520                 return 'Z';
1521 
1522             case value_t::boolean:
1523                 return j.m_data.m_value.boolean ? 'T' : 'F';
1524 
1525             case value_t::number_integer:
1526             {
1527                 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
1528                 {
1529                     return 'i';
1530                 }
1531                 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
1532                 {
1533                     return 'U';
1534                 }
1535                 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
1536                 {
1537                     return 'I';
1538                 }
1539                 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
1540                 {
1541                     return 'u';
1542                 }
1543                 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
1544                 {
1545                     return 'l';
1546                 }
1547                 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
1548                 {
1549                     return 'm';
1550                 }
1551                 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
1552                 {
1553                     return 'L';
1554                 }
1555                 // anything else is treated as high-precision number
1556                 return 'H'; // LCOV_EXCL_LINE
1557             }
1558 
1559             case value_t::number_unsigned:
1560             {
1561                 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
1562                 {
1563                     return 'i';
1564                 }
1565                 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
1566                 {
1567                     return 'U';
1568                 }
1569                 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
1570                 {
1571                     return 'I';
1572                 }
1573                 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
1574                 {
1575                     return 'u';
1576                 }
1577                 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
1578                 {
1579                     return 'l';
1580                 }
1581                 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
1582                 {
1583                     return 'm';
1584                 }
1585                 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
1586                 {
1587                     return 'L';
1588                 }
1589                 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
1590                 {
1591                     return 'M';
1592                 }
1593                 // anything else is treated as high-precision number
1594                 return 'H'; // LCOV_EXCL_LINE
1595             }
1596 
1597             case value_t::number_float:
1598                 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
1599 
1600             case value_t::string:
1601                 return 'S';
1602 
1603             case value_t::array: // fallthrough
1604             case value_t::binary:
1605                 return '[';
1606 
1607             case value_t::object:
1608                 return '{';
1609 
1610             case value_t::discarded:
1611             default:  // discarded values
1612                 return 'N';
1613         }
1614     }
1615 
1616     static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
1617     {
1618         return 'd';  // float 32
1619     }
1620 
1621     static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
1622     {
1623         return 'D';  // float 64
1624     }
1625 
1626     /*!
1627     @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid
1628     */
1629     bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
1630     {
1631         std::map<string_t, CharType> bjdtype = {{"uint8", 'U'},  {"int8", 'i'},  {"uint16", 'u'}, {"int16", 'I'},
1632             {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'},
1633             {"char", 'C'}, {"byte", 'B'}
1634         };
1635 
1636         string_t key = "_ArrayType_";
1637         auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
1638         if (it == bjdtype.end())
1639         {
1640             return true;
1641         }
1642         CharType dtype = it->second;
1643 
1644         key = "_ArraySize_";
1645         std::size_t len = (value.at(key).empty() ? 0 : 1);
1646         for (const auto& el : value.at(key))
1647         {
1648             len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
1649         }
1650 
1651         key = "_ArrayData_";
1652         if (value.at(key).size() != len)
1653         {
1654             return true;
1655         }
1656 
1657         oa->write_character('[');
1658         oa->write_character('$');
1659         oa->write_character(dtype);
1660         oa->write_character('#');
1661 
1662         key = "_ArraySize_";
1663         write_ubjson(value.at(key), use_count, use_type, true,  true, bjdata_version);
1664 
1665         key = "_ArrayData_";
1666         if (dtype == 'U' || dtype == 'C' || dtype == 'B')
1667         {
1668             for (const auto& el : value.at(key))
1669             {
1670                 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
1671             }
1672         }
1673         else if (dtype == 'i')
1674         {
1675             for (const auto& el : value.at(key))
1676             {
1677                 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
1678             }
1679         }
1680         else if (dtype == 'u')
1681         {
1682             for (const auto& el : value.at(key))
1683             {
1684                 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
1685             }
1686         }
1687         else if (dtype == 'I')
1688         {
1689             for (const auto& el : value.at(key))
1690             {
1691                 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
1692             }
1693         }
1694         else if (dtype == 'm')
1695         {
1696             for (const auto& el : value.at(key))
1697             {
1698                 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
1699             }
1700         }
1701         else if (dtype == 'l')
1702         {
1703             for (const auto& el : value.at(key))
1704             {
1705                 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
1706             }
1707         }
1708         else if (dtype == 'M')
1709         {
1710             for (const auto& el : value.at(key))
1711             {
1712                 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
1713             }
1714         }
1715         else if (dtype == 'L')
1716         {
1717             for (const auto& el : value.at(key))
1718             {
1719                 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
1720             }
1721         }
1722         else if (dtype == 'd')
1723         {
1724             for (const auto& el : value.at(key))
1725             {
1726                 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
1727             }
1728         }
1729         else if (dtype == 'D')
1730         {
1731             for (const auto& el : value.at(key))
1732             {
1733                 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
1734             }
1735         }
1736         return false;
1737     }
1738 
1739     ///////////////////////
1740     // Utility functions //
1741     ///////////////////////
1742 
1743     /*
1744     @brief write a number to output input
1745     @param[in] n number of type @a NumberType
1746     @param[in] OutputIsLittleEndian Set to true if output data is
1747                                  required to be little endian
1748     @tparam NumberType the type of the number
1749 
1750     @note This function needs to respect the system's endianness, because bytes
1751           in CBOR, MessagePack, and UBJSON are stored in network order (big
1752           endian) and therefore need reordering on little endian systems.
1753           On the other hand, BSON and BJData use little endian and should reorder
1754           on big endian systems.
1755     */
1756     template<typename NumberType>
1757     void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
1758     {
1759         // step 1: write number to array of length NumberType
1760         std::array<CharType, sizeof(NumberType)> vec{};
1761         std::memcpy(vec.data(), &n, sizeof(NumberType));
1762 
1763         // step 2: write array to output (with possible reordering)
1764         if (is_little_endian != OutputIsLittleEndian)
1765         {
1766             // reverse byte order prior to conversion if necessary
1767             std::reverse(vec.begin(), vec.end());
1768         }
1769 
1770         oa->write_characters(vec.data(), sizeof(NumberType));
1771     }
1772 
1773     void write_compact_float(const number_float_t n, detail::input_format_t format)
1774     {
1775 #ifdef __GNUC__
1776 #pragma GCC diagnostic push
1777 #pragma GCC diagnostic ignored "-Wfloat-equal"
1778 #endif
1779         if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
1780                 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
1781                 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
1782         {
1783             oa->write_character(format == detail::input_format_t::cbor
1784                                 ? get_cbor_float_prefix(static_cast<float>(n))
1785                                 : get_msgpack_float_prefix(static_cast<float>(n)));
1786             write_number(static_cast<float>(n));
1787         }
1788         else
1789         {
1790             oa->write_character(format == detail::input_format_t::cbor
1791                                 ? get_cbor_float_prefix(n)
1792                                 : get_msgpack_float_prefix(n));
1793             write_number(n);
1794         }
1795 #ifdef __GNUC__
1796 #pragma GCC diagnostic pop
1797 #endif
1798     }
1799 
1800   public:
1801     // The following to_char_type functions are implement the conversion
1802     // between uint8_t and CharType. In case CharType is not unsigned,
1803     // such a conversion is required to allow values greater than 128.
1804     // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
1805     template < typename C = CharType,
1806                enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
1807     static constexpr CharType to_char_type(std::uint8_t x) noexcept
1808     {
1809         return *reinterpret_cast<char*>(&x);
1810     }
1811 
1812     template < typename C = CharType,
1813                enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
1814     static CharType to_char_type(std::uint8_t x) noexcept
1815     {
1816         static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
1817         static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
1818         CharType result;
1819         std::memcpy(&result, &x, sizeof(x));
1820         return result;
1821     }
1822 
1823     template<typename C = CharType,
1824              enable_if_t<std::is_unsigned<C>::value>* = nullptr>
1825     static constexpr CharType to_char_type(std::uint8_t x) noexcept
1826     {
1827         return x;
1828     }
1829 
1830     template < typename InputCharType, typename C = CharType,
1831                enable_if_t <
1832                    std::is_signed<C>::value &&
1833                    std::is_signed<char>::value &&
1834                    std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
1835                    > * = nullptr >
1836     static constexpr CharType to_char_type(InputCharType x) noexcept
1837     {
1838         return x;
1839     }
1840 
1841   private:
1842     /// whether we can assume little endianness
1843     const bool is_little_endian = little_endianness();
1844 
1845     /// the output
1846     output_adapter_t<CharType> oa = nullptr;
1847 };
1848 
1849 }  // namespace detail
1850 NLOHMANN_JSON_NAMESPACE_END