Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:02:20

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