FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
json2cpp/include/json2cpp/json2cpp.hpp at main · lefticus/json2cpp · GitHub
lefticus
/
json2cpp
Public
Uh oh!
There was an error while loading.
Please reload this page
.
Notifications
You must be signed in to change notification settings
Fork
23
Star
293
Code
Issues
3
Pull requests
3
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
json2cpp
/
include
/
json2cpp
/
json2cpp.hpp
Copy path
More file actions
More file actions
Latest commit
History
History
History
507 lines (413 loc) · 16 KB
Breadcrumbs
json2cpp
/
include
/
json2cpp
/
json2cpp.hpp
Copy path
File metadata and controls
507 lines (413 loc) · 16 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
/*
MIT License
Copyright (c) 2022 Jason Turner
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//
Important note: the types in this file are only intended for compile-time construction
//
but consteval doesn't exist in C++17, and we're targeting C++17
#
ifndef
CONSTEXPR_JSON_HPP_INCLUDED
#
define
CONSTEXPR_JSON_HPP_INCLUDED
#
include
<
array
>
#
include
<
cassert
>
#
include
<
cstdint
>
#
include
<
stdexcept
>
#
include
<
string_view
>
//
simple pair to speed up compilation a bit compared to std::pair
namespace
json2cpp
{
template
<
typename
First,
typename
Second>
struct
pair
{
First first;
Second second;
};
//
simple span because std::span is not in C++17
template
<
typename
T>
struct
span
{
template
<std::
size_t
Size>
constexpr
explicit
span
(
const
std::array<T, Size> &input)
: begin_{ input.
data
() }, end_{
std::next
(input.
data
(), Size) }
{}
constexpr
span
() : begin_{
nullptr
}, end_{
nullptr
} {}
[[nodiscard]]
constexpr
const
T *
begin
()
const
noexcept
{
return
begin_; }
[[nodiscard]]
constexpr
const
T *
end
()
const
noexcept
{
return
end_; }
[[nodiscard]]
constexpr
std::
size_t
size
()
const
noexcept
{
return
static_cast
<std::
size_t
>(
std::distance
(begin_, end_));
}
const
T *begin_;
const
T *end_;
};
template
<
typename
CharType>
struct
basic_json
;
template
<
typename
CharType>
using
basic_array_t
= span<basic_json<CharType>>;
template
<
typename
CharType>
using
basic_value_pair_t
= pair<std::basic_string_view<CharType>, basic_json<CharType>>;
template
<
typename
CharType>
using
basic_object_t
= span<
basic_value_pair_t
<CharType>>;
using
binary_t
= span<std::
uint8_t
>;
template
<
typename
CharType>
struct
data_variant
{
struct
monostate
{
};
union
value_t
{
monostate empty_;
bool
bool_;
binary_t
binary_;
basic_array_t
<CharType> array_;
basic_object_t
<CharType> object_;
std::
int64_t
int64_t_;
std::
uint64_t
uint64_t_;
double
double_;
std::basic_string_view<CharType> string_view_;
std::
nullptr_t
null_;
constexpr
explicit
value_t
() : empty_{} {}
constexpr
explicit
value_t
(monostate) :
value_t
() {}
constexpr
explicit
value_t
(
bool
b) : bool_{ b } {}
constexpr
explicit
value_t
(
binary_t
b) : binary_{ b } {}
constexpr
explicit
value_t
(
basic_array_t
<CharType> a) : array_{ a } {}
constexpr
explicit
value_t
(
basic_object_t
<CharType> o) : object_{ o } {}
constexpr
explicit
value_t
(std::
int64_t
i) : int64_t_{ i } {}
constexpr
explicit
value_t
(std::
uint64_t
i) : uint64_t_{ i } {}
constexpr
explicit
value_t
(
double
d) : double_{ d } {}
constexpr
explicit
value_t
(std::basic_string_view<CharType> s) : string_view_{ s } {}
constexpr
explicit
value_t
(std::
nullptr_t
) : null_{} {}
};
enum
struct
selected_type
{
empty,
boolean,
binary,
array,
object,
integer,
uinteger,
floating_point,
string,
nullish
};
value_t
value{ monostate{} };
selected_type selected{ selected_type::empty };
//
letting these be implicit measurably improves construction performance
constexpr
data_variant
() = default;
//
cppcheck-suppress noExplicitConstructor
constexpr
data_variant
(monostate) : data_variant() {}
//
cppcheck-suppress noExplicitConstructor
constexpr
data_variant
(
bool
b) : value{ b }, selected{ selected_type::boolean } {}
//
cppcheck-suppress noExplicitConstructor
constexpr
data_variant
(
basic_array_t
<CharType> a) : value{ a }, selected{ selected_type::array } {}
//
cppcheck-suppress noExplicitConstructor
constexpr
data_variant
(
basic_object_t
<CharType> o) : value{ o }, selected{ selected_type::object } {}
//
cppcheck-suppress noExplicitConstructor
constexpr
data_variant
(std::
int64_t
i) : value{ i }, selected{ selected_type::integer } {}
//
cppcheck-suppress noExplicitConstructor
constexpr
data_variant
(std::
uint64_t
i) : value{ i }, selected{ selected_type::uinteger } {}
//
cppcheck-suppress noExplicitConstructor
constexpr
data_variant
(
double
d) : value{ d }, selected{ selected_type::floating_point } {}
//
cppcheck-suppress noExplicitConstructor
constexpr
data_variant
(std::basic_string_view<CharType> s) : value{ s }, selected{ selected_type::string } {}
//
cppcheck-suppress noExplicitConstructor
constexpr
data_variant
(std::
nullptr_t
) : value{
nullptr
}, selected{ selected_type::nullish } {}
[[nodiscard]]
constexpr
bool
is_boolean
()
const
noexcept
{
return
selected == selected_type::boolean; }
[[nodiscard]]
constexpr
const
bool
*
get_if_boolean
()
const
noexcept
{
if
(selected == selected_type::boolean) {
return
&value.
bool_
;
}
else
{
return
nullptr
;
}
}
[[nodiscard]]
constexpr
bool
is_array
()
const
noexcept
{
return
selected == selected_type::array; }
[[nodiscard]]
constexpr
const
basic_array_t
<CharType> *
get_if_array
()
const
noexcept
{
if
(
is_array
()) {
return
&value.
array_
;
}
else
{
return
nullptr
;
}
}
[[nodiscard]]
constexpr
bool
is_object
()
const
noexcept
{
return
selected == selected_type::object; }
[[nodiscard]]
constexpr
const
basic_object_t
<CharType> *
get_if_object
()
const
noexcept
{
if
(
is_object
()) {
return
&value.
object_
;
}
else
{
return
nullptr
;
}
}
[[nodiscard]]
constexpr
bool
is_integer
()
const
noexcept
{
return
selected == selected_type::integer; }
[[nodiscard]]
constexpr
const
std::
int64_t
*
get_if_integer
()
const
noexcept
{
if
(
is_integer
()) {
return
&value.
int64_t_
;
}
else
{
return
nullptr
;
}
}
[[nodiscard]]
constexpr
bool
is_uinteger
()
const
noexcept
{
return
selected == selected_type::uinteger; }
[[nodiscard]]
constexpr
const
std::
uint64_t
*
get_if_uinteger
()
const
noexcept
{
if
(
is_uinteger
()) {
return
&value.
uint64_t_
;
}
else
{
return
nullptr
;
}
}
[[nodiscard]]
constexpr
bool
is_floating_point
()
const
noexcept
{
return
selected == selected_type::floating_point; }
[[nodiscard]]
constexpr
const
double
*
get_if_floating_point
()
const
noexcept
{
if
(
is_floating_point
()) {
return
&value.
double_
;
}
else
{
return
nullptr
;
}
}
[[nodiscard]]
constexpr
bool
is_string
()
const
noexcept
{
return
selected == selected_type::string; }
[[nodiscard]]
constexpr
const
std::basic_string_view<CharType> *
get_if_string
()
const
noexcept
{
if
(
is_string
()) {
return
&value.
string_view_
;
}
else
{
return
nullptr
;
}
}
[[nodiscard]]
constexpr
bool
is_null
()
const
noexcept
{
return
selected == selected_type::nullish; }
};
template
<
typename
CharType>
struct
basic_json
{
using
data_t
= data_variant<CharType>;
struct
iterator
{
constexpr
iterator
()
noexcept
= default;
constexpr
explicit
iterator
(
const
basic_json &value, std::
size_t
index =
0
)
noexcept
: parent_value_(&value), index_{ index }
{}
constexpr
const
basic_json &
operator
*()
const
{
if
(parent_value_->
is_array
()) {
return
(*parent_value_)[index_];
}
else
if
(parent_value_->
is_object
()) {
return
std::next
(parent_value_->
object_data
().
begin
(),
static_cast
<std::
ptrdiff_t
>(index_))->
second
;
}
else
{
return
*parent_value_;
}
}
constexpr
const
basic_json *
operator
->()
const
noexcept
{
return
&(*(*
this
)); }
constexpr
std::
size_t
index
()
const
noexcept
{
return
index_; }
constexpr
const
basic_json &
value
()
const
noexcept
{
return
*(*
this
); }
constexpr
std::basic_string_view<CharType>
key
()
const
{
if
(parent_value_->
is_object
()) {
return
std::next
(parent_value_->
object_data
().
begin
(),
static_cast
<std::
ptrdiff_t
>(index_))->
first
;
}
else
{
throw
std::runtime_error
(
"
json value is not an object, it has no key
"
);
}
}
constexpr
bool
operator
==(
const
iterator &other)
const
noexcept
{
return
other.
parent_value_
== parent_value_ && other.
index_
== index_;
}
constexpr
bool
operator
!=(
const
iterator &other)
const
noexcept
{
return
!(*
this
== other); }
constexpr
bool
operator
<(
const
iterator &other)
const
noexcept
{
return
other.
parent_value_
== parent_value_ && index_ < other.
index_
;
}
constexpr
iterator &
operator
--()
noexcept
{
--index_;
return
*
this
;
}
[[nodiscard]]
constexpr
iterator
operator
--(
int
)
noexcept
{
iterator result{ *
this
};
index_--;
return
result;
}
constexpr
iterator &
operator
++()
noexcept
{
++index_;
return
*
this
;
}
[[nodiscard]]
constexpr
iterator
operator
++(
int
)
noexcept
{
iterator result{ *
this
};
index_++;
return
result;
}
constexpr
iterator &
operator
+=(
const
std::
ptrdiff_t
value)
noexcept
{
index_ =
static_cast
<std::
size_t
>(
static_cast
<std::
ptrdiff_t
>(index_) + value);
return
*
this
;
}
constexpr
iterator &
operator
+=(
const
std::
size_t
value)
noexcept
{
index_ += value;
return
*
this
;
}
const
basic_json *parent_value_{
nullptr
};
std::
size_t
index_{
0
};
};
using
const_iterator = iterator;
[[nodiscard]]
constexpr
iterator
begin
()
const
noexcept
{
return
iterator{ *
this
}; }
[[nodiscard]]
constexpr
iterator
end
()
const
noexcept
{
return
iterator{ *
this
,
size
() }; }
[[nodiscard]]
constexpr
iterator
cbegin
()
const
noexcept
{
return
begin
(); }
[[nodiscard]]
constexpr
iterator
cend
()
const
noexcept
{
return
end
(); }
[[nodiscard]]
constexpr
std::
size_t
size
()
const
noexcept
{
return
size_; }
[[nodiscard]]
constexpr
bool
empty
()
const
noexcept
{
return
size_ ==
0
; }
[[nodiscard]]
static
constexpr
std::
size_t
size
(
const
basic_json &obj)
noexcept
{
if
(obj.
is_null
()) {
return
0
; }
if
(obj.
is_object
()) {
return
obj.
data
.
get_if_object
()->
size
(); }
if
(obj.
is_array
()) {
return
obj.
data
.
get_if_array
()->
size
(); }
return
1
;
}
[[nodiscard]]
constexpr
const
basic_json &
operator
[](
const
std::
size_t
idx)
const
{
if
(
const
auto
&children =
array_data
(); idx < children.
size
()) {
return
*
std::next
(children.
begin
(),
static_cast
<std::
ptrdiff_t
>(idx));
}
else
{
throw
std::runtime_error
(
"
index out of range
"
);
}
}
[[nodiscard]]
constexpr
const
basic_json &
at
(
const
std::basic_string_view<CharType> key)
const
{
const
auto
&children =
object_data
();
//
find_if is not constexpr in C++17, so we rolled our own,
//
and this helps us work around bugs in older versions of GCC
//
and constexpr
const
auto
finder = [&]() {
auto
itr = children.
begin
();
for
(; itr != children.
end
(); ++itr) {
if
(itr->
first
== key) {
return
itr; }
}
return
itr;
};
const
auto
obj =
finder
();
if
(obj != children.
end
()) {
return
obj->
second
;
}
else
{
throw
std::runtime_error
(
"
Key not found
"
);
}
}
template
<
typename
Key>
[[nodiscard]]
constexpr
std::
size_t
count
(
const
Key &key)
const
{
if
(
is_object
()) {
const
auto
found =
find
(key);
if
(found ==
end
()) {
return
0
;
}
else
{
return
1
;
}
}
return
0
;
}
[[nodiscard]]
constexpr
iterator
find
(
const
std::basic_string_view<CharType> key)
const
{
for
(
auto
itr =
begin
(); itr !=
end
(); ++itr) {
if
(itr.
key
() == key) {
return
itr; }
}
return
end
();
}
[[nodiscard]]
constexpr
const
basic_json &
operator
[](
const
std::basic_string_view<CharType> key)
const
{
return
at
(key);
}
constexpr
const
auto
&
array_data
()
const
{
if
(data.
is_array
()) {
return
*data.
get_if_array
();
}
else
{
throw
std::runtime_error
(
"
value is not an array type
"
);
}
}
constexpr
const
auto
&
object_data
()
const
{
if
(data.
is_object
()) {
return
*data.
get_if_object
();
}
else
{
throw
std::runtime_error
(
"
value is not an object type
"
);
}
}
constexpr
static
basic_json
object
() {
return
basic_json{
data_t
{
basic_object_t
<CharType>{} } }; }
constexpr
static
basic_json
array
() {
return
basic_json{
data_t
{
basic_array_t
<CharType>{} } }; }
template
<
typename
Type>
[[nodiscard]]
constexpr
auto
get
()
const
{
//
I don't like this level of implicit conversions in the `get()` function,
//
but it's necessary for API compatibility with nlohmann::json
if
constexpr
(std::is_same_v<Type,
std::
uint64_t
> || std::is_same_v<Type, std::
int64_t
> || std::is_same_v<Type,
double
>) {
if
(data.
is_uinteger
()) {
return
Type
(*data.
get_if_uinteger
());
}
else
if
(data.
is_integer
()) {
return
Type
(*data.
get_if_integer
());
}
else
if
(data.
is_floating_point
()) {
return
Type
(*data.
get_if_floating_point
());
}
else
{
throw
std::runtime_error
(
"
Unexpected type: number requested
"
);
//
+ ss.str() );
}
}
else
if
constexpr
(std::is_same_v<Type,
std::basic_string_view<CharType>> || std::is_same_v<Type, std::basic_string<CharType>>) {
if
(data.
is_string
()) {
return
*data.
get_if_string
();
}
else
{
throw
std::runtime_error
(
"
Unexpected type: string-like requested
"
);
}
}
else
if
constexpr
(std::is_same_v<Type,
bool
>) {
if
(data.
is_boolean
()) {
return
*data.
get_if_boolean
();
}
else
{
throw
std::runtime_error
(
"
Unexpected type: bool requested
"
);
}
}
else
if
constexpr
(std::is_same_v<Type, std::
nullptr_t
>) {
if
(data.
is_null
()) {
return
nullptr
;
}
else
{
throw
std::runtime_error
(
"
Unexpected type: null requested
"
);
}
}
else
{
throw
std::runtime_error
(
"
Unexpected type for get()
"
);
}
}
[[nodiscard]]
constexpr
bool
is_object
()
const
noexcept
{
return
data.
selected
==
data_t
::selected_type::object; }
[[nodiscard]]
constexpr
bool
is_array
()
const
noexcept
{
return
data.
selected
==
data_t
::selected_type::array; }
[[nodiscard]]
constexpr
bool
is_string
()
const
noexcept
{
return
data.
selected
==
data_t
::selected_type::string; }
[[nodiscard]]
constexpr
bool
is_boolean
()
const
noexcept
{
return
data.
selected
==
data_t
::selected_type::boolean; }
[[nodiscard]]
constexpr
bool
is_structured
()
const
noexcept
{
return
is_object
() ||
is_array
(); }
[[nodiscard]]
constexpr
bool
is_number
()
const
noexcept
{
return
is_number_integer
() ||
is_number_float
(); }
[[nodiscard]]
constexpr
bool
is_number_integer
()
const
noexcept
{
return
is_number_signed
() ||
is_number_unsigned
(); }
[[nodiscard]]
constexpr
bool
is_null
()
const
noexcept
{
return
data.
selected
==
data_t
::selected_type::nullish; }
[[nodiscard]]
constexpr
bool
is_binary
()
const
noexcept
{
return
data.
selected
==
data_t
::selected_type::binary; }
[[nodiscard]]
constexpr
bool
is_number_signed
()
const
noexcept
{
return
data.
selected
==
data_t
::selected_type::integer;
}
[[nodiscard]]
constexpr
bool
is_number_unsigned
()
const
noexcept
{
return
data.
selected
==
data_t
::selected_type::uinteger;
}
[[nodiscard]]
constexpr
bool
is_number_float
()
const
noexcept
{
return
data.
selected
==
data_t
::selected_type::floating_point;
}
[[nodiscard]]
constexpr
bool
is_primitive
()
const
noexcept
{
return
is_null
() ||
is_string
() ||
is_boolean
() ||
is_number
() ||
is_binary
();
}
data_t
data;
std::
size_t
size_{
basic_json::size
(*
this
) };
};
using
json = basic_json<
char
>;
using
object_t
=
basic_object_t
<
char
>;
using
value_pair_t
=
basic_value_pair_t
<
char
>;
using
array_t
=
basic_array_t
<
char
>;
}
//
namespace json2cpp
#
endif
Back
|
FazBrowse Home
|
New Git URL