WPILibC++ 2023.4.3-108-ge5452e3
json_serializer.h
Go to the documentation of this file.
1/*----------------------------------------------------------------------------*/
2/* Modifications Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7/*
8 __ _____ _____ _____
9 __| | __| | | | JSON for Modern C++
10| | |__ | | | | | | version 3.1.2
11|_____|_____|_____|_|___| https://github.com/nlohmann/json
12
13Licensed under the MIT License <http://opensource.org/licenses/MIT>.
14Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
15
16Permission is hereby granted, free of charge, to any person obtaining a copy
17of this software and associated documentation files (the "Software"), to deal
18in the Software without restriction, including without limitation the rights
19to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20copies of the Software, and to permit persons to whom the Software is
21furnished to do so, subject to the following conditions:
22
23The above copyright notice and this permission notice shall be included in all
24copies or substantial portions of the Software.
25
26THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32SOFTWARE.
33*/
34#include "wpi/json.h"
35
36#include <clocale> // lconv, localeconv
37#include <cmath> // labs, isfinite, isnan, signbit, ldexp
38#include <type_traits>
39
40#include "wpi/raw_ostream.h"
41
42namespace wpi {
43
45{
46 static constexpr uint8_t UTF8_ACCEPT = 0;
47 static constexpr uint8_t UTF8_REJECT = 1;
48
49 public:
50 /*!
51 @param[in] s output stream to serialize to
52 @param[in] ichar indentation character to use
53 @param[in] indent_init_len initial length of indentation string buffer
54 */
55 serializer(raw_ostream& s, const char ichar, size_t indent_init_len = 512)
56 : o(s), indent_char(ichar),
57 indent_string(indent_init_len, indent_char)
58 {}
59
60 // delete because of pointer members
61 serializer(const serializer&) = delete;
62 serializer& operator=(const serializer&) = delete;
63
64 /*!
65 @brief internal implementation of the serialization function
66
67 This function is called by the public member function dump and organizes
68 the serialization internally. The indentation level is propagated as
69 additional parameter. In case of arrays and objects, the function is
70 called recursively.
71
72 - strings and object keys are escaped using `escape_string()`
73 - integer numbers are converted implicitly via `operator<<`
74 - floating-point numbers are converted to a string using `"%g"` format
75
76 @param[in] val value to serialize
77 @param[in] pretty_print whether the output shall be pretty-printed
78 @param[in] ensure_ascii whether the output shall only use ASCII chars
79 @param[in] indent_step the indent level
80 @param[in] current_indent the current indent level (only used internally)
81 */
82 void dump(const json& val, const bool pretty_print,
83 const bool ensure_ascii,
84 const unsigned int indent_step,
85 const unsigned int current_indent = 0);
86
87 /*!
88 @brief dump escaped string
89
90 Escape a string by replacing certain special characters by a sequence of an
91 escape character (backslash) and another character and other control
92 characters by a sequence of "\u" followed by a four-digit hex
93 representation. The escaped string is written to output stream @a o.
94
95 @param[in] s the string to escape
96 @param[in] ensure_ascii whether to escape non-ASCII characters with
97 "\uXXXX" sequences
98
99 Complexity: Linear in the length of string @a s.
100 */
101 void dump_escaped(std::string_view s, const bool ensure_ascii);
102
103 template <typename NumberType,
105 bool is_negative_integer(NumberType x) {
106 return false;
107 }
108
109 template <typename NumberType,
111 bool is_negative_integer(NumberType x) {
112 return x < 0;
113 }
114
115 /*!
116 @brief dump an integer
117
118 Dump a given integer to output stream @a o. Works internally with
119 @a number_buffer.
120
121 @param[in] x integer number (signed or unsigned) to dump
122 @tparam NumberType either @a int64_t or @a uint64_t
123 */
124 template<typename NumberType, detail::enable_if_t<
125 std::is_same<NumberType, uint64_t>::value or
126 std::is_same<NumberType, int64_t>::value,
127 int> = 0>
128 void dump_integer(NumberType x)
129 {
130 // special case for "0"
131 if (x == 0)
132 {
133 o << '0';
134 return;
135 }
136
137 const bool is_negative = is_negative_integer(x); // see issue #755
138 std::size_t i = 0;
139
140 while (x != 0)
141 {
142 // spare 1 byte for '\0'
143 assert(i < number_buffer.size() - 1);
144
145 const auto digit = std::labs(static_cast<long>(x % 10));
146 number_buffer[i++] = static_cast<char>('0' + digit);
147 x /= 10;
148 }
149
150 if (is_negative)
151 {
152 // make sure there is capacity for the '-'
153 assert(i < number_buffer.size() - 2);
154 number_buffer[i++] = '-';
155 }
156
157 std::reverse(number_buffer.begin(), number_buffer.begin() + i);
158 o.write(number_buffer.data(), i);
159 }
160
161 /*!
162 @brief dump a floating-point number
163
164 Dump a given floating-point number to output stream @a o. Works internally
165 with @a number_buffer.
166
167 @param[in] x floating-point number to dump
168 */
169 void dump_float(double x);
170
171 /*!
172 @brief check whether a string is UTF-8 encoded
173
174 The function checks each byte of a string whether it is UTF-8 encoded. The
175 result of the check is stored in the @a state parameter. The function must
176 be called initially with state 0 (accept). State 1 means the string must
177 be rejected, because the current byte is not allowed. If the string is
178 completely processed, but the state is non-zero, the string ended
179 prematurely; that is, the last byte indicated more bytes should have
180 followed.
181
182 @param[in,out] state the state of the decoding
183 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
184 @param[in] byte next byte to decode
185 @return new state
186
187 @note The function has been edited: a std::array is used.
188
189 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
190 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
191 */
192 static uint8_t decode(uint8_t& state, uint32_t& codep, const uint8_t byte) noexcept;
193
194 private:
195 /// the output of the serializer
196 raw_ostream& o;
197
198 /// a (hopefully) large enough character buffer
199 std::array<char, 64> number_buffer{{}};
200
201 /// the indentation character
202 const char indent_char;
203 /// the indentation string
204 std::string indent_string;
205};
206
207} // namespace wpi
or
Definition: ThirdPartyNotices.txt:196
Definition: json_serializer.h:45
serializer(const serializer &)=delete
void dump(const json &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
void dump_escaped(std::string_view s, const bool ensure_ascii)
dump escaped string
bool is_negative_integer(NumberType x)
Definition: json_serializer.h:105
serializer & operator=(const serializer &)=delete
static uint8_t decode(uint8_t &state, uint32_t &codep, const uint8_t byte) noexcept
check whether a string is UTF-8 encoded
serializer(raw_ostream &s, const char ichar, size_t indent_init_len=512)
Definition: json_serializer.h:55
void dump_integer(NumberType x)
dump an integer
Definition: json_serializer.h:128
void dump_float(double x)
dump a floating-point number
a class to store JSON values
Definition: json.h:2655
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:44
raw_ostream & write(unsigned char C)
basic_string_view< char > string_view
Definition: core.h:520
constexpr auto is_negative(T value) -> bool
Definition: format.h:1009
::uint32_t uint32_t
Definition: Meta.h:56
::uint8_t uint8_t
Definition: Meta.h:52
typename std::enable_if< B, T >::type enable_if_t
Definition: json.h:207
Definition: AprilTagFieldLayout.h:18