WPILibC++ 2027.0.0-alpha-5
Loading...
Searching...
No Matches
json.hpp
Go to the documentation of this file.
1// -*- mode:c++;indent-tabs-mode:nil;c-basic-offset:4;coding:utf-8 -*-
2// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
3//
4// Copyright 2024 Mozilla Foundation
5//
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18#pragma once
19
20#include <climits>
21#include <concepts>
22#include <ranges>
23#include <string>
24#include <string_view>
25#include <tuple>
26#include <utility>
27#include <vector>
28
30#include "wpi/util/expected"
31
32namespace wpi::util {
33
34class json;
35class raw_ostream;
36
37template <typename T>
39
40namespace detail {
41template <typename T>
42concept HasToJson = requires(json& j, const T& val) {
43 { to_json(j, val) };
44};
45
46template <typename T>
47concept HasFromJson = requires(const json& j, T& val) {
48 { from_json(j, val) };
49};
50
51template <typename T>
52concept HasJsonSerializer = requires (json& j, const json& cj, const T& val) {
55};
56
57template <typename T>
58concept HasJsonDeserializer = requires (json& j, const json& cj, const T& val) {
60 { json_serializer<typename std::remove_cvref_t<T>>::from(cj) } -> std::convertible_to<typename std::remove_cvref_t<T>>;
61};
62
63template <typename T>
67 std::is_same_v<T, std::nullptr_t> ||
68 std::is_same_v<T, bool> ||
69 std::is_floating_point_v<T> ||
70 std::is_integral_v<T> ||
71 std::convertible_to<T, std::string> ||
72 std::convertible_to<T, std::string_view> ||
73 std::is_same_v<T, std::vector<json>> ||
74 std::is_same_v<T, wpi::util::StringMap<json>>;
75
76template <typename F, typename Tuple, size_t... I>
77void apply_pairs_helper(F&& f, Tuple&& t, std::index_sequence<I...>) {
78 // This fold expression creates a sequence of calls to f for each pair
79 (f(std::get<I * 2>(std::forward<Tuple>(t)),
80 std::get<I * 2 + 1>(std::forward<Tuple>(t))), ...);
81}
82} // namespace detail
83
84class json
85{
86 friend bool operator==(const json& lhs, const json& rhs);
87 public:
88 using array_t = std::vector<json>;
90
103
104 private:
105 enum Status
106 {
107 success,
108 bad_double,
109 absent_value,
110 bad_negative,
111 bad_exponent,
112 missing_comma,
113 missing_colon,
114 malformed_utf8,
115 depth_exceeded,
116 stack_overflow,
117 unexpected_eof,
118 overlong_ascii,
119 unexpected_comma,
120 unexpected_colon,
121 unexpected_octal,
122 trailing_content,
123 illegal_character,
124 invalid_hex_escape,
125 overlong_utf8_0x7ff,
126 overlong_utf8_0xffff,
127 object_missing_value,
128 illegal_utf8_character,
129 invalid_unicode_escape,
130 utf16_surrogate_in_utf8,
131 unexpected_end_of_array,
132 hex_escape_not_printable,
133 invalid_escape_character,
134 utf8_exceeds_utf16_range,
135 unexpected_end_of_string,
136 unexpected_end_of_object,
137 object_key_must_be_string,
138 c1_control_code_in_string,
139 non_del_c0_control_code_in_string,
140 };
141
142 Type type_;
143 union
144 {
148 long long long_value;
149 unsigned long long ulong_value;
150 std::string string_value;
153 };
154
155 public:
157 static json parse_or_throw(std::string_view);
158
159 json(const json&);
161 json(const char*);
162 json(const std::string&);
163 json(std::string_view);
165
166 constexpr json(const std::nullptr_t = nullptr) : type_(Type::Null)
167 {
168 }
169
170 constexpr json(std::same_as<bool> auto value) : type_(Type::Bool), bool_value(value)
171 {
172 }
173
174 constexpr json(int value) : type_(Type::Int), long_value(value)
175 {
176 }
177
178 constexpr json(float value) : type_(Type::Float), float_value(value)
179 {
180 }
181
182 constexpr json(unsigned value) : type_(Type::Int), long_value(value)
183 {
184 }
185
186 constexpr json(long value) : type_(Type::Int), long_value(value)
187 {
188 }
189
190 constexpr json(unsigned long value)
191 {
192 if (value <= LLONG_MAX) {
193 type_ = Type::Int;
195 } else {
196 type_ = Type::Uint;
198 }
199 }
200
201 constexpr json(long long value) : type_(Type::Int), long_value(value)
202 {
203 }
204
205 constexpr json(unsigned long long value)
206 {
207 if (value <= LLONG_MAX) {
208 type_ = Type::Int;
210 } else {
211 type_ = Type::Uint;
213 }
214 }
215
216 constexpr json(double value) : type_(Type::Double), double_value(value)
217 {
218 }
219
220 json(std::string&& value) : type_(Type::String), string_value(std::move(value))
221 {
222 }
223
225 {
226 }
227
229 {
230 }
231
232 template <std::ranges::input_range R>
234 json(const R& range) : type_(Type::Array), array_value(std::ranges::cbegin(range), std::ranges::cend(range))
235 {
236 }
237
238 template <detail::HasToJson T>
239 json(const T& value) : type_(Type::Null)
240 {
241 to_json(*this, value);
242 }
243
244 template <detail::HasJsonSerializer T>
245 json(const T& value) : type_(Type::Null)
246 {
248 }
249
250 constexpr Type type() const
251 {
252 return type_;
253 }
254
255 constexpr bool is_null() const
256 {
257 return type_ == Type::Null;
258 }
259
260 constexpr bool is_bool() const
261 {
262 return type_ == Type::Bool;
263 }
264
265 constexpr bool is_number() const
266 {
267 return is_float() || is_double() || is_int() || is_uint();
268 }
269
270 constexpr bool is_int() const
271 {
272 return type_ == Type::Int;
273 }
274
275 constexpr bool is_uint() const
276 {
277 return type_ == Type::Uint;
278 }
279
280 constexpr bool is_float() const
281 {
282 return type_ == Type::Float;
283 }
284
285 constexpr bool is_double() const
286 {
287 return type_ == Type::Double;
288 }
289
290 bool is_string() const
291 {
292 return type_ == Type::String;
293 }
294
295 bool is_array() const
296 {
297 return type_ == Type::Array;
298 }
299
300 bool is_object() const
301 {
302 return type_ == Type::Object;
303 }
304
305 bool get_bool() const;
306 float get_float() const;
307 double get_double() const;
308 double get_number() const;
309 long long get_int() const;
310 unsigned long long get_uint() const;
311 std::string& get_string();
312 const std::string& get_string() const;
314 const array_t& get_array() const;
316 const object_t& get_object() const;
317
318 template <detail::HasFromJson T>
319 T get() const {
320 T value;
321 from_json(*this, value);
322 return value;
323 }
324
325 template <detail::HasJsonDeserializer T>
326 T get() const {
327 return json_serializer<T>::from(*this);
328 }
329
330 bool contains(std::string_view) const;
331
332 json* lookup(std::string_view);
333 const json* lookup(std::string_view) const;
334
335 void set_array();
337
338 template <typename... Args>
339 static json array(Args&&... args) {
340 json j;
341 j.set_array();
342 (j.array_value.emplace_back(std::forward<Args>(args)), ...);
343 return j;
344 }
345
346 template <typename... Args>
347 static json object(Args&&... args) {
348 json j;
349 j.set_object();
351 [&](auto&& key, auto&& value) {
352 j.object_value[std::forward<decltype(key)>(key)] = std::forward<decltype(value)>(value);
353 },
354 std::forward_as_tuple(args...),
355 std::make_index_sequence<sizeof...(Args) / 2>{});
356 return j;
357 }
358
359 std::string to_string() const;
360 std::string to_string_pretty() const;
361
364
365 template <detail::HasToJson T>
366 json& operator=(const T& value) {
367 to_json(*this, value);
368 return *this;
369 }
370
371 template <detail::HasJsonSerializer T>
372 json& operator=(const T& value) {
374 return *this;
375 }
376
377 json& operator[](size_t);
378 json& operator[](std::string_view);
379
380 json& at(size_t);
381 json& at(std::string_view);
382
383 const json& at(size_t) const;
384 const json& at(std::string_view) const;
385
386 json value(size_t, json&&);
387 json value(std::string_view, json&&);
388
389 void erase(std::string_view);
390
392
393 bool empty() const;
394
395 operator std::string() const
396 {
397 return to_string();
398 }
399
400 void marshal(wpi::util::raw_ostream& os, bool pretty = false, int indent = 0) const;
401
402 static void stringify_null(wpi::util::raw_ostream&);
403 static void stringify_string(wpi::util::raw_ostream&, std::string_view);
404 static void stringify_bool(wpi::util::raw_ostream&, bool);
405 static void stringify_float(wpi::util::raw_ostream&, float);
406 static void stringify_double(wpi::util::raw_ostream&, double);
407 static void stringify_int(wpi::util::raw_ostream&, long long);
408 static void stringify_uint(wpi::util::raw_ostream&, unsigned long long);
409 static void stringify_array(wpi::util::raw_ostream&, const array_t&, bool pretty = false, int indent = 0);
410 static void stringify_object(wpi::util::raw_ostream&, const object_t&, bool pretty = false, int indent = 0);
411
412 private:
413 static const char* StatusToString(Status);
414 void clear();
415 static void serialize(wpi::util::raw_ostream&, std::string_view);
416 static Status parse(json&, const char*&, const char*, int, int);
417};
418
419bool operator==(const json& lhs, const json& rhs);
420inline bool operator!=(const json& lhs, const json& rhs) {
421 return !(lhs == rhs);
422}
423
424} // namespace wpi::util
and restrictions which apply to each piece of software is included later in this file and or inside of the individual applicable source files The disclaimer of warranty in the WPILib license above applies to all code in and nothing in any of the other licenses gives permission to use the names of FIRST nor the names of the WPILib contributors to endorse or promote products derived from this software The following pieces of software have additional or alternate and or glfw and nanopb were modified for use in Google Inc All rights reserved Redistribution and use in source and binary with or without are permitted provided that the following conditions are this list of conditions and the following disclaimer *Redistributions in binary form must reproduce the above copyright this list of conditions and the following disclaimer in the documentation and or other materials provided with the distribution *Neither the name of Google Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable from
Definition ThirdPartyNotices.txt:136
StringMap is a sorted associative container that contains key-value pairs with unique string keys.
Definition StringMap.hpp:26
An expected<T, E> object is an object that contains the storage for another object and manages the li...
Definition expected:1250
Definition json.hpp:85
json & at(std::string_view)
std::vector< json > array_t
Definition json.hpp:88
json(const T &value)
Definition json.hpp:239
json(const R &range)
Definition json.hpp:234
static void stringify_int(wpi::util::raw_ostream &, long long)
std::string to_string() const
json & at(size_t)
json & operator=(json &&)
bool bool_value
Definition json.hpp:145
json(std::string_view)
constexpr json(long long value)
Definition json.hpp:201
json(const json &)
std::string string_value
Definition json.hpp:150
const array_t & get_array() const
json(const std::string &)
object_t & get_object()
constexpr json(unsigned long long value)
Definition json.hpp:205
array_t & get_array()
json value(size_t, json &&)
bool contains(std::string_view) const
Type
Definition json.hpp:92
@ Int
Definition json.hpp:95
@ Float
Definition json.hpp:97
@ String
Definition json.hpp:99
@ Array
Definition json.hpp:100
@ Object
Definition json.hpp:101
@ Null
Definition json.hpp:93
@ Bool
Definition json.hpp:94
@ Double
Definition json.hpp:98
@ Uint
Definition json.hpp:96
json & emplace_back(json &&value)
T get() const
Definition json.hpp:319
constexpr bool is_float() const
Definition json.hpp:280
long long long_value
Definition json.hpp:148
static void stringify_double(wpi::util::raw_ostream &, double)
json & operator=(const T &value)
Definition json.hpp:366
long long get_int() const
static json object(Args &&... args)
Definition json.hpp:347
json * lookup(std::string_view)
void erase(std::string_view)
constexpr json(std::same_as< bool > auto value)
Definition json.hpp:170
constexpr json(int value)
Definition json.hpp:174
json value(std::string_view, json &&)
std::string & get_string()
json(array_t &&value)
Definition json.hpp:224
json & operator=(const json &)
static json array(Args &&... args)
Definition json.hpp:339
static void stringify_uint(wpi::util::raw_ostream &, unsigned long long)
bool empty() const
bool is_object() const
Definition json.hpp:300
const json & at(size_t) const
constexpr json(double value)
Definition json.hpp:216
double get_double() const
const json * lookup(std::string_view) const
constexpr bool is_double() const
Definition json.hpp:285
constexpr json(long value)
Definition json.hpp:186
json(object_t &&value)
Definition json.hpp:228
static void stringify_object(wpi::util::raw_ostream &, const object_t &, bool pretty=false, int indent=0)
void marshal(wpi::util::raw_ostream &os, bool pretty=false, int indent=0) const
float float_value
Definition json.hpp:146
double get_number() const
constexpr bool is_uint() const
Definition json.hpp:275
bool is_array() const
Definition json.hpp:295
static void stringify_string(wpi::util::raw_ostream &, std::string_view)
const json & at(std::string_view) const
const object_t & get_object() const
double double_value
Definition json.hpp:147
unsigned long long get_uint() const
json(std::string &&value)
Definition json.hpp:220
std::string to_string_pretty() const
constexpr bool is_null() const
Definition json.hpp:255
array_t array_value
Definition json.hpp:151
unsigned long long ulong_value
Definition json.hpp:149
constexpr bool is_number() const
Definition json.hpp:265
constexpr json(unsigned long value)
Definition json.hpp:190
constexpr bool is_bool() const
Definition json.hpp:260
static void stringify_float(wpi::util::raw_ostream &, float)
constexpr Type type() const
Definition json.hpp:250
constexpr json(const std::nullptr_t=nullptr)
Definition json.hpp:166
wpi::util::StringMap< json > object_t
Definition json.hpp:89
json(const char *)
static void stringify_null(wpi::util::raw_ostream &)
constexpr json(float value)
Definition json.hpp:178
static json parse_or_throw(std::string_view)
static wpi::util::expected< json, const char * > parse(std::string_view)
bool is_string() const
Definition json.hpp:290
constexpr bool is_int() const
Definition json.hpp:270
constexpr json(unsigned value)
Definition json.hpp:182
object_t object_value
Definition json.hpp:152
bool get_bool() const
json & operator[](std::string_view)
friend bool operator==(const json &lhs, const json &rhs)
float get_float() const
json & operator[](size_t)
const std::string & get_string() const
static void stringify_bool(wpi::util::raw_ostream &, bool)
static void stringify_array(wpi::util::raw_ostream &, const array_t &, bool pretty=false, int indent=0)
Definition json.hpp:47
Definition json.hpp:42
Converts a string literal into a format string that will be parsed at compile time and converted into...
Definition printf.h:50
Definition StringMap.hpp:773
void apply_pairs_helper(F &&f, Tuple &&t, std::index_sequence< I... >)
Definition json.hpp:77
Definition raw_os_ostream.hpp:19
constexpr bool operator!=(const unexpected< E > &lhs, const unexpected< E > &rhs)
Definition expected:180
constexpr bool operator==(const unexpected< E > &lhs, const unexpected< E > &rhs)
Definition expected:176
Definition json.hpp:38