neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
json.inl
Go to the documentation of this file.
1// json.inl
2/*
3 * NoFussJSON v1.0
4 *
5 * Copyright (c) 2018, 2020 Leigh Johnston.
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
11 * met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * * Neither the name of Leigh Johnston nor the names of any
21 * other contributors to this software may be used to endorse or
22 * promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
26 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
27 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36*/
37
38#pragma once
39
40#include <neolib/neolib.hpp>
41#include <variant>
42#include <unordered_map>
43#include <fstream>
44#include <iomanip>
45#include <type_traits>
46#include <boost/lexical_cast.hpp>
47#include <boost/functional/hash.hpp>
52
53namespace neolib
54{
55 namespace json_detail
56 {
57#ifdef DEBUG_JSON
58 constexpr bool debug = true;
59#else
60 constexpr bool debug = false;
61#endif
62 enum class keyword
63 {
64 True,
65 False,
66 Null
67 };
68
69 enum class token : uint8_t
70 {
71 Invalid,
76 Colon,
77 Comma,
78 Quote,
80 Escape,
82 Escaped,
83 Plus,
84 Minus,
85 Digit,
92 Symbol,
93 Space,
97 };
98 constexpr std::size_t TOKEN_COUNT = static_cast<std::size_t>(token::TOKEN_COUNT);
111 constexpr token TPLU = token::Plus;
124
158 constexpr std::size_t STATE_COUNT = static_cast<std::size_t>(state::STATE_COUNT);
172 constexpr state SNAM = state::Name;
188
189 inline std::string to_string(state aState)
190 {
191 switch (aState)
192 {
193 case state::Error:
194 return std::string{ "Error" };
195 case state::Ignore:
196 return std::string{ "Ignore" };
198 return std::string{ "EndOfParse" };
199 case state::Element:
200 return std::string{ "Element" };
201 case state::Object:
202 return std::string{ "Object" };
203 case state::Array:
204 return std::string{ "Array" };
205 case state::Close:
206 return std::string{ "Close" };
207 case state::Value:
208 return std::string{ "Value" };
210 return std::string{ "NeedValueSeparator" };
211 case state::NeedValue:
212 return std::string{ "NeedValue" };
214 return std::string{ "NeedObjectValueSeparator" };
216 return std::string{ "NeedObjectValue" };
217 case state::Keyword:
218 return std::string{ "Keyword" };
219 case state::Name:
220 return std::string{ "Name" };
221 case state::EndName:
222 return std::string{ "EndName" };
223 case state::String:
224 return std::string{ "String" };
225 case state::StringEnd:
226 return std::string{ "StringEnd" };
228 return std::string{ "NumberIntNeedDigit" };
229 case state::NumberInt:
230 return std::string{ "NumberInt" };
232 return std::string{ "NumberFracNeedDigit" };
234 return std::string{ "NumberFrac" };
236 return std::string{ "NumberExpSign" };
238 return std::string{ "NumberExpIntNeedDigit" };
240 return std::string{ "NumberExpInt" };
241 case state::Escaping:
242 return std::string{ "Escaping" };
243 case state::Escaped:
244 return std::string{ "Escaped" };
246 return std::string{ "EscapingUnicode" };
249 return std::string{ "Comment" };
250 default:
251 return std::string{ "??" };
252 }
253 }
254
255 template <json_syntax Syntax>
256 constexpr inline std::array<state, TOKEN_COUNT> object_state()
257 {
258 if constexpr (Syntax != json_syntax::Functional)
259 {
260 return
261 // state::Object
262 std::array<state, TOKEN_COUNT>
263 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
265 }};
266 }
267 else
268 {
269 return
270 // state::Object
271 std::array<state, TOKEN_COUNT>
272 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
274 }};
275 }
276 }
277
278 template <json_syntax Syntax>
279 constexpr inline std::array<state, TOKEN_COUNT> need_value_state()
280 {
281 if constexpr (Syntax != json_syntax::Functional)
282 {
283 return
284 // state::NeedValue
285 std::array<state, TOKEN_COUNT>
286 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
288 }};
289 }
290 else
291 {
292 return
293 // state::NeedValue
294 std::array<state, TOKEN_COUNT>
295 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
297 }};
298 }
299 }
300
301 template <json_syntax Syntax>
302 constexpr inline std::array<state, TOKEN_COUNT> need_object_value_state()
303 {
304 if constexpr (Syntax != json_syntax::Functional)
305 {
306 return
307 // state::NeedObjectValue
308 std::array<state, TOKEN_COUNT>
309 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
311 }};
312 }
313 else
314 {
315 return
316 // state::NeedObjectValue
317 std::array<state, TOKEN_COUNT>
318 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
320 }};
321 }
322 }
323
324 template <json_syntax Syntax>
325 constexpr inline std::array<state, TOKEN_COUNT> value_state()
326 {
327 if constexpr (Syntax == json_syntax::Standard || Syntax == json_syntax::StandardNoKeywords)
328 {
329 return
330 // state::Value
331 std::array<state, TOKEN_COUNT>
332 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
334 }};
335 }
336 else
337 {
338 return
339 // state::Value
340 std::array<state, TOKEN_COUNT>
341 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
343 }};
344 }
345 }
346
347 template <json_syntax Syntax>
348 constexpr inline std::array<state, TOKEN_COUNT> keyword_state()
349 {
350 if constexpr (Syntax == json_syntax::Standard || Syntax == json_syntax::StandardNoKeywords)
351 {
352 return
353 // state::Keyword
354 std::array<state, TOKEN_COUNT>
355 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
357 }};
358 }
359 else if constexpr (Syntax == json_syntax::Relaxed)
360 {
361 return
362 // state::Keyword
363 std::array<state, TOKEN_COUNT>
364 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
366 }};
367 }
368 else
369 {
370 return
371 // state::Keyword
372 std::array<state, TOKEN_COUNT>
373 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
375 }};
376 }
377 }
378
379 template <json_syntax Syntax>
380 constexpr std::array<std::array<state, TOKEN_COUNT>, STATE_COUNT> sStateTables
381 {
382 // state::Error
383 std::array<state, TOKEN_COUNT>
384 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
386 }},
387 // state::Ignore
388 std::array<state, TOKEN_COUNT>
389 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
391 }},
392 // state::EndOfParse
393 std::array<state, TOKEN_COUNT>
394 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
396 }},
397 // state::Element
398 std::array<state, TOKEN_COUNT>
399 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
401 }},
402 // state::Object
403 object_state<Syntax>(),
404 // state::Array
405 std::array<state, TOKEN_COUNT>
406 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
408 }},
409 // state::Close
410 std::array<state, TOKEN_COUNT>
411 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
413 }},
414 // state::Value
415 value_state<Syntax>(),
416 // state::NeedValueSeparator
417 std::array<state, TOKEN_COUNT>
418 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
420 }},
421 // state::NeedValue
422 need_value_state<Syntax>(),
423 // state::NeedObjectValueSeparator
424 std::array<state, TOKEN_COUNT>
425 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
427 }},
428 // state::NeedObjectValue
429 need_object_value_state<Syntax>(),
430 // state::Keyword
431 keyword_state<Syntax>(),
432 // state::Name
433 std::array<state, TOKEN_COUNT>
434 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
436 }},
437 // state::EndName
438 std::array<state, TOKEN_COUNT>
439 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
441 }},
442 // state::String
443 std::array<state, TOKEN_COUNT>
444 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
446 }},
447 // state::StringEnd
448 std::array<state, TOKEN_COUNT>
449 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
451 }},
452 // state::NumberIntNeedDigit
453 std::array<state, TOKEN_COUNT>
454 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
456 }},
457 // state::NumberInt
458 std::array<state, TOKEN_COUNT>
459 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
461 }},
462 // state::NumberFracNeedDigit
463 std::array<state, TOKEN_COUNT>
464 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
466 }},
467 // state::NumberFrac
468 std::array<state, TOKEN_COUNT>
469 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
471 }},
472 // state::NumberExpSign
473 std::array<state, TOKEN_COUNT>
474 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
476 }},
477 // state::NumberExpIntNeedDigit
478 std::array<state, TOKEN_COUNT>
479 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
481 }},
482 // state::NumberExpInt
483 std::array<state, TOKEN_COUNT>
484 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
486 }},
487 // state::Escaping
488 std::array<state, TOKEN_COUNT>
489 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
491 }},
492 // state::Escaped
493 std::array<state, TOKEN_COUNT>
494 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
496 }},
497 // state::EscapingUnicode
498 std::array<state, TOKEN_COUNT>
499 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
501 }},
502 // state::CppStyleComment
503 std::array<state, TOKEN_COUNT>
504 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
506 }},
507 // state::CStyleComment
508 std::array<state, TOKEN_COUNT>
509 {{//TXXX TOBJ TCLO TARR TCLA TCOL TCOM TQOT TCHA TESC TESU TECH TPLU TMIN TDIG THEX TEHX TDEC TEXP TAST TFWD TSYM TSPA TWSP TZZZ
511 }}
512 };
513
514 template <json_syntax Syntax>
515 constexpr std::array<token, 256> sTokenTable
516 {
517 {// 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF
518 TZZZ, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TWSP, TWSP, TXXX, TXXX, TWSP, TXXX, TXXX, // 0x0
519 TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, // 0x1
520 TSPA, TSYM, TQOT, TSYM, TCHA, TSYM, TSYM, TSYM, TSYM, TSYM, TAST, TPLU, TCOM, TMIN, TDEC, TFWD, // 0x2
521 TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TCOL, TSYM, TSYM, TSYM, TSYM, TSYM, // 0x3
522 TCHA, THEX, THEX, THEX, THEX, TEXP, THEX, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0x4
523 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TARR, TESC, TCLA, TSYM, TCHA, // 0x5
524 TSYM, THEX, TEHX, THEX, THEX, TEXP, TEHX, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TECH, TCHA, // 0x6
525 TCHA, TCHA, TECH, TCHA, TECH, TESU, TCHA, TCHA, TCHA, TCHA, TCHA, TOBJ, TSYM, TCLO, TSYM, TSYM, // 0x7
526 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0x8
527 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0x9
528 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xA
529 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xB
530 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xC
531 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xD
532 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xE
533 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xF
534 },
535 };
536
537 template <>
538 constexpr std::array<token, 256> sTokenTable<json_syntax::Relaxed>
539 {
540 {// 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF
541 TZZZ, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TWSP, TWSP, TXXX, TXXX, TWSP, TXXX, TXXX, // 0x0
542 TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, // 0x1
543 TSPA, TSYM, TQOT, TSYM, TCHA, TSYM, TSYM, TQOT, TSYM, TSYM, TAST, TPLU, TCOM, TMIN, TDEC, TFWD, // 0x2
544 TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TCOL, TSYM, TSYM, TSYM, TSYM, TSYM, // 0x3
545 TCHA, THEX, THEX, THEX, THEX, TEXP, THEX, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0x4
546 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TARR, TESC, TCLA, TSYM, TCHA, // 0x5
547 TQOT, THEX, TEHX, THEX, THEX, TEXP, TEHX, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TECH, TCHA, // 0x6
548 TCHA, TCHA, TECH, TCHA, TECH, TESU, TCHA, TCHA, TCHA, TCHA, TCHA, TOBJ, TSYM, TCLO, TSYM, TSYM, // 0x7
549 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0x8
550 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0x9
551 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xA
552 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xB
553 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xC
554 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xD
555 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xE
556 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xF
557 },
558 };
559
560 template <>
561 constexpr std::array<token, 256> sTokenTable<json_syntax::Functional>
562 {
563 {// 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF
564 TZZZ, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TWSP, TWSP, TXXX, TXXX, TWSP, TXXX, TXXX, // 0x0
565 TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, TXXX, // 0x1
566 TSPA, TSYM, TQOT, TSYM, TCHA, TSYM, TSYM, TQOT, TSYM, TSYM, TAST, TPLU, TSYM, TMIN, TDEC, TFWD, // 0x2
567 TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TDIG, TCOL, TSYM, TSYM, TSYM, TSYM, TSYM, // 0x3
568 TCHA, THEX, THEX, THEX, THEX, TEXP, THEX, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0x4
569 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TARR, TESC, TCLA, TSYM, TCHA, // 0x5
570 TQOT, THEX, TEHX, THEX, THEX, TEXP, TEHX, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TECH, TCHA, // 0x6
571 TCHA, TCHA, TECH, TCHA, TECH, TESU, TCHA, TCHA, TCHA, TCHA, TCHA, TOBJ, TSYM, TCLO, TSYM, TSYM, // 0x7
572 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0x8
573 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0x9
574 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xA
575 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xB
576 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xC
577 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xD
578 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xE
579 TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, TCHA, // 0xF
580 },
581 };
582
583 template <typename CharT>
584 inline token to_token(const std::array<token, 256>& aTokenTable, CharT aCharacter)
585 {
586 auto const tableIndex = std::min<std::size_t>(static_cast<typename std::make_unsigned<CharT>::type>(aCharacter), 0xFFu);
587 return aTokenTable[tableIndex];
588 }
589
590 template <json_syntax Syntax, typename CharT>
591 inline state next_state(state aCurrentState, CharT aCharacter)
592 {
593 auto const token = to_token(sTokenTable<Syntax>, aCharacter);
594 auto const stateIndex = static_cast<std::size_t>(aCurrentState);
595 return sStateTables<Syntax>[stateIndex][static_cast<std::size_t>(token)];
596 }
597
598 template <json_syntax Syntax, typename CharT>
599 inline state next_state(state aCurrentState, state aPreviousState, CharT aCurrentCharacter, CharT aNextCharacter)
600 {
601 if constexpr (Syntax == json_syntax::Standard || Syntax == json_syntax::StandardNoKeywords)
602 return next_state<Syntax>(aCurrentState, aCurrentCharacter);
603 else
604 {
605 auto const token = to_token(sTokenTable<Syntax>, aCurrentCharacter);
606 switch (aCurrentState)
607 {
609 if (aCurrentCharacter != '\n' && token != token::EndOfInput)
611 return next_state<Syntax>(aPreviousState, aPreviousState, aCurrentCharacter, aNextCharacter);
614 {
615 auto const nextToken = to_token(sTokenTable<Syntax>, aNextCharacter);
616 if (nextToken == json_detail::token::ForwardSlash)
617 return state::Ignore;
618 else if (nextToken == json_detail::token::EndOfInput)
619 return state::Error;
620 }
622 return state::Error;
624 default:
626 {
627 auto const nextToken = to_token(sTokenTable<Syntax>, aNextCharacter);
628 if (nextToken == json_detail::token::ForwardSlash)
630 else if (nextToken == json_detail::token::Asterisk)
632 }
633 break;
634 }
635 auto const stateIndex = static_cast<std::size_t>(aCurrentState);
636 return sStateTables<Syntax>[stateIndex][static_cast<std::size_t>(token)];
637 }
638 }
639
641 {
642 template <typename String>
643 std::size_t operator()(const String& aString) const noexcept
644 {
645 return std::hash<typename String::value_type>{}(aString[0]);
646 }
647 };
648 }
649
650 namespace json_detail
651 {
652 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
663
664 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
675 }
676
677 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
678 template <typename IteratorTraits>
679 class basic_json_value<Syntax, Alloc, CharT, Traits, CharAlloc>::iterator_base : public IteratorTraits
680 {
681 private:
682 typedef IteratorTraits traits;
683 protected:
684 using typename traits::iterator_category;
685 using typename traits::value_type;
686 using typename traits::difference_type;
687 using typename traits::pointer;
688 using typename traits::reference;
689 protected:
692 protected:
693 iterator_base() : iValue{ nullptr }
694 {
695 }
696 iterator_base(const iterator_base& aOther) : iValue{ aOther.iValue }
697 {
698 }
699 protected:
700 iterator_base(value_pointer aValue) : iValue{ aValue }
701 {
702 }
703 protected:
704 pointer operator->() const
705 {
706 return &*iValue;
707 }
708 reference operator*() const
709 {
710 return *iValue;
711 }
712 protected:
713 void operator++()
714 {
715 iValue = value().next_sibling();
716 }
717 void operator--()
718 {
719 // todo
720 iValue = nullptr;
721 }
722 protected:
723 bool operator==(const iterator_base& aOther) const
724 {
725 return iValue == aOther.iValue;
726 }
727 bool operator!=(const iterator_base& aOther) const
728 {
729 return iValue != aOther.iValue;
730 }
731 protected:
732 value_reference value() const
733 {
734 return *iValue;
735 }
736 bool has_parent() const
737 {
738 return iValue != nullptr && value().has_parent();
739 }
740 value_pointer parent() const
741 {
742 if (has_parent())
743 return &value().parent();
744 return nullptr;
745 }
746 private:
747 value_pointer iValue;
748 };
749
750 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
751 class basic_json_value<Syntax, Alloc, CharT, Traits, CharAlloc>::iterator : iterator_base<typename json_detail::iterator_traits<Syntax, Alloc, CharT, Traits, CharAlloc>>
752 {
753 typedef iterator_base<typename json_detail::iterator_traits<Syntax, Alloc, CharT, Traits, CharAlloc>> base_type;
754 friend class basic_json_value<Syntax, Alloc, CharT, Traits, CharAlloc>;
755 public:
756 using typename base_type::iterator_category;
757 using typename base_type::value_type;
758 using typename base_type::difference_type;
759 using typename base_type::pointer;
760 using typename base_type::reference;
761 public:
762 using typename base_type::value_pointer;
763 public:
765 {
766 }
767 iterator(const iterator& aOther) : base_type{ aOther }
768 {
769 }
770 private:
771 iterator(value_pointer aValue) : base_type{ aValue }
772 {
773 }
774 public:
775 using base_type::operator*;
776 using base_type::operator->;
777 public:
779 {
780 base_type::operator++();
781 return *this;
782 }
784 {
785 auto previous = *this;
786 base_type::operator++();
787 return previous;
788 }
790 {
791 base_type::operator--();
792 return *this;
793 }
795 {
796 auto previous = *this;
797 base_type::operator--();
798 return previous;
799 }
800 public:
801 bool operator==(const iterator& aRhs) const
802 {
803 return base_type::operator==(aRhs);
804 }
805 bool operator!=(const iterator& aRhs) const
806 {
807 return base_type::operator!=(aRhs);
808 }
809 public:
810 using base_type::value;
811 };
812
813 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
814 class basic_json_value<Syntax, Alloc, CharT, Traits, CharAlloc>::const_iterator : iterator_base<typename json_detail::const_iterator_traits<Syntax, Alloc, CharT, Traits, CharAlloc>>
815 {
816 typedef iterator_base<typename json_detail::const_iterator_traits<Syntax, Alloc, CharT, Traits, CharAlloc>> base_type;
817 friend class basic_json_value<Syntax, Alloc, CharT, Traits, CharAlloc>;
818 public:
819 using typename base_type::iterator_category;
820 using typename base_type::value_type;
821 using typename base_type::difference_type;
822 using typename base_type::pointer;
823 using typename base_type::reference;
824 public:
825 using typename base_type::value_pointer;
826 public:
828 {
829 }
830 const_iterator(const const_iterator& aOther) : base_type{ aOther }
831 {
832 }
833 const_iterator(const iterator& aOther) : base_type{ aOther.iValue }
834 {
835 }
836 private:
837 const_iterator(value_pointer aValue) : base_type{ aValue }
838 {
839 }
840 public:
841 using base_type::operator*;
842 using base_type::operator->;
843 public:
845 {
846 base_type::operator++();
847 return *this;
848 }
850 {
851 auto previous = *this;
852 base_type::operator++();
853 return previous;
854 }
856 {
857 base_type::operator--();
858 return *this;
859 }
861 {
862 auto previous = *this;
863 base_type::operator--();
864 return previous;
865 }
866 public:
867 bool operator==(const const_iterator& aRhs) const
868 {
869 return base_type::operator==(aRhs);
870 }
871 bool operator!=(const const_iterator& aRhs) const
872 {
873 return base_type::operator!=(aRhs);
874 }
875 public:
876 using base_type::value;
877 };
878
879 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
880 template <typename IteratorTraits>
881 class basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::iterator_base : public IteratorTraits
882 {
883 private:
884 typedef IteratorTraits traits;
885 protected:
886 using typename traits::iterator_category;
887 using typename traits::value_type;
888 using typename traits::difference_type;
889 using typename traits::pointer;
890 using typename traits::reference;
891 protected:
894 protected:
895 iterator_base() : iValue{ nullptr }
896 {
897 }
898 iterator_base(const iterator_base& aOther) : iValue{ aOther.iValue }
899 {
900 }
901 protected:
902 iterator_base(value_pointer aValue) : iValue{ aValue }
903 {
904 }
905 protected:
906 pointer operator->() const
907 {
908 return &*iValue;
909 }
910 reference operator*() const
911 {
912 return *iValue;
913 }
914 protected:
915 void operator++()
916 {
917 if (value().has_children())
918 iValue = value().first_child();
919 else if (!value().is_last_sibling())
920 iValue = value().next_sibling();
921 else
922 iValue = value().next_parent_sibling();
923 }
924 void operator--()
925 {
926 // todo
927 iValue = nullptr;
928 }
929 protected:
930 bool operator==(const iterator_base& aOther) const
931 {
932 return iValue == aOther.iValue;
933 }
934 bool operator!=(const iterator_base& aOther) const
935 {
936 return iValue != aOther.iValue;
937 }
938 protected:
939 value_reference value() const
940 {
941 return *iValue;
942 }
943 bool has_parent() const
944 {
945 return iValue != nullptr && value().has_parent();
946 }
947 value_pointer parent() const
948 {
949 if (has_parent())
950 return &value().parent();
951 return nullptr;
952 }
953 private:
954 value_pointer iValue;
955 };
956
957 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
958 class basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::iterator : public iterator_base<typename json_detail::iterator_traits<Syntax, Alloc, CharT, Traits, CharAlloc>>
959 {
960 typedef iterator_base<typename json_detail::iterator_traits<Syntax, Alloc, CharT, Traits, CharAlloc>> base_type;
961 friend class basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>;
962 public:
963 using typename base_type::iterator_category;
964 using typename base_type::value_type;
965 using typename base_type::difference_type;
966 using typename base_type::pointer;
967 using typename base_type::reference;
968 public:
969 using typename base_type::value_pointer;
970 public:
972 {
973 }
974 iterator(const iterator& aOther) : base_type{ aOther }
975 {
976 }
977 private:
978 iterator(value_pointer aValue) : base_type{ aValue }
979 {
980 }
981 public:
982 using base_type::operator*;
983 using base_type::operator->;
984 public:
986 {
987 base_type::operator++();
988 return *this;
989 }
991 {
992 auto previous = *this;
993 base_type::operator++();
994 return previous;
995 }
997 {
998 base_type::operator--();
999 return *this;
1000 }
1002 {
1003 auto previous = *this;
1004 base_type::operator--();
1005 return previous;
1006 }
1007 public:
1008 bool operator==(const iterator& aRhs) const
1009 {
1010 return base_type::operator==(aRhs);
1011 }
1012 bool operator!=(const iterator& aRhs) const
1013 {
1014 return base_type::operator!=(aRhs);
1015 }
1016 public:
1017 using base_type::value;
1018 };
1019
1020 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1021 class basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::const_iterator : public iterator_base<typename json_detail::const_iterator_traits<Syntax, Alloc, CharT, Traits, CharAlloc>>
1022 {
1023 typedef iterator_base<typename json_detail::const_iterator_traits<Syntax, Alloc, CharT, Traits, CharAlloc>> base_type;
1024 friend class basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>;
1025 public:
1026 using typename base_type::iterator_category;
1027 using typename base_type::value_type;
1028 using typename base_type::difference_type;
1029 using typename base_type::pointer;
1030 using typename base_type::reference;
1031 public:
1032 using typename base_type::value_pointer;
1033 public:
1035 {
1036 }
1037 const_iterator(const const_iterator& aOther) : base_type{ aOther }
1038 {
1039 }
1040 const_iterator(const iterator& aOther) : base_type{ aOther.iValue }
1041 {
1042 }
1043 private:
1044 const_iterator(value_pointer aValue) : base_type{ aValue }
1045 {
1046 }
1047 public:
1048 using base_type::operator*;
1049 using base_type::operator->;
1050 public:
1052 {
1053 base_type::operator++();
1054 return *this;
1055 }
1057 {
1058 auto previous = *this;
1059 base_type::operator++();
1060 return previous;
1061 }
1063 {
1064 base_type::operator--();
1065 return *this;
1066 }
1068 {
1069 auto previous = *this;
1070 base_type::operator--();
1071 return previous;
1072 }
1073 public:
1074 bool operator==(const const_iterator& aRhs) const
1075 {
1076 return base_type::operator==(aRhs);
1077 }
1078 bool operator!=(const const_iterator& aRhs) const
1079 {
1080 return base_type::operator!=(aRhs);
1081 }
1082 public:
1083 using base_type::value;
1084 };
1085
1086 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1087 inline basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::basic_json() : iEncoding{ json_detail::default_encoding<CharT>::DEFAULT_ENCODING }, iCursor{}
1088 {
1089 }
1090
1091 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1092 inline basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::basic_json(const std::string& aPath, bool aValidateUtf) : iEncoding{ json_detail::default_encoding<CharT>::DEFAULT_ENCODING }, iCursor{}
1093 {
1094 if (!read(aPath, aValidateUtf))
1095 throw json_error(error_text());
1096 }
1097
1098 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1099 template <typename Elem, typename ElemTraits>
1100 inline basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::basic_json(std::basic_istream<Elem, ElemTraits>& aInput, bool aValidateUtf) : iEncoding{ json_detail::default_encoding<CharT>::DEFAULT_ENCODING }, iCursor{}
1101 {
1102 if (!read(aInput, aValidateUtf))
1103 throw json_error(error_text());
1104 }
1105
1106 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1108 {
1109 iCursor = decltype(iCursor){};
1110 document().clear();
1111 iUtf16HighSurrogate = std::nullopt;
1112 }
1113
1114 template <json_syntax Syntax>
1115 inline constexpr const char* document_type()
1116 {
1117 if constexpr (Syntax == json_syntax::Standard || Syntax == json_syntax::StandardNoKeywords)
1118 return "JSON";
1119 else if constexpr (Syntax == json_syntax::Relaxed)
1120 return "RJSON";
1121 else if constexpr (Syntax == json_syntax::Functional)
1122 return "FJSON";
1123 }
1124
1125 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1126 inline bool basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::read(const std::string& aPath, bool aValidateUtf)
1127 {
1128 std::ifstream input{ aPath, std::ios::binary };
1129 if (!input)
1130 {
1131 iErrorText = "failed to open " + std::string{ document_type<Syntax>() } + " file '" + aPath + "'";
1132 return false;
1133 }
1134 bool ok = do_read(input, aValidateUtf);
1135 if (ok)
1136 ok = do_parse();
1137 if (!ok)
1138 iErrorText = "failed to parse " + std::string{ document_type<Syntax>() } + " file '" + aPath + "', " + iErrorText;
1139 return ok;
1140 }
1141
1142 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1143 template <typename Elem, typename ElemTraits>
1144 inline bool basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::read(std::basic_istream<Elem, ElemTraits>& aInput, bool aValidateUtf)
1145 {
1146 if (!aInput)
1147 {
1148 iErrorText = "failed to read " + std::string{ document_type<Syntax>() } + " text";
1149 return false;
1150 }
1151 bool ok = do_read(aInput, aValidateUtf);
1152 if (ok)
1153 ok = do_parse();
1154 if (!ok)
1155 iErrorText = "failed to parse " + std::string{ document_type<Syntax>() } + " text, " + iErrorText;
1156 return ok;
1157 }
1158
1159 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1160 template <typename Elem, typename ElemTraits>
1161 inline bool basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::do_read(std::basic_istream<Elem, ElemTraits>& aInput, bool aValidateUtf)
1162 {
1163 clear();
1164
1165 if (!aInput)
1166 {
1167 iErrorText = "input stream bad";
1168 return false;
1169 }
1170
1171 typedef typename std::basic_istream<CharT, Traits>::pos_type pos_type;
1172 pos_type count = 0;
1173 aInput.seekg(0, std::ios::end);
1174 if (aInput)
1175 {
1176 count = aInput.tellg();
1177 if (count == static_cast<pos_type>(-1))
1178 count = 0;
1179 aInput.seekg(0, std::ios::beg);
1180 }
1181 else
1182 aInput.clear();
1183
1184 if (count != typename std::basic_istream<CharT>::pos_type(0))
1185 {
1186 document().reserve(static_cast<typename json_string::size_type>(count) + 1);
1187 document().resize(static_cast<typename json_string::size_type>(count));
1188 aInput.read(&document()[0], count);
1189 document().resize(static_cast<typename json_string::size_type>(aInput.gcount()));
1190 }
1191 else
1192 {
1193 CharT buffer[1024];
1194 while (aInput.read(buffer, sizeof(buffer)))
1195 document().append(buffer, static_cast<typename json_string::size_type>(aInput.gcount()));
1196 if (aInput.eof())
1197 document().append(buffer, static_cast<typename json_string::size_type>(aInput.gcount()));
1198 }
1199
1200 if (document().empty())
1201 {
1202 iErrorText = "empty document";
1203 return false;
1204 }
1205
1206 if (json_detail::next_state<syntax>(json_detail::state::Value, document().back()) != json_detail::state::Ignore)
1207 document().push_back(character_type{ '\n' });
1208 document().push_back(character_type{ '\0' });
1209
1210 if (aValidateUtf && !neolib::check_utf8(document().to_std_string_view()))
1211 {
1212 iErrorText = "invalid utf-8";
1213 return false;
1214 }
1215
1216 return true;
1217 }
1218
1219 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1220 inline bool basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::do_parse()
1221 {
1222 static constexpr bool usePreviousState = (Syntax == json_syntax::Relaxed || Syntax == json_syntax::Functional || json_detail::debug);
1223
1225 json_detail::state previousState = currentState;
1226 json_detail::state nextState;
1227 element currentElement = {};
1228
1229 iCursor.line = 1;
1230 iCursor.column = 1;
1231
1232 auto nextInputCh = &*document().begin();
1233 auto nextOutputCh = nextInputCh;
1234
1235 auto increment_cursor = [&nextInputCh, this]()
1236 {
1237 if (*nextInputCh++ != '\n')
1238 ++iCursor.column;
1239 else
1240 {
1241 iCursor.column = 1;
1242 ++iCursor.line;
1243 }
1244 };
1245
1246 // Main parse loop
1247 for (;;)
1248 {
1249 if constexpr (json_detail::debug)
1250 {
1251 if (*nextInputCh != '\n')
1252 std::cout << *nextInputCh;
1253 else
1254 std::cout << "\\n";
1255 }
1256 try
1257 {
1258 if constexpr (!usePreviousState)
1259 nextState = json_detail::next_state<syntax>(currentState, *nextInputCh);
1260 else
1261 {
1262 bool skippingComment = false;
1263 auto tempState = currentState;
1264 do {
1265 nextState = json_detail::next_state<syntax>(tempState, previousState, *nextInputCh, nextInputCh != &iDocumentText.back() ? *(nextInputCh + 1) : '\0');
1266 skippingComment = (nextState == json_detail::state::CppStyleComment || nextState == json_detail::state::CStyleComment);
1267 if (skippingComment)
1268 {
1269 if (tempState != nextState && currentElement.start != nullptr && nextOutputCh == currentElement.start)
1270 nextOutputCh = (currentState != json_detail::state::StringEnd ? nextInputCh : nextInputCh - 1);
1271 tempState = nextState;
1272 increment_cursor();
1273 }
1274 else if (tempState == json_detail::state::CStyleComment && nextState == json_detail::state::Ignore)
1275 increment_cursor();
1276 } while (skippingComment);
1277 }
1278 if constexpr (Syntax == json_syntax::Functional)
1279 {
1280 if (nextState == json_detail::state::Error)
1281 {
1282 switch (currentState)
1283 {
1287 switch (to_token(json_detail::sTokenTable<json_syntax::Functional>, *nextInputCh))
1288 {
1292 currentState = json_detail::state::Keyword;
1293 nextState = json_detail::state::Keyword;
1294 currentElement.type = element::Keyword;
1295 nextOutputCh = nextInputCh;
1296 break;
1297 default:
1298 break;
1299 }
1300 default:
1301 break;
1302 }
1303 }
1304 }
1305 switch (nextState)
1306 {
1308 increment_cursor();
1309 continue;
1311 create_parse_error();
1312 return false;
1314 if (nextInputCh != &iDocumentText.back())
1315 {
1316 create_parse_error();
1317 return false;
1318 }
1319 return true;
1320 default:
1321 if (currentState == nextState)
1322 {
1323 switch (currentState)
1324 {
1328 if (currentElement.start != nextOutputCh)
1329 *nextOutputCh++ = *nextInputCh;
1330 // fall through
1331 default:
1332 increment_cursor();
1333 continue;
1336 break;
1337 }
1338 }
1339 }
1340 if constexpr (json_detail::debug)
1341 std::cout << "(" << to_string(currentState) << " -> " << to_string(nextState) << ")";
1342 switch (nextState)
1343 {
1346 switch (currentElement.type)
1347 {
1348 case element::Unknown:
1349 break;
1350 case element::String:
1351 {
1352 json_string newString{ currentElement.start, currentElement.start == nextOutputCh ? nextInputCh - 1 : nextOutputCh };
1353 buy_value(currentElement, newString);
1354 }
1355 break;
1356 case element::Name:
1357 if (context() == json_type::Object && std::holds_alternative<std::monostate>(currentElement.name))
1358 {
1359 json_string newString{ currentElement.start, currentElement.start == nextOutputCh ? nextInputCh - 1 : nextOutputCh };
1360 currentElement.name = newString;
1361 }
1362 break;
1363 case element::Number:
1364 {
1365 json_string newNumber{ currentElement.start, currentElement.start == nextOutputCh ? nextInputCh : nextOutputCh };
1366 if (currentState == json_detail::state::NumberInt)
1367 {
1368 std::visit([this, &currentElement](auto&& arg)
1369 {
1370 buy_value(currentElement, std::forward<decltype(arg)>(arg));
1371 }, string_to_number(newNumber.to_std_string_view()));
1372 }
1373 else
1374 buy_value(currentElement, neolib::string_to_double(newNumber.to_std_string_view()));
1375 }
1376 break;
1377 case element::Keyword:
1378 {
1379 static const std::unordered_map<std::string_view, json_detail::keyword, json_detail::hash_first_character> sJsonKeywords =
1380 {
1381 { "true", json_detail::keyword::True },
1382 { "false", json_detail::keyword::False },
1383 { "null", json_detail::keyword::Null },
1384 };
1385 auto keywordText = json_string{ currentElement.start, currentElement.start == nextOutputCh ? nextInputCh : nextOutputCh };
1386 auto keyword = sJsonKeywords.find(keywordText);
1387 if (keyword != sJsonKeywords.end())
1388 {
1389 if (context() == json_type::Object && std::holds_alternative<std::monostate>(currentElement.name))
1390 {
1391 create_parse_error("bad object field name");
1392 return false;
1393 }
1394 switch (keyword->second)
1395 {
1397 buy_value(currentElement, json_bool{ true });
1398 break;
1400 buy_value(currentElement, json_bool{ false });
1401 break;
1403 buy_value(currentElement, json_null{});
1404 break;
1405 }
1406 }
1407 else
1408 {
1409 if constexpr (syntax == json_syntax::StandardNoKeywords)
1410 {
1411 create_parse_error("keywords unavailable");
1412 return false;
1413 }
1414 if (context() == json_type::Object && std::holds_alternative<std::monostate>(currentElement.name))
1415 {
1416 currentElement.name = json_keyword{ keywordText };
1417 currentElement.type = element::Name;
1418 }
1419 else
1420 buy_value(currentElement, json_keyword{ keywordText });
1421 }
1422 }
1423 break;
1424 default:
1425 break;
1426 }
1427 if (nextState == json_detail::state::Close)
1428 iCompositeValueStack.pop_back();
1429 switch (context())
1430 {
1431 case json_type::Object:
1432 if constexpr (syntax == json_syntax::Standard)
1433 {
1434 if (std::holds_alternative<std::monostate>(currentElement.name))
1435 {
1436 if (nextState == json_detail::state::Close)
1438 else if (*nextInputCh == ',')
1440 else
1442 }
1443 else
1445 }
1446 else
1447 {
1448 if (std::holds_alternative<std::monostate>(currentElement.name))
1449 nextState = json_detail::state::Object;
1450 else
1451 nextState = *nextInputCh != ':' ? json_detail::state::EndName : json_detail::state::NeedValue;
1452 }
1453 break;
1454 case json_type::Array:
1455 if constexpr (syntax == json_syntax::Standard)
1456 {
1457 if (*nextInputCh == ',')
1459 else
1461 }
1462 else
1463 nextState = json_detail::state::Value;
1464 break;
1465 default:
1466 if (nextState == json_detail::state::Close)
1467 nextState = json_detail::state::Value;
1468 break;
1469 }
1470 currentElement.type = element::Unknown;
1471 currentElement.start = nullptr;
1472 break;
1474 currentElement.type = element::String;
1475 currentElement.start = (nextOutputCh = nextInputCh + 1);
1476 break;
1478 currentElement.type = element::Name;
1479 currentElement.start = (nextOutputCh = nextInputCh + 1);
1480 break;
1482 if (std::holds_alternative<std::monostate>(currentElement.name))
1483 {
1484 json_string newName
1485 {
1486 currentElement.start,
1487 currentElement.start == nextOutputCh ? nextInputCh : nextOutputCh
1488 };
1489 currentElement.name = newName;
1490 }
1491 break;
1493 currentElement.type = element::Number;
1494 currentElement.start = nextInputCh;
1495 break;
1497 if (currentElement.type != element::Number)
1498 {
1499 currentElement.type = element::Number;
1500 currentElement.start = nextInputCh;
1501 }
1502 break;
1504 {
1505 json_value* newArray = buy_value(currentElement, json_array{});
1506 iCompositeValueStack.push_back(newArray);
1507 nextState = json_detail::state::Value;
1508 }
1509 break;
1511 {
1512 json_value* newObject = buy_value(currentElement, json_object{});
1513 iCompositeValueStack.push_back(newObject);
1514 }
1515 break;
1517 currentElement.type = element::Keyword;
1518 currentElement.start = (nextOutputCh = nextInputCh);
1519 break;
1521 if constexpr (syntax == json_syntax::Relaxed)
1522 {
1523 // relaxed: support for three different quote characters
1524 if (*nextInputCh != *(currentElement.start - 1))
1525 nextState = json_detail::state::String;
1526 }
1527 break;
1529 if (nextOutputCh == currentElement.start)
1530 nextOutputCh = (currentState != json_detail::state::EscapingUnicode ? nextInputCh - 1 : nextInputCh - 2);
1531 if (currentState == json_detail::state::Escaping)
1532 {
1533 switch (*(nextInputCh))
1534 {
1535 case '\"':
1536 (*nextOutputCh++) = '\"';
1537 break;
1538 case '\\':
1539 (*nextOutputCh++) = '\\';
1540 break;
1541 case '/':
1542 (*nextOutputCh++) = '/';
1543 break;
1544 case 'b':
1545 (*nextOutputCh++) = '\b';
1546 break;
1547 case 'f':
1548 (*nextOutputCh++) = '\f';
1549 break;
1550 case 'n':
1551 (*nextOutputCh++) = '\n';
1552 break;
1553 case 'r':
1554 (*nextOutputCh++) = '\r';
1555 break;
1556 case 't':
1557 (*nextOutputCh++) = '\t';
1558 break;
1559 default:
1560 break;
1561 }
1562 nextState = currentElement.type == element::String ? json_detail::state::String : json_detail::state::Name;
1563 }
1564 else if (currentState == json_detail::state::EscapingUnicode)
1565 {
1566 // todo throw an error if there are invalid surrogate pairs
1567 if (currentElement.auxType != element::EscapedUnicode)
1568 {
1569 currentElement.auxType = element::EscapedUnicode;
1570 currentElement.auxStart = nextInputCh;
1571 }
1572 if (nextInputCh + 1 - currentElement.auxStart == 4)
1573 {
1574 string_type s{ currentElement.auxStart, nextInputCh + 1 };
1575 char16_t u16ch = static_cast<char16_t>(std::stoul(s, nullptr, 16));
1576 if (utf16::is_high_surrogate(u16ch))
1577 {
1578 iUtf16HighSurrogate = u16ch;
1579 currentElement.auxType = element::Unknown;
1580 currentElement.type = element::String;
1581 nextState = json_detail::state::String;
1582 break;
1583 }
1584 else if (utf16::is_low_surrogate(u16ch) && iUtf16HighSurrogate != std::nullopt)
1585 {
1586 switch (encoding())
1587 {
1589 {
1590 char16_t surrogatePair[] = { *iUtf16HighSurrogate, u16ch };
1591 auto utf8 = utf16_to_utf8(std::u16string(&surrogatePair[0], 2));
1592 nextOutputCh = std::copy(utf8.begin(), utf8.end(), nextOutputCh);
1593 }
1594 break;
1597 (*nextOutputCh++) = static_cast<character_type>(*iUtf16HighSurrogate);
1598 (*nextOutputCh++) = static_cast<character_type>(u16ch);
1599 break;
1602 {
1603 char16_t surrogatePair[] = { *iUtf16HighSurrogate, u16ch };
1604 (*nextOutputCh++) = static_cast<character_type>(utf8_to_utf32(utf16_to_utf8(std::u16string{ &surrogatePair[0], 2 }))[0]);
1605 }
1606 break;
1607 default:
1608 break;
1609 }
1610 iUtf16HighSurrogate = std::nullopt;
1611 }
1612 else
1613 {
1614 switch (encoding())
1615 {
1617 {
1618 auto utf8 = utf16_to_utf8(std::u16string(1, u16ch));
1619 nextOutputCh = std::copy(utf8.begin(), utf8.end(), nextOutputCh);
1620 }
1621 break;
1624 *(nextOutputCh++) = static_cast<character_type>(u16ch);
1625 break;
1628 *(nextOutputCh++) = static_cast<character_type>(u16ch);
1629 break;
1630 default:
1631 break;
1632 }
1633 }
1634 currentElement.auxType = element::Unknown;
1635 nextState = json_detail::state::String;
1636 }
1637 else
1638 {
1640 }
1641 }
1642 break;
1643 default:
1644 break;
1645 }
1646 if (currentState != nextState)
1647 {
1648 if constexpr (json_detail::debug)
1649 std::cout << "(" << to_string(nextState) << ")";
1650 currentState = nextState;
1651 }
1652 }
1653 catch (std::exception& e)
1654 {
1655 create_parse_error(e.what());
1656 return false;
1657 }
1658 increment_cursor();
1659 }
1660
1661 return true;
1662 }
1663
1664 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1665 inline bool basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::write(const std::string& aPath, const string_type& aIndent)
1666 {
1667 std::ofstream output{ aPath, std::ofstream::out | std::ofstream::trunc };
1668 return write(output, aIndent);
1669 }
1670
1671 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1672 template <typename Elem, typename ElemTraits>
1673 inline bool basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::write(std::basic_ostream<Elem, ElemTraits>& aOutput, const string_type& aIndent)
1674 {
1675 static const string_type trueString = "true";
1676 static const string_type falseString = "false";
1677 static const string_type nullString = "null";
1678 int32_t level = 0;
1679 auto end = cend();
1680 auto indent = [&aOutput, &aIndent, &level]()
1681 {
1682 for (int32_t l = 0; l < level; ++l)
1683 aOutput << aIndent;
1684 };
1685 for (auto i = cbegin(); i != end; ++i)
1686 {
1687 auto const& v = **i;
1688 indent();
1689 if (i.value().has_name())
1690 {
1691 if (!i.value().name_is_keyword())
1692 aOutput << '\"' << i.value().name() << "\": ";
1693 else
1694 aOutput << i.value().name() << ": ";
1695 }
1696 switch (i.value().type())
1697 {
1698 case json_type::Object:
1699 aOutput << '{';
1700 if (i.value().is_populated_composite())
1701 {
1702 ++level;
1703 aOutput << std::endl;
1704 }
1705 else
1706 aOutput << '}';
1707 break;
1708 case json_type::Array:
1709 aOutput << '[';
1710 if (i.value().is_populated_composite())
1711 {
1712 ++level;
1713 aOutput << std::endl;
1714 }
1715 else
1716 aOutput << ']';
1717 break;
1718 case json_type::Double:
1719 aOutput << std::get<json_double>(v);
1720 break;
1721 case json_type::Int64:
1722 aOutput << std::get<json_int64>(v);
1723 break;
1724 case json_type::Uint64:
1725 aOutput << std::get<json_uint64>(v);
1726 break;
1727 case json_type::Int:
1728 aOutput << std::get<json_int>(v);
1729 break;
1730 case json_type::Uint:
1731 aOutput << std::get<json_uint>(v);
1732 break;
1733 case json_type::String:
1734 aOutput << '\"';
1735 for (auto const& ch : std::get<json_string>(v))
1736 switch (ch)
1737 {
1738 case '\"':
1739 aOutput << "\\\"";
1740 break;
1741 case '\\':
1742 aOutput << "\\\\";
1743 break;
1744 case '\b':
1745 aOutput << "\\b";
1746 break;
1747 case '\f':
1748 aOutput << "\\f";
1749 break;
1750 case '\n':
1751 aOutput << "\\n";
1752 break;
1753 case '\r':
1754 aOutput << "\\r";
1755 break;
1756 case '\t':
1757 aOutput << "\\t";
1758 break;
1759 default:
1760 if (static_cast<uint32_t>(ch) >= 32u)
1761 aOutput << ch;
1762 else
1763 aOutput << "\\u" << std::hex << std::setw(4) << std::setfill('0') << (int)ch;
1764 }
1765 aOutput << '\"';
1766 break;
1767 case json_type::Bool:
1768 aOutput << (std::get<json_bool>(v) ? trueString : falseString);
1769 break;
1770 case json_type::Null:
1771 aOutput << nullString;
1772 break;
1773 case json_type::Keyword:
1774 aOutput << std::get<json_keyword>(v).text;
1775 break;
1776 default:
1777 break;
1778 }
1779
1780 if (!i.value().is_composite() || i.value().is_empty_composite())
1781 {
1782 auto next = &i.value();
1783 bool needNewline = false;
1784 while (next->is_last_sibling() && next->has_parent())
1785 {
1786 --level;
1787 auto nextParent = &next->parent();
1788 if (nextParent->type() == json_type::Array)
1789 {
1790 aOutput << std::endl;
1791 indent();
1792 aOutput << ']';
1793 needNewline = true;
1794 }
1795 else if (nextParent->type() == json_type::Object)
1796 {
1797 aOutput << std::endl;
1798 indent();
1799 aOutput << '}';
1800 needNewline = true;
1801 }
1802 if (!nextParent->is_last_sibling())
1803 {
1804 aOutput << ',';
1805 needNewline = true;
1806 }
1807 next = nextParent;
1808 }
1809 if (needNewline && level > 0)
1810 aOutput << std::endl;
1811 }
1812 if (!i.value().is_last_sibling() && (!i.value().is_composite() || i.value().is_empty_composite()))
1813 aOutput << ',' << std::endl;
1814 }
1815 return true;
1816 }
1817
1818 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1820 {
1821 return iEncoding;
1822 }
1823
1824 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1829
1830 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1831 inline const typename basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::string_type& basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::error_text() const
1832 {
1833 return iErrorText;
1834 }
1835
1836 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1838 {
1839 return iRoot != std::nullopt;
1840 }
1841
1842 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1844 {
1845 if (iRoot == std::nullopt)
1846 iRoot.emplace();
1847 return *iRoot;
1848 }
1849
1850 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1855
1856 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1861
1862 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1864 {
1865 auto bitStart = aPath.begin();
1866 auto bitEnd = std::find(bitStart, aPath.end(), '.');
1867 json_value const* node = &root();
1868 if (bitEnd == bitStart)
1869 return *node;
1870 do
1871 {
1872 auto existing = std::find_if(node->begin(), node->end(), [&](auto&& child) { return child.name() == std::string_view{ &*bitStart, static_cast<std::string_view::size_type>(std::distance(bitStart, bitEnd)) }; });
1873 if (existing == node->end())
1874 throw json_path_not_found(aPath.to_std_string());
1875 node = &*existing;
1876 bitStart = (bitEnd != aPath.end() ? std::next(bitEnd) : bitEnd);
1877 bitEnd = std::find(bitStart, aPath.end(), '.');
1878 } while (bitStart != aPath.end());
1879 return *node;
1880 }
1881
1882 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1887
1888 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1889 template <typename Visitor>
1891 {
1892 if (has_root())
1893 root().visit(std::forward<Visitor>(aVisitor));
1894 }
1895
1896 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1897 template <typename Visitor>
1899 {
1900 if (has_root())
1901 root().visit(std::forward<Visitor>(aVisitor));
1902 }
1903
1904 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1909
1910 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1915
1916 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1918 {
1919 if (iRoot != std::nullopt)
1920 return const_iterator{ &*iRoot };
1921 return const_iterator{};
1922 }
1923
1924 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1929
1930 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1932 {
1933 if (iRoot != std::nullopt)
1934 return iterator{ &*iRoot };
1935 return iterator{};
1936 }
1937
1938 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1943
1944 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1945 typename basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::string_type basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::to_error_text(const json_document_source_location& aDocumentSourceLocation, const string_type& aExtraInfo)
1946 {
1947 string_type text;
1948 if (!aExtraInfo.empty())
1949 {
1950 text += "(";
1951 text += aExtraInfo;
1952 text += ") ";
1953 }
1954 text += "line " + boost::lexical_cast<string_type>(aDocumentSourceLocation.line) + ", col " + boost::lexical_cast<string_type>(aDocumentSourceLocation.column);
1955 return text;
1956 }
1957
1958 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1959 typename basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::string_type basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::to_error_text(const json_value& aNode, const string_type& aExtraInfo)
1960 {
1961 return to_error_text(aNode.document_source_location(), aExtraInfo);
1962 }
1963
1964 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1965 typename basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::string_type basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::to_error_text(const string_type& aExtraInfo) const
1966 {
1967 return to_error_text(iCursor, aExtraInfo);
1968 }
1969
1970 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1971 inline typename basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::json_string& basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::document()
1972 {
1973 return iDocumentText;
1974 }
1975
1976 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1977 inline json_type basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::context() const
1978 {
1979 if (!iCompositeValueStack.empty())
1980 return iCompositeValueStack.back()->type();
1981 return json_type::Unknown;
1982 }
1983
1984 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
1985 template <typename T>
1986 inline typename basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::json_value* basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::buy_value(element& aCurrentElement, T&& aValue)
1987 {
1988 switch (context())
1989 {
1990 case json_type::Array:
1991 {
1992 auto newObject = iCompositeValueStack.back()->buy_child(std::forward<T>(aValue));
1993 newObject->set_document_source_location(iCursor);
1994 if constexpr(std::is_same_v<typename std::remove_cv<typename std::remove_reference<T>::type>::type, json_array>)
1995 newObject->template as<json_array>().set_contents(*newObject);
1996 else if constexpr(std::is_same_v<typename std::remove_cv<typename std::remove_reference<T>::type>::type, json_object>)
1997 newObject->template as<json_object>().set_contents(*newObject);
1998 return newObject;
1999 }
2000 case json_type::Object:
2001 {
2002 auto newObject = iCompositeValueStack.back()->buy_child(std::forward<T>(aValue));
2003 newObject->set_document_source_location(iCursor);
2004 if constexpr(std::is_same_v<typename std::remove_cv<typename std::remove_reference<T>::type>::type, json_array>)
2005 newObject->template as<json_array>().set_contents(*newObject);
2006 else if constexpr(std::is_same_v<typename std::remove_cv<typename std::remove_reference<T>::type>::type, json_object>)
2007 newObject->template as<json_object>().set_contents(*newObject);
2008 if (std::holds_alternative<json_string>(aCurrentElement.name))
2009 newObject->set_name(std::get<json_string>(aCurrentElement.name));
2010 else
2011 newObject->set_name(std::get<json_keyword>(aCurrentElement.name));
2012 aCurrentElement.name = std::monostate{};
2013 return newObject;
2014 }
2015 default:
2016 root() = std::forward<T>(aValue);
2017 root().set_document_source_location(iCursor);
2018 return &root();
2019 }
2020 }
2021
2022 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
2023 inline void basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>::create_parse_error(const string_type& aExtraInfo) const
2024 {
2025 iErrorText = to_error_text(aExtraInfo);
2026 }
2027}
2028
bool operator!=(const const_iterator &aRhs) const
Definition json.inl:1078
const_iterator operator++(int)
Definition json.inl:1056
const_iterator operator--(int)
Definition json.inl:1067
const_iterator & operator++()
Definition json.inl:1051
bool operator==(const const_iterator &aRhs) const
Definition json.inl:1074
const_iterator & operator--()
Definition json.inl:1062
const_iterator(const iterator &aOther)
Definition json.inl:1040
const_iterator(const const_iterator &aOther)
Definition json.inl:1037
bool operator!=(const iterator &aRhs) const
Definition json.inl:1012
bool operator==(const iterator &aRhs) const
Definition json.inl:1008
iterator operator++(int)
Definition json.inl:990
iterator(const iterator &aOther)
Definition json.inl:974
const_iterator(const iterator &aOther)
Definition json.inl:833
bool operator!=(const const_iterator &aRhs) const
Definition json.inl:871
bool operator==(const const_iterator &aRhs) const
Definition json.inl:867
const_iterator(const const_iterator &aOther)
Definition json.inl:830
iterator(const iterator &aOther)
Definition json.inl:767
bool operator!=(const iterator &aRhs) const
Definition json.inl:805
bool operator==(const iterator &aRhs) const
Definition json.inl:801
const_reference parent() const
Definition json.hpp:718
const_iterator begin() const
Definition json.hpp:775
const_iterator end() const
Definition json.hpp:779
void push_back(T &&aValue)
Definition json.hpp:859
const json_document_source_location & document_source_location() const
Definition json.hpp:868
const value_type & operator*() const
Definition json.hpp:640
bool has_parent() const
Definition json.hpp:714
self_type & reference
Definition json.hpp:564
self_type * pointer
Definition json.hpp:562
bool write(const std::string &aPath, const string_type &aIndent=string_type(2, character_type{' '}))
Definition json.inl:1665
void visit(Visitor &&aVisitor) const
Definition json.inl:1890
value_type * pointer
Definition json.hpp:921
json_encoding encoding() const
Definition json.inl:1819
const json_string & document() const
Definition json.inl:1825
bool has_root() const
Definition json.inl:1837
bool read(const std::string &aPath, bool aValidateUtf=false)
Definition json.inl:1126
const json_value & root() const
Definition json.inl:1851
value_type & reference
Definition json.hpp:923
const json_value & croot() const
Definition json.inl:1843
const json_value & at(const json_string &aPath) const
Definition json.inl:1863
const string_type & error_text() const
Definition json.inl:1831
string_type::size_type size_type
string_type to_std_string() const
bool operator!=(color_or_gradient const &lhs, color const &rhs) noexcept
std::string to_string(note const &aNote)
bool operator==(const basic_rect< CoordinateType, CoordinateSystem > &left, const basic_rect< CoordinateType, CoordinateSystem > &right)
constexpr token TMIN
Definition json.inl:112
constexpr std::size_t STATE_COUNT
Definition json.inl:158
constexpr token TCOL
Definition json.inl:104
constexpr token TCOM
Definition json.inl:105
constexpr state SNU7
Definition json.inl:182
constexpr token TECH
Definition json.inl:110
constexpr state SOBJ
Definition json.inl:163
constexpr token TESC
Definition json.inl:108
constexpr state SZZZ
Definition json.inl:161
constexpr state SNU3
Definition json.inl:178
constexpr token TEHX
Definition json.inl:115
constexpr token THEX
Definition json.inl:114
constexpr state SNU4
Definition json.inl:179
constexpr std::array< state, TOKEN_COUNT > need_value_state()
Definition json.inl:279
constexpr state SKEY
Definition json.inl:171
constexpr token TSYM
Definition json.inl:120
constexpr std::array< std::array< state, TOKEN_COUNT >, STATE_COUNT > sStateTables
Definition json.inl:381
constexpr state SOVS
Definition json.inl:169
constexpr token TEXP
Definition json.inl:117
constexpr state SELE
Definition json.inl:162
constexpr state SIGN
Definition json.inl:160
constexpr state SSTR
Definition json.inl:174
constexpr state SVAL
Definition json.inl:166
constexpr std::array< state, TOKEN_COUNT > value_state()
Definition json.inl:325
constexpr token TWSP
Definition json.inl:122
constexpr state SNVA
Definition json.inl:168
constexpr state SESC
Definition json.inl:183
constexpr std::size_t TOKEN_COUNT
Definition json.inl:98
state next_state(state aCurrentState, CharT aCharacter)
Definition json.inl:591
constexpr token TESU
Definition json.inl:109
constexpr state SNU1
Definition json.inl:176
constexpr token TOBJ
Definition json.inl:100
constexpr state SNAM
Definition json.inl:172
constexpr state SSEN
Definition json.inl:175
constexpr state SCLO
Definition json.inl:165
constexpr token TCLO
Definition json.inl:101
constexpr token TZZZ
Definition json.inl:123
constexpr state SEUN
Definition json.inl:185
constexpr token TPLU
Definition json.inl:111
constexpr state SCM1
Definition json.inl:186
constexpr state SNU2
Definition json.inl:177
constexpr bool debug
Definition json.inl:60
constexpr token TAST
Definition json.inl:118
constexpr state SXXX
Definition json.inl:159
constexpr state SARR
Definition json.inl:164
constexpr state SESD
Definition json.inl:184
constexpr state SENM
Definition json.inl:173
constexpr std::array< state, TOKEN_COUNT > keyword_state()
Definition json.inl:348
constexpr token TFWD
Definition json.inl:119
constexpr state SNU5
Definition json.inl:180
constexpr token TCLA
Definition json.inl:103
constexpr token TCHA
Definition json.inl:107
constexpr std::array< state, TOKEN_COUNT > object_state()
Definition json.inl:256
constexpr token TARR
Definition json.inl:102
constexpr state SNOV
Definition json.inl:170
constexpr std::array< state, TOKEN_COUNT > need_object_value_state()
Definition json.inl:302
constexpr token TXXX
Definition json.inl:99
constexpr token TSPA
Definition json.inl:121
constexpr state SNVS
Definition json.inl:167
constexpr state SNU6
Definition json.inl:181
token to_token(const std::array< token, 256 > &aTokenTable, CharT aCharacter)
Definition json.inl:584
constexpr token TDIG
Definition json.inl:113
constexpr state SCM2
Definition json.inl:187
constexpr token TQOT
Definition json.inl:106
constexpr std::array< token, 256 > sTokenTable
Definition json.inl:516
constexpr token TDEC
Definition json.inl:116
basic_vector< T, D, Type > operator*(const basic_vector< T, D, Type > &left, const T &right)
bool is_low_surrogate(unicode_char_t aCharacter)
bool is_high_surrogate(unicode_char_t aCharacter)
json::json_array json_array
Definition json.hpp:1011
bool check_utf8(const std::basic_string_view< CharT, Traits > &aString)
constexpr const char * document_type()
Definition json.inl:1115
json::json_string json_string
Definition json.hpp:1017
number_t string_to_number(const std::basic_string_view< CharT, Traits > &aStringView)
json::json_bool json_bool
Definition json.hpp:1018
std::string utf16_to_utf8(const std::u16string &aString, CharacterMapUpdater aCharacterMapUpdater)
json::json_null json_null
Definition json.hpp:1019
json::json_object json_object
Definition json.hpp:1010
std::u32string utf8_to_utf32(std::string_view const &aStringView, Callback aCallback, bool aCodePageFallback=false)
json_type
Definition json.hpp:94
json_encoding
Definition json.hpp:73
to_const_reference_t< T > to_const(T &&object)
Definition neolib.hpp:113
json::json_value json_value
Definition json.hpp:1009
json::json_keyword json_keyword
Definition json.hpp:1020
double string_to_double(const std::basic_string_view< CharT, Traits > &aStringView)
it_type next(it_type it, const typename iterator_traits< it_type >::difference_type distance=1)
Definition plf_hive.h:89
constexpr decltype(auto) visit(Visitor &&vis, neolib::variant< Types... > &&var)
Definition variant.hpp:60
std::bidirectional_iterator_tag iterator_category
Definition json.inl:667
neolib::basic_json< Syntax, Alloc, CharT, Traits, CharAlloc > document_type
Definition json.inl:673
neolib::basic_json_value< Syntax, Alloc, CharT, Traits, CharAlloc > value_type
Definition json.inl:668
std::size_t operator()(const String &aString) const noexcept
Definition json.inl:643
neolib::basic_json< Syntax, Alloc, CharT, Traits, CharAlloc > document_type
Definition json.inl:661
std::bidirectional_iterator_tag iterator_category
Definition json.inl:655
neolib::basic_json_value< Syntax, Alloc, CharT, Traits, CharAlloc > value_type
Definition json.inl:656