1c5f01b2fSopenharmony_ci//     __ _____ _____ _____
2c5f01b2fSopenharmony_ci//  __|  |   __|     |   | |  JSON for Modern C++
3c5f01b2fSopenharmony_ci// |  |  |__   |  |  | | | |  version 3.11.2
4c5f01b2fSopenharmony_ci// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5c5f01b2fSopenharmony_ci//
6c5f01b2fSopenharmony_ci// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de>
7c5f01b2fSopenharmony_ci// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
8c5f01b2fSopenharmony_ci// SPDX-License-Identifier: MIT
9c5f01b2fSopenharmony_ci
10c5f01b2fSopenharmony_ci#pragma once
11c5f01b2fSopenharmony_ci
12c5f01b2fSopenharmony_ci#include <algorithm> // reverse, remove, fill, find, none_of
13c5f01b2fSopenharmony_ci#include <array> // array
14c5f01b2fSopenharmony_ci#include <clocale> // localeconv, lconv
15c5f01b2fSopenharmony_ci#include <cmath> // labs, isfinite, isnan, signbit
16c5f01b2fSopenharmony_ci#include <cstddef> // size_t, ptrdiff_t
17c5f01b2fSopenharmony_ci#include <cstdint> // uint8_t
18c5f01b2fSopenharmony_ci#include <cstdio> // snprintf
19c5f01b2fSopenharmony_ci#include <limits> // numeric_limits
20c5f01b2fSopenharmony_ci#include <string> // string, char_traits
21c5f01b2fSopenharmony_ci#include <iomanip> // setfill, setw
22c5f01b2fSopenharmony_ci#include <type_traits> // is_same
23c5f01b2fSopenharmony_ci#include <utility> // move
24c5f01b2fSopenharmony_ci
25c5f01b2fSopenharmony_ci#include <nlohmann/detail/conversions/to_chars.hpp>
26c5f01b2fSopenharmony_ci#include <nlohmann/detail/exceptions.hpp>
27c5f01b2fSopenharmony_ci#include <nlohmann/detail/macro_scope.hpp>
28c5f01b2fSopenharmony_ci#include <nlohmann/detail/meta/cpp_future.hpp>
29c5f01b2fSopenharmony_ci#include <nlohmann/detail/output/binary_writer.hpp>
30c5f01b2fSopenharmony_ci#include <nlohmann/detail/output/output_adapters.hpp>
31c5f01b2fSopenharmony_ci#include <nlohmann/detail/string_concat.hpp>
32c5f01b2fSopenharmony_ci#include <nlohmann/detail/value_t.hpp>
33c5f01b2fSopenharmony_ci
34c5f01b2fSopenharmony_ciNLOHMANN_JSON_NAMESPACE_BEGIN
35c5f01b2fSopenharmony_cinamespace detail
36c5f01b2fSopenharmony_ci{
37c5f01b2fSopenharmony_ci
38c5f01b2fSopenharmony_ci///////////////////
39c5f01b2fSopenharmony_ci// serialization //
40c5f01b2fSopenharmony_ci///////////////////
41c5f01b2fSopenharmony_ci
42c5f01b2fSopenharmony_ci/// how to treat decoding errors
43c5f01b2fSopenharmony_cienum class error_handler_t
44c5f01b2fSopenharmony_ci{
45c5f01b2fSopenharmony_ci    strict,  ///< throw a type_error exception in case of invalid UTF-8
46c5f01b2fSopenharmony_ci    replace, ///< replace invalid UTF-8 sequences with U+FFFD
47c5f01b2fSopenharmony_ci    ignore   ///< ignore invalid UTF-8 sequences
48c5f01b2fSopenharmony_ci};
49c5f01b2fSopenharmony_ci
50c5f01b2fSopenharmony_citemplate<typename BasicJsonType>
51c5f01b2fSopenharmony_ciclass serializer
52c5f01b2fSopenharmony_ci{
53c5f01b2fSopenharmony_ci    using string_t = typename BasicJsonType::string_t;
54c5f01b2fSopenharmony_ci    using number_float_t = typename BasicJsonType::number_float_t;
55c5f01b2fSopenharmony_ci    using number_integer_t = typename BasicJsonType::number_integer_t;
56c5f01b2fSopenharmony_ci    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
57c5f01b2fSopenharmony_ci    using binary_char_t = typename BasicJsonType::binary_t::value_type;
58c5f01b2fSopenharmony_ci    static constexpr std::uint8_t UTF8_ACCEPT = 0;
59c5f01b2fSopenharmony_ci    static constexpr std::uint8_t UTF8_REJECT = 1;
60c5f01b2fSopenharmony_ci
61c5f01b2fSopenharmony_ci  public:
62c5f01b2fSopenharmony_ci    /*!
63c5f01b2fSopenharmony_ci    @param[in] s  output stream to serialize to
64c5f01b2fSopenharmony_ci    @param[in] ichar  indentation character to use
65c5f01b2fSopenharmony_ci    @param[in] error_handler_  how to react on decoding errors
66c5f01b2fSopenharmony_ci    */
67c5f01b2fSopenharmony_ci    serializer(output_adapter_t<char> s, const char ichar,
68c5f01b2fSopenharmony_ci               error_handler_t error_handler_ = error_handler_t::strict)
69c5f01b2fSopenharmony_ci        : o(std::move(s))
70c5f01b2fSopenharmony_ci        , loc(std::localeconv())
71c5f01b2fSopenharmony_ci        , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
72c5f01b2fSopenharmony_ci        , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
73c5f01b2fSopenharmony_ci        , indent_char(ichar)
74c5f01b2fSopenharmony_ci        , indent_string(512, indent_char)
75c5f01b2fSopenharmony_ci        , error_handler(error_handler_)
76c5f01b2fSopenharmony_ci    {}
77c5f01b2fSopenharmony_ci
78c5f01b2fSopenharmony_ci    // delete because of pointer members
79c5f01b2fSopenharmony_ci    serializer(const serializer&) = delete;
80c5f01b2fSopenharmony_ci    serializer& operator=(const serializer&) = delete;
81c5f01b2fSopenharmony_ci    serializer(serializer&&) = delete;
82c5f01b2fSopenharmony_ci    serializer& operator=(serializer&&) = delete;
83c5f01b2fSopenharmony_ci    ~serializer() = default;
84c5f01b2fSopenharmony_ci
85c5f01b2fSopenharmony_ci    /*!
86c5f01b2fSopenharmony_ci    @brief internal implementation of the serialization function
87c5f01b2fSopenharmony_ci
88c5f01b2fSopenharmony_ci    This function is called by the public member function dump and organizes
89c5f01b2fSopenharmony_ci    the serialization internally. The indentation level is propagated as
90c5f01b2fSopenharmony_ci    additional parameter. In case of arrays and objects, the function is
91c5f01b2fSopenharmony_ci    called recursively.
92c5f01b2fSopenharmony_ci
93c5f01b2fSopenharmony_ci    - strings and object keys are escaped using `escape_string()`
94c5f01b2fSopenharmony_ci    - integer numbers are converted implicitly via `operator<<`
95c5f01b2fSopenharmony_ci    - floating-point numbers are converted to a string using `"%g"` format
96c5f01b2fSopenharmony_ci    - binary values are serialized as objects containing the subtype and the
97c5f01b2fSopenharmony_ci      byte array
98c5f01b2fSopenharmony_ci
99c5f01b2fSopenharmony_ci    @param[in] val               value to serialize
100c5f01b2fSopenharmony_ci    @param[in] pretty_print      whether the output shall be pretty-printed
101c5f01b2fSopenharmony_ci    @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
102c5f01b2fSopenharmony_ci    in the output are escaped with `\uXXXX` sequences, and the result consists
103c5f01b2fSopenharmony_ci    of ASCII characters only.
104c5f01b2fSopenharmony_ci    @param[in] indent_step       the indent level
105c5f01b2fSopenharmony_ci    @param[in] current_indent    the current indent level (only used internally)
106c5f01b2fSopenharmony_ci    */
107c5f01b2fSopenharmony_ci    void dump(const BasicJsonType& val,
108c5f01b2fSopenharmony_ci              const bool pretty_print,
109c5f01b2fSopenharmony_ci              const bool ensure_ascii,
110c5f01b2fSopenharmony_ci              const unsigned int indent_step,
111c5f01b2fSopenharmony_ci              const unsigned int current_indent = 0)
112c5f01b2fSopenharmony_ci    {
113c5f01b2fSopenharmony_ci        switch (val.m_type)
114c5f01b2fSopenharmony_ci        {
115c5f01b2fSopenharmony_ci            case value_t::object:
116c5f01b2fSopenharmony_ci            {
117c5f01b2fSopenharmony_ci                if (val.m_value.object->empty())
118c5f01b2fSopenharmony_ci                {
119c5f01b2fSopenharmony_ci                    o->write_characters("{}", 2);
120c5f01b2fSopenharmony_ci                    return;
121c5f01b2fSopenharmony_ci                }
122c5f01b2fSopenharmony_ci
123c5f01b2fSopenharmony_ci                if (pretty_print)
124c5f01b2fSopenharmony_ci                {
125c5f01b2fSopenharmony_ci                    o->write_characters("{\n", 2);
126c5f01b2fSopenharmony_ci
127c5f01b2fSopenharmony_ci                    // variable to hold indentation for recursive calls
128c5f01b2fSopenharmony_ci                    const auto new_indent = current_indent + indent_step;
129c5f01b2fSopenharmony_ci                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
130c5f01b2fSopenharmony_ci                    {
131c5f01b2fSopenharmony_ci                        indent_string.resize(indent_string.size() * 2, ' ');
132c5f01b2fSopenharmony_ci                    }
133c5f01b2fSopenharmony_ci
134c5f01b2fSopenharmony_ci                    // first n-1 elements
135c5f01b2fSopenharmony_ci                    auto i = val.m_value.object->cbegin();
136c5f01b2fSopenharmony_ci                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
137c5f01b2fSopenharmony_ci                    {
138c5f01b2fSopenharmony_ci                        o->write_characters(indent_string.c_str(), new_indent);
139c5f01b2fSopenharmony_ci                        o->write_character('\"');
140c5f01b2fSopenharmony_ci                        dump_escaped(i->first, ensure_ascii);
141c5f01b2fSopenharmony_ci                        o->write_characters("\": ", 3);
142c5f01b2fSopenharmony_ci                        dump(i->second, true, ensure_ascii, indent_step, new_indent);
143c5f01b2fSopenharmony_ci                        o->write_characters(",\n", 2);
144c5f01b2fSopenharmony_ci                    }
145c5f01b2fSopenharmony_ci
146c5f01b2fSopenharmony_ci                    // last element
147c5f01b2fSopenharmony_ci                    JSON_ASSERT(i != val.m_value.object->cend());
148c5f01b2fSopenharmony_ci                    JSON_ASSERT(std::next(i) == val.m_value.object->cend());
149c5f01b2fSopenharmony_ci                    o->write_characters(indent_string.c_str(), new_indent);
150c5f01b2fSopenharmony_ci                    o->write_character('\"');
151c5f01b2fSopenharmony_ci                    dump_escaped(i->first, ensure_ascii);
152c5f01b2fSopenharmony_ci                    o->write_characters("\": ", 3);
153c5f01b2fSopenharmony_ci                    dump(i->second, true, ensure_ascii, indent_step, new_indent);
154c5f01b2fSopenharmony_ci
155c5f01b2fSopenharmony_ci                    o->write_character('\n');
156c5f01b2fSopenharmony_ci                    o->write_characters(indent_string.c_str(), current_indent);
157c5f01b2fSopenharmony_ci                    o->write_character('}');
158c5f01b2fSopenharmony_ci                }
159c5f01b2fSopenharmony_ci                else
160c5f01b2fSopenharmony_ci                {
161c5f01b2fSopenharmony_ci                    o->write_character('{');
162c5f01b2fSopenharmony_ci
163c5f01b2fSopenharmony_ci                    // first n-1 elements
164c5f01b2fSopenharmony_ci                    auto i = val.m_value.object->cbegin();
165c5f01b2fSopenharmony_ci                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
166c5f01b2fSopenharmony_ci                    {
167c5f01b2fSopenharmony_ci                        o->write_character('\"');
168c5f01b2fSopenharmony_ci                        dump_escaped(i->first, ensure_ascii);
169c5f01b2fSopenharmony_ci                        o->write_characters("\":", 2);
170c5f01b2fSopenharmony_ci                        dump(i->second, false, ensure_ascii, indent_step, current_indent);
171c5f01b2fSopenharmony_ci                        o->write_character(',');
172c5f01b2fSopenharmony_ci                    }
173c5f01b2fSopenharmony_ci
174c5f01b2fSopenharmony_ci                    // last element
175c5f01b2fSopenharmony_ci                    JSON_ASSERT(i != val.m_value.object->cend());
176c5f01b2fSopenharmony_ci                    JSON_ASSERT(std::next(i) == val.m_value.object->cend());
177c5f01b2fSopenharmony_ci                    o->write_character('\"');
178c5f01b2fSopenharmony_ci                    dump_escaped(i->first, ensure_ascii);
179c5f01b2fSopenharmony_ci                    o->write_characters("\":", 2);
180c5f01b2fSopenharmony_ci                    dump(i->second, false, ensure_ascii, indent_step, current_indent);
181c5f01b2fSopenharmony_ci
182c5f01b2fSopenharmony_ci                    o->write_character('}');
183c5f01b2fSopenharmony_ci                }
184c5f01b2fSopenharmony_ci
185c5f01b2fSopenharmony_ci                return;
186c5f01b2fSopenharmony_ci            }
187c5f01b2fSopenharmony_ci
188c5f01b2fSopenharmony_ci            case value_t::array:
189c5f01b2fSopenharmony_ci            {
190c5f01b2fSopenharmony_ci                if (val.m_value.array->empty())
191c5f01b2fSopenharmony_ci                {
192c5f01b2fSopenharmony_ci                    o->write_characters("[]", 2);
193c5f01b2fSopenharmony_ci                    return;
194c5f01b2fSopenharmony_ci                }
195c5f01b2fSopenharmony_ci
196c5f01b2fSopenharmony_ci                if (pretty_print)
197c5f01b2fSopenharmony_ci                {
198c5f01b2fSopenharmony_ci                    o->write_characters("[\n", 2);
199c5f01b2fSopenharmony_ci
200c5f01b2fSopenharmony_ci                    // variable to hold indentation for recursive calls
201c5f01b2fSopenharmony_ci                    const auto new_indent = current_indent + indent_step;
202c5f01b2fSopenharmony_ci                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
203c5f01b2fSopenharmony_ci                    {
204c5f01b2fSopenharmony_ci                        indent_string.resize(indent_string.size() * 2, ' ');
205c5f01b2fSopenharmony_ci                    }
206c5f01b2fSopenharmony_ci
207c5f01b2fSopenharmony_ci                    // first n-1 elements
208c5f01b2fSopenharmony_ci                    for (auto i = val.m_value.array->cbegin();
209c5f01b2fSopenharmony_ci                            i != val.m_value.array->cend() - 1; ++i)
210c5f01b2fSopenharmony_ci                    {
211c5f01b2fSopenharmony_ci                        o->write_characters(indent_string.c_str(), new_indent);
212c5f01b2fSopenharmony_ci                        dump(*i, true, ensure_ascii, indent_step, new_indent);
213c5f01b2fSopenharmony_ci                        o->write_characters(",\n", 2);
214c5f01b2fSopenharmony_ci                    }
215c5f01b2fSopenharmony_ci
216c5f01b2fSopenharmony_ci                    // last element
217c5f01b2fSopenharmony_ci                    JSON_ASSERT(!val.m_value.array->empty());
218c5f01b2fSopenharmony_ci                    o->write_characters(indent_string.c_str(), new_indent);
219c5f01b2fSopenharmony_ci                    dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
220c5f01b2fSopenharmony_ci
221c5f01b2fSopenharmony_ci                    o->write_character('\n');
222c5f01b2fSopenharmony_ci                    o->write_characters(indent_string.c_str(), current_indent);
223c5f01b2fSopenharmony_ci                    o->write_character(']');
224c5f01b2fSopenharmony_ci                }
225c5f01b2fSopenharmony_ci                else
226c5f01b2fSopenharmony_ci                {
227c5f01b2fSopenharmony_ci                    o->write_character('[');
228c5f01b2fSopenharmony_ci
229c5f01b2fSopenharmony_ci                    // first n-1 elements
230c5f01b2fSopenharmony_ci                    for (auto i = val.m_value.array->cbegin();
231c5f01b2fSopenharmony_ci                            i != val.m_value.array->cend() - 1; ++i)
232c5f01b2fSopenharmony_ci                    {
233c5f01b2fSopenharmony_ci                        dump(*i, false, ensure_ascii, indent_step, current_indent);
234c5f01b2fSopenharmony_ci                        o->write_character(',');
235c5f01b2fSopenharmony_ci                    }
236c5f01b2fSopenharmony_ci
237c5f01b2fSopenharmony_ci                    // last element
238c5f01b2fSopenharmony_ci                    JSON_ASSERT(!val.m_value.array->empty());
239c5f01b2fSopenharmony_ci                    dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
240c5f01b2fSopenharmony_ci
241c5f01b2fSopenharmony_ci                    o->write_character(']');
242c5f01b2fSopenharmony_ci                }
243c5f01b2fSopenharmony_ci
244c5f01b2fSopenharmony_ci                return;
245c5f01b2fSopenharmony_ci            }
246c5f01b2fSopenharmony_ci
247c5f01b2fSopenharmony_ci            case value_t::string:
248c5f01b2fSopenharmony_ci            {
249c5f01b2fSopenharmony_ci                o->write_character('\"');
250c5f01b2fSopenharmony_ci                dump_escaped(*val.m_value.string, ensure_ascii);
251c5f01b2fSopenharmony_ci                o->write_character('\"');
252c5f01b2fSopenharmony_ci                return;
253c5f01b2fSopenharmony_ci            }
254c5f01b2fSopenharmony_ci
255c5f01b2fSopenharmony_ci            case value_t::binary:
256c5f01b2fSopenharmony_ci            {
257c5f01b2fSopenharmony_ci                if (pretty_print)
258c5f01b2fSopenharmony_ci                {
259c5f01b2fSopenharmony_ci                    o->write_characters("{\n", 2);
260c5f01b2fSopenharmony_ci
261c5f01b2fSopenharmony_ci                    // variable to hold indentation for recursive calls
262c5f01b2fSopenharmony_ci                    const auto new_indent = current_indent + indent_step;
263c5f01b2fSopenharmony_ci                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
264c5f01b2fSopenharmony_ci                    {
265c5f01b2fSopenharmony_ci                        indent_string.resize(indent_string.size() * 2, ' ');
266c5f01b2fSopenharmony_ci                    }
267c5f01b2fSopenharmony_ci
268c5f01b2fSopenharmony_ci                    o->write_characters(indent_string.c_str(), new_indent);
269c5f01b2fSopenharmony_ci
270c5f01b2fSopenharmony_ci                    o->write_characters("\"bytes\": [", 10);
271c5f01b2fSopenharmony_ci
272c5f01b2fSopenharmony_ci                    if (!val.m_value.binary->empty())
273c5f01b2fSopenharmony_ci                    {
274c5f01b2fSopenharmony_ci                        for (auto i = val.m_value.binary->cbegin();
275c5f01b2fSopenharmony_ci                                i != val.m_value.binary->cend() - 1; ++i)
276c5f01b2fSopenharmony_ci                        {
277c5f01b2fSopenharmony_ci                            dump_integer(*i);
278c5f01b2fSopenharmony_ci                            o->write_characters(", ", 2);
279c5f01b2fSopenharmony_ci                        }
280c5f01b2fSopenharmony_ci                        dump_integer(val.m_value.binary->back());
281c5f01b2fSopenharmony_ci                    }
282c5f01b2fSopenharmony_ci
283c5f01b2fSopenharmony_ci                    o->write_characters("],\n", 3);
284c5f01b2fSopenharmony_ci                    o->write_characters(indent_string.c_str(), new_indent);
285c5f01b2fSopenharmony_ci
286c5f01b2fSopenharmony_ci                    o->write_characters("\"subtype\": ", 11);
287c5f01b2fSopenharmony_ci                    if (val.m_value.binary->has_subtype())
288c5f01b2fSopenharmony_ci                    {
289c5f01b2fSopenharmony_ci                        dump_integer(val.m_value.binary->subtype());
290c5f01b2fSopenharmony_ci                    }
291c5f01b2fSopenharmony_ci                    else
292c5f01b2fSopenharmony_ci                    {
293c5f01b2fSopenharmony_ci                        o->write_characters("null", 4);
294c5f01b2fSopenharmony_ci                    }
295c5f01b2fSopenharmony_ci                    o->write_character('\n');
296c5f01b2fSopenharmony_ci                    o->write_characters(indent_string.c_str(), current_indent);
297c5f01b2fSopenharmony_ci                    o->write_character('}');
298c5f01b2fSopenharmony_ci                }
299c5f01b2fSopenharmony_ci                else
300c5f01b2fSopenharmony_ci                {
301c5f01b2fSopenharmony_ci                    o->write_characters("{\"bytes\":[", 10);
302c5f01b2fSopenharmony_ci
303c5f01b2fSopenharmony_ci                    if (!val.m_value.binary->empty())
304c5f01b2fSopenharmony_ci                    {
305c5f01b2fSopenharmony_ci                        for (auto i = val.m_value.binary->cbegin();
306c5f01b2fSopenharmony_ci                                i != val.m_value.binary->cend() - 1; ++i)
307c5f01b2fSopenharmony_ci                        {
308c5f01b2fSopenharmony_ci                            dump_integer(*i);
309c5f01b2fSopenharmony_ci                            o->write_character(',');
310c5f01b2fSopenharmony_ci                        }
311c5f01b2fSopenharmony_ci                        dump_integer(val.m_value.binary->back());
312c5f01b2fSopenharmony_ci                    }
313c5f01b2fSopenharmony_ci
314c5f01b2fSopenharmony_ci                    o->write_characters("],\"subtype\":", 12);
315c5f01b2fSopenharmony_ci                    if (val.m_value.binary->has_subtype())
316c5f01b2fSopenharmony_ci                    {
317c5f01b2fSopenharmony_ci                        dump_integer(val.m_value.binary->subtype());
318c5f01b2fSopenharmony_ci                        o->write_character('}');
319c5f01b2fSopenharmony_ci                    }
320c5f01b2fSopenharmony_ci                    else
321c5f01b2fSopenharmony_ci                    {
322c5f01b2fSopenharmony_ci                        o->write_characters("null}", 5);
323c5f01b2fSopenharmony_ci                    }
324c5f01b2fSopenharmony_ci                }
325c5f01b2fSopenharmony_ci                return;
326c5f01b2fSopenharmony_ci            }
327c5f01b2fSopenharmony_ci
328c5f01b2fSopenharmony_ci            case value_t::boolean:
329c5f01b2fSopenharmony_ci            {
330c5f01b2fSopenharmony_ci                if (val.m_value.boolean)
331c5f01b2fSopenharmony_ci                {
332c5f01b2fSopenharmony_ci                    o->write_characters("true", 4);
333c5f01b2fSopenharmony_ci                }
334c5f01b2fSopenharmony_ci                else
335c5f01b2fSopenharmony_ci                {
336c5f01b2fSopenharmony_ci                    o->write_characters("false", 5);
337c5f01b2fSopenharmony_ci                }
338c5f01b2fSopenharmony_ci                return;
339c5f01b2fSopenharmony_ci            }
340c5f01b2fSopenharmony_ci
341c5f01b2fSopenharmony_ci            case value_t::number_integer:
342c5f01b2fSopenharmony_ci            {
343c5f01b2fSopenharmony_ci                dump_integer(val.m_value.number_integer);
344c5f01b2fSopenharmony_ci                return;
345c5f01b2fSopenharmony_ci            }
346c5f01b2fSopenharmony_ci
347c5f01b2fSopenharmony_ci            case value_t::number_unsigned:
348c5f01b2fSopenharmony_ci            {
349c5f01b2fSopenharmony_ci                dump_integer(val.m_value.number_unsigned);
350c5f01b2fSopenharmony_ci                return;
351c5f01b2fSopenharmony_ci            }
352c5f01b2fSopenharmony_ci
353c5f01b2fSopenharmony_ci            case value_t::number_float:
354c5f01b2fSopenharmony_ci            {
355c5f01b2fSopenharmony_ci                dump_float(val.m_value.number_float);
356c5f01b2fSopenharmony_ci                return;
357c5f01b2fSopenharmony_ci            }
358c5f01b2fSopenharmony_ci
359c5f01b2fSopenharmony_ci            case value_t::discarded:
360c5f01b2fSopenharmony_ci            {
361c5f01b2fSopenharmony_ci                o->write_characters("<discarded>", 11);
362c5f01b2fSopenharmony_ci                return;
363c5f01b2fSopenharmony_ci            }
364c5f01b2fSopenharmony_ci
365c5f01b2fSopenharmony_ci            case value_t::null:
366c5f01b2fSopenharmony_ci            {
367c5f01b2fSopenharmony_ci                o->write_characters("null", 4);
368c5f01b2fSopenharmony_ci                return;
369c5f01b2fSopenharmony_ci            }
370c5f01b2fSopenharmony_ci
371c5f01b2fSopenharmony_ci            default:            // LCOV_EXCL_LINE
372c5f01b2fSopenharmony_ci                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
373c5f01b2fSopenharmony_ci        }
374c5f01b2fSopenharmony_ci    }
375c5f01b2fSopenharmony_ci
376c5f01b2fSopenharmony_ci  JSON_PRIVATE_UNLESS_TESTED:
377c5f01b2fSopenharmony_ci    /*!
378c5f01b2fSopenharmony_ci    @brief dump escaped string
379c5f01b2fSopenharmony_ci
380c5f01b2fSopenharmony_ci    Escape a string by replacing certain special characters by a sequence of an
381c5f01b2fSopenharmony_ci    escape character (backslash) and another character and other control
382c5f01b2fSopenharmony_ci    characters by a sequence of "\u" followed by a four-digit hex
383c5f01b2fSopenharmony_ci    representation. The escaped string is written to output stream @a o.
384c5f01b2fSopenharmony_ci
385c5f01b2fSopenharmony_ci    @param[in] s  the string to escape
386c5f01b2fSopenharmony_ci    @param[in] ensure_ascii  whether to escape non-ASCII characters with
387c5f01b2fSopenharmony_ci                             \uXXXX sequences
388c5f01b2fSopenharmony_ci
389c5f01b2fSopenharmony_ci    @complexity Linear in the length of string @a s.
390c5f01b2fSopenharmony_ci    */
391c5f01b2fSopenharmony_ci    void dump_escaped(const string_t& s, const bool ensure_ascii)
392c5f01b2fSopenharmony_ci    {
393c5f01b2fSopenharmony_ci        std::uint32_t codepoint{};
394c5f01b2fSopenharmony_ci        std::uint8_t state = UTF8_ACCEPT;
395c5f01b2fSopenharmony_ci        std::size_t bytes = 0;  // number of bytes written to string_buffer
396c5f01b2fSopenharmony_ci
397c5f01b2fSopenharmony_ci        // number of bytes written at the point of the last valid byte
398c5f01b2fSopenharmony_ci        std::size_t bytes_after_last_accept = 0;
399c5f01b2fSopenharmony_ci        std::size_t undumped_chars = 0;
400c5f01b2fSopenharmony_ci
401c5f01b2fSopenharmony_ci        for (std::size_t i = 0; i < s.size(); ++i)
402c5f01b2fSopenharmony_ci        {
403c5f01b2fSopenharmony_ci            const auto byte = static_cast<std::uint8_t>(s[i]);
404c5f01b2fSopenharmony_ci
405c5f01b2fSopenharmony_ci            switch (decode(state, codepoint, byte))
406c5f01b2fSopenharmony_ci            {
407c5f01b2fSopenharmony_ci                case UTF8_ACCEPT:  // decode found a new code point
408c5f01b2fSopenharmony_ci                {
409c5f01b2fSopenharmony_ci                    switch (codepoint)
410c5f01b2fSopenharmony_ci                    {
411c5f01b2fSopenharmony_ci                        case 0x08: // backspace
412c5f01b2fSopenharmony_ci                        {
413c5f01b2fSopenharmony_ci                            string_buffer[bytes++] = '\\';
414c5f01b2fSopenharmony_ci                            string_buffer[bytes++] = 'b';
415c5f01b2fSopenharmony_ci                            break;
416c5f01b2fSopenharmony_ci                        }
417c5f01b2fSopenharmony_ci
418c5f01b2fSopenharmony_ci                        case 0x09: // horizontal tab
419c5f01b2fSopenharmony_ci                        {
420c5f01b2fSopenharmony_ci                            string_buffer[bytes++] = '\\';
421c5f01b2fSopenharmony_ci                            string_buffer[bytes++] = 't';
422c5f01b2fSopenharmony_ci                            break;
423c5f01b2fSopenharmony_ci                        }
424c5f01b2fSopenharmony_ci
425c5f01b2fSopenharmony_ci                        case 0x0A: // newline
426c5f01b2fSopenharmony_ci                        {
427c5f01b2fSopenharmony_ci                            string_buffer[bytes++] = '\\';
428c5f01b2fSopenharmony_ci                            string_buffer[bytes++] = 'n';
429c5f01b2fSopenharmony_ci                            break;
430c5f01b2fSopenharmony_ci                        }
431c5f01b2fSopenharmony_ci
432c5f01b2fSopenharmony_ci                        case 0x0C: // formfeed
433c5f01b2fSopenharmony_ci                        {
434c5f01b2fSopenharmony_ci                            string_buffer[bytes++] = '\\';
435c5f01b2fSopenharmony_ci                            string_buffer[bytes++] = 'f';
436c5f01b2fSopenharmony_ci                            break;
437c5f01b2fSopenharmony_ci                        }
438c5f01b2fSopenharmony_ci
439c5f01b2fSopenharmony_ci                        case 0x0D: // carriage return
440c5f01b2fSopenharmony_ci                        {
441c5f01b2fSopenharmony_ci                            string_buffer[bytes++] = '\\';
442c5f01b2fSopenharmony_ci                            string_buffer[bytes++] = 'r';
443c5f01b2fSopenharmony_ci                            break;
444c5f01b2fSopenharmony_ci                        }
445c5f01b2fSopenharmony_ci
446c5f01b2fSopenharmony_ci                        case 0x22: // quotation mark
447c5f01b2fSopenharmony_ci                        {
448c5f01b2fSopenharmony_ci                            string_buffer[bytes++] = '\\';
449c5f01b2fSopenharmony_ci                            string_buffer[bytes++] = '\"';
450c5f01b2fSopenharmony_ci                            break;
451c5f01b2fSopenharmony_ci                        }
452c5f01b2fSopenharmony_ci
453c5f01b2fSopenharmony_ci                        case 0x5C: // reverse solidus
454c5f01b2fSopenharmony_ci                        {
455c5f01b2fSopenharmony_ci                            string_buffer[bytes++] = '\\';
456c5f01b2fSopenharmony_ci                            string_buffer[bytes++] = '\\';
457c5f01b2fSopenharmony_ci                            break;
458c5f01b2fSopenharmony_ci                        }
459c5f01b2fSopenharmony_ci
460c5f01b2fSopenharmony_ci                        default:
461c5f01b2fSopenharmony_ci                        {
462c5f01b2fSopenharmony_ci                            // escape control characters (0x00..0x1F) or, if
463c5f01b2fSopenharmony_ci                            // ensure_ascii parameter is used, non-ASCII characters
464c5f01b2fSopenharmony_ci                            if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
465c5f01b2fSopenharmony_ci                            {
466c5f01b2fSopenharmony_ci                                if (codepoint <= 0xFFFF)
467c5f01b2fSopenharmony_ci                                {
468c5f01b2fSopenharmony_ci                                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
469c5f01b2fSopenharmony_ci                                    static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
470c5f01b2fSopenharmony_ci                                                                      static_cast<std::uint16_t>(codepoint)));
471c5f01b2fSopenharmony_ci                                    bytes += 6;
472c5f01b2fSopenharmony_ci                                }
473c5f01b2fSopenharmony_ci                                else
474c5f01b2fSopenharmony_ci                                {
475c5f01b2fSopenharmony_ci                                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
476c5f01b2fSopenharmony_ci                                    static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
477c5f01b2fSopenharmony_ci                                                                      static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
478c5f01b2fSopenharmony_ci                                                                      static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
479c5f01b2fSopenharmony_ci                                    bytes += 12;
480c5f01b2fSopenharmony_ci                                }
481c5f01b2fSopenharmony_ci                            }
482c5f01b2fSopenharmony_ci                            else
483c5f01b2fSopenharmony_ci                            {
484c5f01b2fSopenharmony_ci                                // copy byte to buffer (all previous bytes
485c5f01b2fSopenharmony_ci                                // been copied have in default case above)
486c5f01b2fSopenharmony_ci                                string_buffer[bytes++] = s[i];
487c5f01b2fSopenharmony_ci                            }
488c5f01b2fSopenharmony_ci                            break;
489c5f01b2fSopenharmony_ci                        }
490c5f01b2fSopenharmony_ci                    }
491c5f01b2fSopenharmony_ci
492c5f01b2fSopenharmony_ci                    // write buffer and reset index; there must be 13 bytes
493c5f01b2fSopenharmony_ci                    // left, as this is the maximal number of bytes to be
494c5f01b2fSopenharmony_ci                    // written ("\uxxxx\uxxxx\0") for one code point
495c5f01b2fSopenharmony_ci                    if (string_buffer.size() - bytes < 13)
496c5f01b2fSopenharmony_ci                    {
497c5f01b2fSopenharmony_ci                        o->write_characters(string_buffer.data(), bytes);
498c5f01b2fSopenharmony_ci                        bytes = 0;
499c5f01b2fSopenharmony_ci                    }
500c5f01b2fSopenharmony_ci
501c5f01b2fSopenharmony_ci                    // remember the byte position of this accept
502c5f01b2fSopenharmony_ci                    bytes_after_last_accept = bytes;
503c5f01b2fSopenharmony_ci                    undumped_chars = 0;
504c5f01b2fSopenharmony_ci                    break;
505c5f01b2fSopenharmony_ci                }
506c5f01b2fSopenharmony_ci
507c5f01b2fSopenharmony_ci                case UTF8_REJECT:  // decode found invalid UTF-8 byte
508c5f01b2fSopenharmony_ci                {
509c5f01b2fSopenharmony_ci                    switch (error_handler)
510c5f01b2fSopenharmony_ci                    {
511c5f01b2fSopenharmony_ci                        case error_handler_t::strict:
512c5f01b2fSopenharmony_ci                        {
513c5f01b2fSopenharmony_ci                            JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
514c5f01b2fSopenharmony_ci                        }
515c5f01b2fSopenharmony_ci
516c5f01b2fSopenharmony_ci                        case error_handler_t::ignore:
517c5f01b2fSopenharmony_ci                        case error_handler_t::replace:
518c5f01b2fSopenharmony_ci                        {
519c5f01b2fSopenharmony_ci                            // in case we saw this character the first time, we
520c5f01b2fSopenharmony_ci                            // would like to read it again, because the byte
521c5f01b2fSopenharmony_ci                            // may be OK for itself, but just not OK for the
522c5f01b2fSopenharmony_ci                            // previous sequence
523c5f01b2fSopenharmony_ci                            if (undumped_chars > 0)
524c5f01b2fSopenharmony_ci                            {
525c5f01b2fSopenharmony_ci                                --i;
526c5f01b2fSopenharmony_ci                            }
527c5f01b2fSopenharmony_ci
528c5f01b2fSopenharmony_ci                            // reset length buffer to the last accepted index;
529c5f01b2fSopenharmony_ci                            // thus removing/ignoring the invalid characters
530c5f01b2fSopenharmony_ci                            bytes = bytes_after_last_accept;
531c5f01b2fSopenharmony_ci
532c5f01b2fSopenharmony_ci                            if (error_handler == error_handler_t::replace)
533c5f01b2fSopenharmony_ci                            {
534c5f01b2fSopenharmony_ci                                // add a replacement character
535c5f01b2fSopenharmony_ci                                if (ensure_ascii)
536c5f01b2fSopenharmony_ci                                {
537c5f01b2fSopenharmony_ci                                    string_buffer[bytes++] = '\\';
538c5f01b2fSopenharmony_ci                                    string_buffer[bytes++] = 'u';
539c5f01b2fSopenharmony_ci                                    string_buffer[bytes++] = 'f';
540c5f01b2fSopenharmony_ci                                    string_buffer[bytes++] = 'f';
541c5f01b2fSopenharmony_ci                                    string_buffer[bytes++] = 'f';
542c5f01b2fSopenharmony_ci                                    string_buffer[bytes++] = 'd';
543c5f01b2fSopenharmony_ci                                }
544c5f01b2fSopenharmony_ci                                else
545c5f01b2fSopenharmony_ci                                {
546c5f01b2fSopenharmony_ci                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
547c5f01b2fSopenharmony_ci                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
548c5f01b2fSopenharmony_ci                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
549c5f01b2fSopenharmony_ci                                }
550c5f01b2fSopenharmony_ci
551c5f01b2fSopenharmony_ci                                // write buffer and reset index; there must be 13 bytes
552c5f01b2fSopenharmony_ci                                // left, as this is the maximal number of bytes to be
553c5f01b2fSopenharmony_ci                                // written ("\uxxxx\uxxxx\0") for one code point
554c5f01b2fSopenharmony_ci                                if (string_buffer.size() - bytes < 13)
555c5f01b2fSopenharmony_ci                                {
556c5f01b2fSopenharmony_ci                                    o->write_characters(string_buffer.data(), bytes);
557c5f01b2fSopenharmony_ci                                    bytes = 0;
558c5f01b2fSopenharmony_ci                                }
559c5f01b2fSopenharmony_ci
560c5f01b2fSopenharmony_ci                                bytes_after_last_accept = bytes;
561c5f01b2fSopenharmony_ci                            }
562c5f01b2fSopenharmony_ci
563c5f01b2fSopenharmony_ci                            undumped_chars = 0;
564c5f01b2fSopenharmony_ci
565c5f01b2fSopenharmony_ci                            // continue processing the string
566c5f01b2fSopenharmony_ci                            state = UTF8_ACCEPT;
567c5f01b2fSopenharmony_ci                            break;
568c5f01b2fSopenharmony_ci                        }
569c5f01b2fSopenharmony_ci
570c5f01b2fSopenharmony_ci                        default:            // LCOV_EXCL_LINE
571c5f01b2fSopenharmony_ci                            JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
572c5f01b2fSopenharmony_ci                    }
573c5f01b2fSopenharmony_ci                    break;
574c5f01b2fSopenharmony_ci                }
575c5f01b2fSopenharmony_ci
576c5f01b2fSopenharmony_ci                default:  // decode found yet incomplete multi-byte code point
577c5f01b2fSopenharmony_ci                {
578c5f01b2fSopenharmony_ci                    if (!ensure_ascii)
579c5f01b2fSopenharmony_ci                    {
580c5f01b2fSopenharmony_ci                        // code point will not be escaped - copy byte to buffer
581c5f01b2fSopenharmony_ci                        string_buffer[bytes++] = s[i];
582c5f01b2fSopenharmony_ci                    }
583c5f01b2fSopenharmony_ci                    ++undumped_chars;
584c5f01b2fSopenharmony_ci                    break;
585c5f01b2fSopenharmony_ci                }
586c5f01b2fSopenharmony_ci            }
587c5f01b2fSopenharmony_ci        }
588c5f01b2fSopenharmony_ci
589c5f01b2fSopenharmony_ci        // we finished processing the string
590c5f01b2fSopenharmony_ci        if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
591c5f01b2fSopenharmony_ci        {
592c5f01b2fSopenharmony_ci            // write buffer
593c5f01b2fSopenharmony_ci            if (bytes > 0)
594c5f01b2fSopenharmony_ci            {
595c5f01b2fSopenharmony_ci                o->write_characters(string_buffer.data(), bytes);
596c5f01b2fSopenharmony_ci            }
597c5f01b2fSopenharmony_ci        }
598c5f01b2fSopenharmony_ci        else
599c5f01b2fSopenharmony_ci        {
600c5f01b2fSopenharmony_ci            // we finish reading, but do not accept: string was incomplete
601c5f01b2fSopenharmony_ci            switch (error_handler)
602c5f01b2fSopenharmony_ci            {
603c5f01b2fSopenharmony_ci                case error_handler_t::strict:
604c5f01b2fSopenharmony_ci                {
605c5f01b2fSopenharmony_ci                    JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
606c5f01b2fSopenharmony_ci                }
607c5f01b2fSopenharmony_ci
608c5f01b2fSopenharmony_ci                case error_handler_t::ignore:
609c5f01b2fSopenharmony_ci                {
610c5f01b2fSopenharmony_ci                    // write all accepted bytes
611c5f01b2fSopenharmony_ci                    o->write_characters(string_buffer.data(), bytes_after_last_accept);
612c5f01b2fSopenharmony_ci                    break;
613c5f01b2fSopenharmony_ci                }
614c5f01b2fSopenharmony_ci
615c5f01b2fSopenharmony_ci                case error_handler_t::replace:
616c5f01b2fSopenharmony_ci                {
617c5f01b2fSopenharmony_ci                    // write all accepted bytes
618c5f01b2fSopenharmony_ci                    o->write_characters(string_buffer.data(), bytes_after_last_accept);
619c5f01b2fSopenharmony_ci                    // add a replacement character
620c5f01b2fSopenharmony_ci                    if (ensure_ascii)
621c5f01b2fSopenharmony_ci                    {
622c5f01b2fSopenharmony_ci                        o->write_characters("\\ufffd", 6);
623c5f01b2fSopenharmony_ci                    }
624c5f01b2fSopenharmony_ci                    else
625c5f01b2fSopenharmony_ci                    {
626c5f01b2fSopenharmony_ci                        o->write_characters("\xEF\xBF\xBD", 3);
627c5f01b2fSopenharmony_ci                    }
628c5f01b2fSopenharmony_ci                    break;
629c5f01b2fSopenharmony_ci                }
630c5f01b2fSopenharmony_ci
631c5f01b2fSopenharmony_ci                default:            // LCOV_EXCL_LINE
632c5f01b2fSopenharmony_ci                    JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
633c5f01b2fSopenharmony_ci            }
634c5f01b2fSopenharmony_ci        }
635c5f01b2fSopenharmony_ci    }
636c5f01b2fSopenharmony_ci
637c5f01b2fSopenharmony_ci  private:
638c5f01b2fSopenharmony_ci    /*!
639c5f01b2fSopenharmony_ci    @brief count digits
640c5f01b2fSopenharmony_ci
641c5f01b2fSopenharmony_ci    Count the number of decimal (base 10) digits for an input unsigned integer.
642c5f01b2fSopenharmony_ci
643c5f01b2fSopenharmony_ci    @param[in] x  unsigned integer number to count its digits
644c5f01b2fSopenharmony_ci    @return    number of decimal digits
645c5f01b2fSopenharmony_ci    */
646c5f01b2fSopenharmony_ci    inline unsigned int count_digits(number_unsigned_t x) noexcept
647c5f01b2fSopenharmony_ci    {
648c5f01b2fSopenharmony_ci        unsigned int n_digits = 1;
649c5f01b2fSopenharmony_ci        for (;;)
650c5f01b2fSopenharmony_ci        {
651c5f01b2fSopenharmony_ci            if (x < 10)
652c5f01b2fSopenharmony_ci            {
653c5f01b2fSopenharmony_ci                return n_digits;
654c5f01b2fSopenharmony_ci            }
655c5f01b2fSopenharmony_ci            if (x < 100)
656c5f01b2fSopenharmony_ci            {
657c5f01b2fSopenharmony_ci                return n_digits + 1;
658c5f01b2fSopenharmony_ci            }
659c5f01b2fSopenharmony_ci            if (x < 1000)
660c5f01b2fSopenharmony_ci            {
661c5f01b2fSopenharmony_ci                return n_digits + 2;
662c5f01b2fSopenharmony_ci            }
663c5f01b2fSopenharmony_ci            if (x < 10000)
664c5f01b2fSopenharmony_ci            {
665c5f01b2fSopenharmony_ci                return n_digits + 3;
666c5f01b2fSopenharmony_ci            }
667c5f01b2fSopenharmony_ci            x = x / 10000u;
668c5f01b2fSopenharmony_ci            n_digits += 4;
669c5f01b2fSopenharmony_ci        }
670c5f01b2fSopenharmony_ci    }
671c5f01b2fSopenharmony_ci
672c5f01b2fSopenharmony_ci    /*!
673c5f01b2fSopenharmony_ci     * @brief convert a byte to a uppercase hex representation
674c5f01b2fSopenharmony_ci     * @param[in] byte byte to represent
675c5f01b2fSopenharmony_ci     * @return representation ("00".."FF")
676c5f01b2fSopenharmony_ci     */
677c5f01b2fSopenharmony_ci    static std::string hex_bytes(std::uint8_t byte)
678c5f01b2fSopenharmony_ci    {
679c5f01b2fSopenharmony_ci        std::string result = "FF";
680c5f01b2fSopenharmony_ci        constexpr const char* nibble_to_hex = "0123456789ABCDEF";
681c5f01b2fSopenharmony_ci        result[0] = nibble_to_hex[byte / 16];
682c5f01b2fSopenharmony_ci        result[1] = nibble_to_hex[byte % 16];
683c5f01b2fSopenharmony_ci        return result;
684c5f01b2fSopenharmony_ci    }
685c5f01b2fSopenharmony_ci
686c5f01b2fSopenharmony_ci    // templates to avoid warnings about useless casts
687c5f01b2fSopenharmony_ci    template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
688c5f01b2fSopenharmony_ci    bool is_negative_number(NumberType x)
689c5f01b2fSopenharmony_ci    {
690c5f01b2fSopenharmony_ci        return x < 0;
691c5f01b2fSopenharmony_ci    }
692c5f01b2fSopenharmony_ci
693c5f01b2fSopenharmony_ci    template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
694c5f01b2fSopenharmony_ci    bool is_negative_number(NumberType /*unused*/)
695c5f01b2fSopenharmony_ci    {
696c5f01b2fSopenharmony_ci        return false;
697c5f01b2fSopenharmony_ci    }
698c5f01b2fSopenharmony_ci
699c5f01b2fSopenharmony_ci    /*!
700c5f01b2fSopenharmony_ci    @brief dump an integer
701c5f01b2fSopenharmony_ci
702c5f01b2fSopenharmony_ci    Dump a given integer to output stream @a o. Works internally with
703c5f01b2fSopenharmony_ci    @a number_buffer.
704c5f01b2fSopenharmony_ci
705c5f01b2fSopenharmony_ci    @param[in] x  integer number (signed or unsigned) to dump
706c5f01b2fSopenharmony_ci    @tparam NumberType either @a number_integer_t or @a number_unsigned_t
707c5f01b2fSopenharmony_ci    */
708c5f01b2fSopenharmony_ci    template < typename NumberType, detail::enable_if_t <
709c5f01b2fSopenharmony_ci                   std::is_integral<NumberType>::value ||
710c5f01b2fSopenharmony_ci                   std::is_same<NumberType, number_unsigned_t>::value ||
711c5f01b2fSopenharmony_ci                   std::is_same<NumberType, number_integer_t>::value ||
712c5f01b2fSopenharmony_ci                   std::is_same<NumberType, binary_char_t>::value,
713c5f01b2fSopenharmony_ci                   int > = 0 >
714c5f01b2fSopenharmony_ci    void dump_integer(NumberType x)
715c5f01b2fSopenharmony_ci    {
716c5f01b2fSopenharmony_ci        static constexpr std::array<std::array<char, 2>, 100> digits_to_99
717c5f01b2fSopenharmony_ci        {
718c5f01b2fSopenharmony_ci            {
719c5f01b2fSopenharmony_ci                {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
720c5f01b2fSopenharmony_ci                {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
721c5f01b2fSopenharmony_ci                {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
722c5f01b2fSopenharmony_ci                {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
723c5f01b2fSopenharmony_ci                {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
724c5f01b2fSopenharmony_ci                {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
725c5f01b2fSopenharmony_ci                {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
726c5f01b2fSopenharmony_ci                {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
727c5f01b2fSopenharmony_ci                {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
728c5f01b2fSopenharmony_ci                {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
729c5f01b2fSopenharmony_ci            }
730c5f01b2fSopenharmony_ci        };
731c5f01b2fSopenharmony_ci
732c5f01b2fSopenharmony_ci        // special case for "0"
733c5f01b2fSopenharmony_ci        if (x == 0)
734c5f01b2fSopenharmony_ci        {
735c5f01b2fSopenharmony_ci            o->write_character('0');
736c5f01b2fSopenharmony_ci            return;
737c5f01b2fSopenharmony_ci        }
738c5f01b2fSopenharmony_ci
739c5f01b2fSopenharmony_ci        // use a pointer to fill the buffer
740c5f01b2fSopenharmony_ci        auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
741c5f01b2fSopenharmony_ci
742c5f01b2fSopenharmony_ci        number_unsigned_t abs_value;
743c5f01b2fSopenharmony_ci
744c5f01b2fSopenharmony_ci        unsigned int n_chars{};
745c5f01b2fSopenharmony_ci
746c5f01b2fSopenharmony_ci        if (is_negative_number(x))
747c5f01b2fSopenharmony_ci        {
748c5f01b2fSopenharmony_ci            *buffer_ptr = '-';
749c5f01b2fSopenharmony_ci            abs_value = remove_sign(static_cast<number_integer_t>(x));
750c5f01b2fSopenharmony_ci
751c5f01b2fSopenharmony_ci            // account one more byte for the minus sign
752c5f01b2fSopenharmony_ci            n_chars = 1 + count_digits(abs_value);
753c5f01b2fSopenharmony_ci        }
754c5f01b2fSopenharmony_ci        else
755c5f01b2fSopenharmony_ci        {
756c5f01b2fSopenharmony_ci            abs_value = static_cast<number_unsigned_t>(x);
757c5f01b2fSopenharmony_ci            n_chars = count_digits(abs_value);
758c5f01b2fSopenharmony_ci        }
759c5f01b2fSopenharmony_ci
760c5f01b2fSopenharmony_ci        // spare 1 byte for '\0'
761c5f01b2fSopenharmony_ci        JSON_ASSERT(n_chars < number_buffer.size() - 1);
762c5f01b2fSopenharmony_ci
763c5f01b2fSopenharmony_ci        // jump to the end to generate the string from backward,
764c5f01b2fSopenharmony_ci        // so we later avoid reversing the result
765c5f01b2fSopenharmony_ci        buffer_ptr += n_chars;
766c5f01b2fSopenharmony_ci
767c5f01b2fSopenharmony_ci        // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
768c5f01b2fSopenharmony_ci        // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
769c5f01b2fSopenharmony_ci        while (abs_value >= 100)
770c5f01b2fSopenharmony_ci        {
771c5f01b2fSopenharmony_ci            const auto digits_index = static_cast<unsigned>((abs_value % 100));
772c5f01b2fSopenharmony_ci            abs_value /= 100;
773c5f01b2fSopenharmony_ci            *(--buffer_ptr) = digits_to_99[digits_index][1];
774c5f01b2fSopenharmony_ci            *(--buffer_ptr) = digits_to_99[digits_index][0];
775c5f01b2fSopenharmony_ci        }
776c5f01b2fSopenharmony_ci
777c5f01b2fSopenharmony_ci        if (abs_value >= 10)
778c5f01b2fSopenharmony_ci        {
779c5f01b2fSopenharmony_ci            const auto digits_index = static_cast<unsigned>(abs_value);
780c5f01b2fSopenharmony_ci            *(--buffer_ptr) = digits_to_99[digits_index][1];
781c5f01b2fSopenharmony_ci            *(--buffer_ptr) = digits_to_99[digits_index][0];
782c5f01b2fSopenharmony_ci        }
783c5f01b2fSopenharmony_ci        else
784c5f01b2fSopenharmony_ci        {
785c5f01b2fSopenharmony_ci            *(--buffer_ptr) = static_cast<char>('0' + abs_value);
786c5f01b2fSopenharmony_ci        }
787c5f01b2fSopenharmony_ci
788c5f01b2fSopenharmony_ci        o->write_characters(number_buffer.data(), n_chars);
789c5f01b2fSopenharmony_ci    }
790c5f01b2fSopenharmony_ci
791c5f01b2fSopenharmony_ci    /*!
792c5f01b2fSopenharmony_ci    @brief dump a floating-point number
793c5f01b2fSopenharmony_ci
794c5f01b2fSopenharmony_ci    Dump a given floating-point number to output stream @a o. Works internally
795c5f01b2fSopenharmony_ci    with @a number_buffer.
796c5f01b2fSopenharmony_ci
797c5f01b2fSopenharmony_ci    @param[in] x  floating-point number to dump
798c5f01b2fSopenharmony_ci    */
799c5f01b2fSopenharmony_ci    void dump_float(number_float_t x)
800c5f01b2fSopenharmony_ci    {
801c5f01b2fSopenharmony_ci        // NaN / inf
802c5f01b2fSopenharmony_ci        if (!std::isfinite(x))
803c5f01b2fSopenharmony_ci        {
804c5f01b2fSopenharmony_ci            o->write_characters("null", 4);
805c5f01b2fSopenharmony_ci            return;
806c5f01b2fSopenharmony_ci        }
807c5f01b2fSopenharmony_ci
808c5f01b2fSopenharmony_ci        // If number_float_t is an IEEE-754 single or double precision number,
809c5f01b2fSopenharmony_ci        // use the Grisu2 algorithm to produce short numbers which are
810c5f01b2fSopenharmony_ci        // guaranteed to round-trip, using strtof and strtod, resp.
811c5f01b2fSopenharmony_ci        //
812c5f01b2fSopenharmony_ci        // NB: The test below works if <long double> == <double>.
813c5f01b2fSopenharmony_ci        static constexpr bool is_ieee_single_or_double
814c5f01b2fSopenharmony_ci            = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
815c5f01b2fSopenharmony_ci              (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
816c5f01b2fSopenharmony_ci
817c5f01b2fSopenharmony_ci        dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
818c5f01b2fSopenharmony_ci    }
819c5f01b2fSopenharmony_ci
820c5f01b2fSopenharmony_ci    void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
821c5f01b2fSopenharmony_ci    {
822c5f01b2fSopenharmony_ci        auto* begin = number_buffer.data();
823c5f01b2fSopenharmony_ci        auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
824c5f01b2fSopenharmony_ci
825c5f01b2fSopenharmony_ci        o->write_characters(begin, static_cast<size_t>(end - begin));
826c5f01b2fSopenharmony_ci    }
827c5f01b2fSopenharmony_ci
828c5f01b2fSopenharmony_ci    void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
829c5f01b2fSopenharmony_ci    {
830c5f01b2fSopenharmony_ci        // get number of digits for a float -> text -> float round-trip
831c5f01b2fSopenharmony_ci        static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
832c5f01b2fSopenharmony_ci
833c5f01b2fSopenharmony_ci        // the actual conversion
834c5f01b2fSopenharmony_ci        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
835c5f01b2fSopenharmony_ci        std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
836c5f01b2fSopenharmony_ci
837c5f01b2fSopenharmony_ci        // negative value indicates an error
838c5f01b2fSopenharmony_ci        JSON_ASSERT(len > 0);
839c5f01b2fSopenharmony_ci        // check if buffer was large enough
840c5f01b2fSopenharmony_ci        JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
841c5f01b2fSopenharmony_ci
842c5f01b2fSopenharmony_ci        // erase thousands separator
843c5f01b2fSopenharmony_ci        if (thousands_sep != '\0')
844c5f01b2fSopenharmony_ci        {
845c5f01b2fSopenharmony_ci            // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
846c5f01b2fSopenharmony_ci            const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
847c5f01b2fSopenharmony_ci            std::fill(end, number_buffer.end(), '\0');
848c5f01b2fSopenharmony_ci            JSON_ASSERT((end - number_buffer.begin()) <= len);
849c5f01b2fSopenharmony_ci            len = (end - number_buffer.begin());
850c5f01b2fSopenharmony_ci        }
851c5f01b2fSopenharmony_ci
852c5f01b2fSopenharmony_ci        // convert decimal point to '.'
853c5f01b2fSopenharmony_ci        if (decimal_point != '\0' && decimal_point != '.')
854c5f01b2fSopenharmony_ci        {
855c5f01b2fSopenharmony_ci            // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
856c5f01b2fSopenharmony_ci            const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
857c5f01b2fSopenharmony_ci            if (dec_pos != number_buffer.end())
858c5f01b2fSopenharmony_ci            {
859c5f01b2fSopenharmony_ci                *dec_pos = '.';
860c5f01b2fSopenharmony_ci            }
861c5f01b2fSopenharmony_ci        }
862c5f01b2fSopenharmony_ci
863c5f01b2fSopenharmony_ci        o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
864c5f01b2fSopenharmony_ci
865c5f01b2fSopenharmony_ci        // determine if we need to append ".0"
866c5f01b2fSopenharmony_ci        const bool value_is_int_like =
867c5f01b2fSopenharmony_ci            std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
868c5f01b2fSopenharmony_ci                         [](char c)
869c5f01b2fSopenharmony_ci        {
870c5f01b2fSopenharmony_ci            return c == '.' || c == 'e';
871c5f01b2fSopenharmony_ci        });
872c5f01b2fSopenharmony_ci
873c5f01b2fSopenharmony_ci        if (value_is_int_like)
874c5f01b2fSopenharmony_ci        {
875c5f01b2fSopenharmony_ci            o->write_characters(".0", 2);
876c5f01b2fSopenharmony_ci        }
877c5f01b2fSopenharmony_ci    }
878c5f01b2fSopenharmony_ci
879c5f01b2fSopenharmony_ci    /*!
880c5f01b2fSopenharmony_ci    @brief check whether a string is UTF-8 encoded
881c5f01b2fSopenharmony_ci
882c5f01b2fSopenharmony_ci    The function checks each byte of a string whether it is UTF-8 encoded. The
883c5f01b2fSopenharmony_ci    result of the check is stored in the @a state parameter. The function must
884c5f01b2fSopenharmony_ci    be called initially with state 0 (accept). State 1 means the string must
885c5f01b2fSopenharmony_ci    be rejected, because the current byte is not allowed. If the string is
886c5f01b2fSopenharmony_ci    completely processed, but the state is non-zero, the string ended
887c5f01b2fSopenharmony_ci    prematurely; that is, the last byte indicated more bytes should have
888c5f01b2fSopenharmony_ci    followed.
889c5f01b2fSopenharmony_ci
890c5f01b2fSopenharmony_ci    @param[in,out] state  the state of the decoding
891c5f01b2fSopenharmony_ci    @param[in,out] codep  codepoint (valid only if resulting state is UTF8_ACCEPT)
892c5f01b2fSopenharmony_ci    @param[in] byte       next byte to decode
893c5f01b2fSopenharmony_ci    @return               new state
894c5f01b2fSopenharmony_ci
895c5f01b2fSopenharmony_ci    @note The function has been edited: a std::array is used.
896c5f01b2fSopenharmony_ci
897c5f01b2fSopenharmony_ci    @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
898c5f01b2fSopenharmony_ci    @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
899c5f01b2fSopenharmony_ci    */
900c5f01b2fSopenharmony_ci    static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
901c5f01b2fSopenharmony_ci    {
902c5f01b2fSopenharmony_ci        static const std::array<std::uint8_t, 400> utf8d =
903c5f01b2fSopenharmony_ci        {
904c5f01b2fSopenharmony_ci            {
905c5f01b2fSopenharmony_ci                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
906c5f01b2fSopenharmony_ci                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
907c5f01b2fSopenharmony_ci                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
908c5f01b2fSopenharmony_ci                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
909c5f01b2fSopenharmony_ci                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
910c5f01b2fSopenharmony_ci                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
911c5f01b2fSopenharmony_ci                8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
912c5f01b2fSopenharmony_ci                0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
913c5f01b2fSopenharmony_ci                0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
914c5f01b2fSopenharmony_ci                0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
915c5f01b2fSopenharmony_ci                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
916c5f01b2fSopenharmony_ci                1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
917c5f01b2fSopenharmony_ci                1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
918c5f01b2fSopenharmony_ci                1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
919c5f01b2fSopenharmony_ci            }
920c5f01b2fSopenharmony_ci        };
921c5f01b2fSopenharmony_ci
922c5f01b2fSopenharmony_ci        JSON_ASSERT(byte < utf8d.size());
923c5f01b2fSopenharmony_ci        const std::uint8_t type = utf8d[byte];
924c5f01b2fSopenharmony_ci
925c5f01b2fSopenharmony_ci        codep = (state != UTF8_ACCEPT)
926c5f01b2fSopenharmony_ci                ? (byte & 0x3fu) | (codep << 6u)
927c5f01b2fSopenharmony_ci                : (0xFFu >> type) & (byte);
928c5f01b2fSopenharmony_ci
929c5f01b2fSopenharmony_ci        std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
930c5f01b2fSopenharmony_ci        JSON_ASSERT(index < 400);
931c5f01b2fSopenharmony_ci        state = utf8d[index];
932c5f01b2fSopenharmony_ci        return state;
933c5f01b2fSopenharmony_ci    }
934c5f01b2fSopenharmony_ci
935c5f01b2fSopenharmony_ci    /*
936c5f01b2fSopenharmony_ci     * Overload to make the compiler happy while it is instantiating
937c5f01b2fSopenharmony_ci     * dump_integer for number_unsigned_t.
938c5f01b2fSopenharmony_ci     * Must never be called.
939c5f01b2fSopenharmony_ci     */
940c5f01b2fSopenharmony_ci    number_unsigned_t remove_sign(number_unsigned_t x)
941c5f01b2fSopenharmony_ci    {
942c5f01b2fSopenharmony_ci        JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
943c5f01b2fSopenharmony_ci        return x; // LCOV_EXCL_LINE
944c5f01b2fSopenharmony_ci    }
945c5f01b2fSopenharmony_ci
946c5f01b2fSopenharmony_ci    /*
947c5f01b2fSopenharmony_ci     * Helper function for dump_integer
948c5f01b2fSopenharmony_ci     *
949c5f01b2fSopenharmony_ci     * This function takes a negative signed integer and returns its absolute
950c5f01b2fSopenharmony_ci     * value as unsigned integer. The plus/minus shuffling is necessary as we can
951c5f01b2fSopenharmony_ci     * not directly remove the sign of an arbitrary signed integer as the
952c5f01b2fSopenharmony_ci     * absolute values of INT_MIN and INT_MAX are usually not the same. See
953c5f01b2fSopenharmony_ci     * #1708 for details.
954c5f01b2fSopenharmony_ci     */
955c5f01b2fSopenharmony_ci    inline number_unsigned_t remove_sign(number_integer_t x) noexcept
956c5f01b2fSopenharmony_ci    {
957c5f01b2fSopenharmony_ci        JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
958c5f01b2fSopenharmony_ci        return static_cast<number_unsigned_t>(-(x + 1)) + 1;
959c5f01b2fSopenharmony_ci    }
960c5f01b2fSopenharmony_ci
961c5f01b2fSopenharmony_ci  private:
962c5f01b2fSopenharmony_ci    /// the output of the serializer
963c5f01b2fSopenharmony_ci    output_adapter_t<char> o = nullptr;
964c5f01b2fSopenharmony_ci
965c5f01b2fSopenharmony_ci    /// a (hopefully) large enough character buffer
966c5f01b2fSopenharmony_ci    std::array<char, 64> number_buffer{{}};
967c5f01b2fSopenharmony_ci
968c5f01b2fSopenharmony_ci    /// the locale
969c5f01b2fSopenharmony_ci    const std::lconv* loc = nullptr;
970c5f01b2fSopenharmony_ci    /// the locale's thousand separator character
971c5f01b2fSopenharmony_ci    const char thousands_sep = '\0';
972c5f01b2fSopenharmony_ci    /// the locale's decimal point character
973c5f01b2fSopenharmony_ci    const char decimal_point = '\0';
974c5f01b2fSopenharmony_ci
975c5f01b2fSopenharmony_ci    /// string buffer
976c5f01b2fSopenharmony_ci    std::array<char, 512> string_buffer{{}};
977c5f01b2fSopenharmony_ci
978c5f01b2fSopenharmony_ci    /// the indentation character
979c5f01b2fSopenharmony_ci    const char indent_char;
980c5f01b2fSopenharmony_ci    /// the indentation string
981c5f01b2fSopenharmony_ci    string_t indent_string;
982c5f01b2fSopenharmony_ci
983c5f01b2fSopenharmony_ci    /// error_handler how to react on decoding errors
984c5f01b2fSopenharmony_ci    const error_handler_t error_handler;
985c5f01b2fSopenharmony_ci};
986c5f01b2fSopenharmony_ci
987c5f01b2fSopenharmony_ci}  // namespace detail
988c5f01b2fSopenharmony_ciNLOHMANN_JSON_NAMESPACE_END
989