neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
json.hpp
Go to the documentation of this file.
1// json.hpp
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 <cstddef>
42#include <list>
43#include <string>
44#include <unordered_map>
45#include <vector>
46#include <type_traits>
47#include <istream>
48#include <ostream>
49#include <utility>
50#include <memory>
51#include <exception>
52#include <optional>
53#include <variant>
54#include <boost/functional/hash.hpp>
57
58namespace neolib
59{
60 struct json_error : std::runtime_error { json_error(const std::string& aReason) : std::runtime_error{ aReason } {} };
61 struct json_path_not_found : std::runtime_error { json_path_not_found(const std::string& aPath) : std::runtime_error{ "JSON path not found: " + aPath } {} };
62 struct json_no_owning_node : std::logic_error { json_no_owning_node() : std::logic_error{ "JSON no owning node" } {} };
63
64 enum class json_syntax
65 {
68 Relaxed,
70 };
71
72 enum class json_encoding
73 {
74 Utf8,
75 Utf16LE,
76 Utf16BE,
77 Utf32LE,
79 };
80
81 namespace json_detail
82 {
83 template <std::size_t CharSize>
85 template <> struct default_encoding_helper<1> { static const json_encoding DEFAULT_ENCODING = json_encoding::Utf8; };
86 template <> struct default_encoding_helper<2> { static const json_encoding DEFAULT_ENCODING = json_encoding::Utf16LE; };
87 template <> struct default_encoding_helper<4> { static const json_encoding DEFAULT_ENCODING = json_encoding::Utf32LE; };
88
89 template <typename CharT>
91 }
92
93 enum class json_type
94 {
95 Unknown,
96 Object,
97 Array,
98 Double,
99 Int64,
100 Uint64,
101 Int,
102 Uint,
103 String,
104 Bool,
105 Null,
106 Keyword
107 };
108
109 inline std::string to_string(json_type aType)
110 {
111 switch (aType)
112 {
113 default:
115 return "Unknown";
117 return "Object";
118 case json_type::Array:
119 return "Array";
121 return "Double";
122 case json_type::Int64:
123 return "Int64";
125 return "Uint64";
126 case json_type::Int:
127 return "Int";
128 case json_type::Uint:
129 return "Uint";
131 return "String";
132 case json_type::Bool:
133 return "Bool";
134 case json_type::Null:
135 return "Null";
137 return "Keyword";
138 }
139 }
140
142 {
143 uint32_t line;
144 uint32_t column;
145 };
146
147 namespace json_detail
148 {
149 template <typename T>
151 {
152 typedef basic_json_node<T> self_type;
153 template <json_syntax Syntax, typename Alloc , typename CharT, typename Traits, typename CharAlloc>
154 friend class basic_json_value;
155 public:
156 typedef T json_value;
158 private:
159 typedef typename json_value::value_allocator value_allocator;
160 public:
162 iParent{ nullptr },
163 iPrevious{ nullptr },
164 iNext{ nullptr },
165 iFirstChild{ nullptr },
166 iLastChild{ nullptr }
167 {
168 }
170 iParent{ &aParent },
171 iPrevious{ nullptr },
172 iNext{ nullptr },
173 iFirstChild{ nullptr },
174 iLastChild{ nullptr }
175 {
176 }
178 {
179 while (iLastChild != nullptr)
180 destruct_child(iLastChild);
181 }
182 public:
183 json_value* buy_child(json_value& aParent, const value_type& aValue)
184 {
185 return construct_child(allocate_child(), aParent, aValue);
186 }
188 {
189 return construct_child(allocate_child(), aParent, std::move(aValue));
190 }
191 public:
192 bool has_parent() const
193 {
194 return iParent != nullptr;
195 }
196 const json_value* parent() const
197 {
198 return iParent;
199 }
201 {
202 return iParent;
203 }
204 bool has_children() const
205 {
206 return iFirstChild != nullptr;
207 }
208 const json_value* first_child() const
209 {
210 return iFirstChild;
211 }
213 {
214 return iFirstChild;
215 }
216 const json_value* last_child() const
217 {
218 return iLastChild;
219 }
221 {
222 return iLastChild;
223 }
224 bool is_last_sibling() const
225 {
226 return iNext == nullptr;
227 }
229 {
230 return iNext;
231 }
233 {
234 return iNext;
235 }
237 {
238 auto tryParent = iParent;
239 if (tryParent == nullptr)
240 return nullptr;
241 while (tryParent->has_parent() && tryParent->is_last_sibling())
242 tryParent = &tryParent->parent();
243 return tryParent->next_sibling();
244 }
246 {
247 return const_cast<json_value*>(to_const(*this).next_parent_sibling());
248 }
249 private:
250 json_value* allocate_child()
251 {
252 return std::allocator_traits<value_allocator>::allocate(allocator(), 1);
253 }
254 void deallocate_child(json_value* aAddress)
255 {
256 std::allocator_traits<value_allocator>::deallocate(allocator(), aAddress, 1);
257 }
258 template <typename... Args>
259 json_value* construct_child(json_value* aAddress, json_value& aParent, Args&&... aArguments)
260 {
261 std::allocator_traits<value_allocator>::construct(allocator(), aAddress, aParent, std::forward<Args>(aArguments)...);
262 json_value& child = *aAddress;
263 if (iLastChild == nullptr)
264 {
265 iFirstChild = &child;
266 iLastChild = &child;
267 }
268 else
269 {
270 iLastChild->iNode.iNext = &child;
271 child.iNode.iPrevious = iLastChild;
272 iLastChild = &child;
273 }
274 return &child;
275 }
276 void destruct_child(json_value* aAddress)
277 {
278 json_value& child = *aAddress;
279 if (child.iNode.iPrevious != nullptr)
280 child.iNode.iPrevious->iNode.iNext = child.iNode.iNext;
281 if (child.iNode.iNext != nullptr)
282 child.iNode.iNext->iNode.iPrevious = child.iNode.iPrevious;
283 if (iLastChild == &child)
284 iLastChild = child.iNode.iPrevious;
285 if (iFirstChild == &child)
286 iFirstChild = child.iNode.iNext;
287 child.~json_value();
288 deallocate_child(aAddress);
289 }
290 private:
291 static value_allocator& allocator()
292 {
293 static value_allocator sAllocator;
294 return sAllocator;
295 }
296 json_value* iParent;
297 json_value* iPrevious;
298 json_value* iNext;
299 json_value* iFirstChild;
300 json_value* iLastChild;
301 };
302 }
303
304 template <typename T>
306 {
307 typedef basic_json_object<T> self_type;
308 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
309 friend class basic_json;
310 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
311 friend class basic_json_value;
312 public:
313 typedef T json_value;
316 private:
317 typedef typename json_value::value_allocator allocator_type;
318 typedef std::unordered_multimap<
320 json_value*,
321 boost::hash<json_string>,
322 std::equal_to<json_string>,
323 typename std::allocator_traits<allocator_type>::template rebind_alloc<std::pair<const json_string, json_value*>>> dictionary_type;
324 public:
326 iContents{ nullptr }
327 {
328 }
330 iContents{ &aOwner }
331 {
332 }
333 public:
334 bool has(const json_string& aKey) const
335 {
336 return cache().find(aKey) != cache().end();
337 }
338 const json_value& at(const json_string& aKey) const
339 {
340 auto existing = cache().find(aKey);
341 if (existing != cache().end())
342 return *existing->second;
343 throw std::out_of_range("neolib::basic_json_object::at: key not found");
344 }
346 {
347 return const_cast<json_value&>(to_const(*this).at(aKey));
348 }
349 template <typename U>
350 std::enable_if_t<!std::is_arithmetic_v<U>, const U&> at_or(const json_string& aKey, const U& aDefault) const
351 {
352 if (has(aKey))
353 return at(aKey).template as<U>();
354 return aDefault;
355 }
356 template <typename U>
357 std::enable_if_t<!std::is_arithmetic_v<U>, U&> at_or(const json_string& aKey, U& aDefault)
358 {
359 if (has(aKey))
360 return at(aKey).template as<U>();
361 return aDefault;
362 }
363 template <typename U>
364 std::enable_if_t<std::is_arithmetic_v<U>, U> at_or(const json_string& aKey, const U& aDefault) const
365 {
366 if (has(aKey))
367 return at(aKey).template as<U>();
368 return aDefault;
369 }
370 template <typename U>
371 std::enable_if_t<std::is_arithmetic_v<U>, U&> at_or(const json_string& aKey, U& aDefault)
372 {
373 if (has(aKey))
374 return at(aKey).template as<U>();
375 return aDefault;
376 }
378 {
379 auto existing = cache().find(aKey);
380 if (existing != cache().end())
381 return *existing->second;
382 auto& newChild = contents().emplace_back(value_type{});
383 newChild.set_name(aKey.to_std_string());
384 cache().emplace(newChild.name(), &newChild);
385 return newChild;
386 }
387 public:
389 {
390 if (iContents == nullptr)
391 throw json_no_owning_node();
392 return *iContents;
393 }
395 {
396 iContents = &aOwner;
397 }
398 private:
399 const dictionary_type& cache() const
400 {
401 if (iLazyDictionary != nullptr)
402 return *iLazyDictionary;
403 iLazyDictionary = std::make_unique<dictionary_type>(); // todo: use allocator_type
404 for (auto i = contents().begin(); i != contents().end(); ++i)
405 iLazyDictionary->emplace(i.value().name(), &i.value());
406 return *iLazyDictionary;
407 }
408 dictionary_type& cache()
409 {
410 return const_cast<dictionary_type&>(to_const(*this).cache());
411 }
412 private:
413 json_value* iContents;
414 mutable std::unique_ptr<dictionary_type> iLazyDictionary;
415 };
416
417 template <typename T>
419 {
420 typedef basic_json_array<T> self_type;
421 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
422 friend class basic_json;
423 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
424 friend class basic_json_value;
425 public:
426 typedef T json_value;
429 private:
430 typedef typename json_value::value_allocator allocator_type;
431 typedef std::vector<json_value*> array_type;
432 public:
434 iContents{ nullptr }
435 {
436 }
438 iContents{ &aOwner }
439 {
440 }
441 public:
442 typename array_type::const_iterator cbegin() const
443 {
444 return cache().begin();
445 }
446 typename array_type::const_iterator cend() const
447 {
448 return cache().end();
449 }
450 typename array_type::const_iterator begin() const
451 {
452 return cache().begin();
453 }
454 typename array_type::const_iterator end() const
455 {
456 return cache().end();
457 }
458 typename array_type::iterator begin()
459 {
460 return cache().begin();
461 }
462 typename array_type::iterator end()
463 {
464 return cache().end();
465 }
466 public:
468 {
469 auto& newChild = contents().emplace_back(aValue);
470 cache().emplace_back(&newChild);
471 return back();
472 }
474 {
475 auto& newChild = contents().emplace_back(std::move(aValue));
476 cache().emplace_back(&newChild);
477 return back();
478 }
480 {
481 return *cache().back();
482 }
483 json_value& operator[](std::size_t aIndex)
484 {
485 return *cache().at(aIndex);
486 }
487 public:
489 {
490 if (iContents == nullptr)
491 throw json_no_owning_node();
492 return *iContents;
493 }
495 {
496 iContents = &aOwner;
497 }
498 private:
499 const array_type& cache() const
500 {
501 if (iLazyArray != nullptr)
502 return *iLazyArray;
503 iLazyArray = std::make_unique<array_type>(); // todo: use allocator_type
504 for (auto& e : contents())
505 iLazyArray->emplace_back(&e);
506 return *iLazyArray;
507 }
508 array_type& cache()
509 {
510 return const_cast<array_type&>(to_const(*this).cache());
511 }
512 private:
513 json_value* iContents;
514 mutable std::unique_ptr<array_type> iLazyArray;
515 };
516
517 template <typename T>
519 {
520 public:
521 typedef T json_value;
523 public:
525 };
526
527 template <typename T>
529 {
530 public:
531 typedef T json_value;
532 public:
533 bool operator==(std::nullptr_t) const { return true; }
534 bool operator!=(std::nullptr_t) const { return false; }
535 };
536
537 template <json_syntax Syntax = json_syntax::Standard, typename Alloc = std::allocator<json_type>, typename CharT = char, typename Traits = std::char_traits<CharT>, typename CharAlloc = std::allocator<CharT>>
538 class basic_json;
539
540 template <json_syntax Syntax = json_syntax::Standard, typename Alloc = std::allocator<json_type>, typename CharT = char, typename Traits = std::char_traits<CharT>, typename CharAlloc = std::allocator<CharT>>
542 {
544 friend class basic_json<Syntax, Alloc, CharT, Traits, CharAlloc>;
545 template <typename T>
547 public:
548 struct no_name : std::logic_error { no_name() : std::logic_error("neolib::basic_json_value::no_name") {} };
549 struct bad_conversion : std::runtime_error { bad_conversion() : std::runtime_error("neolib::basic_json_value::bad_conversion") {} };
550 public:
551 static constexpr json_syntax syntax = Syntax;
552 typedef Alloc allocator_type;
553 typedef CharT character_type;
554 typedef Traits character_traits_type;
555 typedef CharAlloc character_allocator_type;
556 public:
558 public:
559 typedef typename std::allocator_traits<allocator_type>::template rebind_alloc<self_type> value_allocator;
560 public:
561 typedef const self_type* const_pointer;
565 private:
566 template <typename IteratorTraits>
567 class iterator_base;
568 public:
569 class const_iterator;
570 class iterator;
571 public:
575 typedef double json_double;
576 typedef int64_t json_int64;
577 typedef uint64_t json_uint64;
578 typedef int32_t json_int;
579 typedef uint32_t json_uint;
580 typedef bool json_bool;
583 public:
584 typedef std::variant<std::monostate, json_string, json_keyword> name_t;
585 public:
586 typedef std::optional<json_string> optional_json_string;
587 public:
588 typedef std::variant<std::monostate, json_object, json_array, json_double, json_int64, json_uint64, json_int, json_uint, json_string, json_bool, json_null, json_keyword> value_type;
589 private:
591 public:
593 iNode{}, iValue{}, iDocumentSourceLocation{}
594 {
595 }
596 basic_json_value(reference aParent, const value_type& aValue) :
597 iNode{ aParent }, iValue{ aValue }, iDocumentSourceLocation{}
598 {
599 update_contents();
600 }
602 iNode{ aParent }, iValue{ std::move(aValue) }, iDocumentSourceLocation{}
603 {
604 update_contents();
605 }
606 public:
609 public:
610 template <typename T>
611 std::enable_if_t<!std::is_arithmetic_v<T>, const T&> as() const
612 {
613 return std::get<T>(iValue);
614 }
615 template <typename T>
616 std::enable_if_t<!std::is_arithmetic_v<T>, T&> as()
617 {
618 return std::get<T>(iValue);
619 }
620 template <typename T>
621 std::enable_if_t<std::is_arithmetic_v<T>, T> as() const
622 {
623 T result = {};
624 std::visit([&result](auto&& v)
625 {
626 using Lhs = std::decay_t<T>;
627 using Rhs = std::decay_t<decltype(v)>;
628 if constexpr (std::is_convertible_v<Lhs, Rhs>)
629 result = static_cast<T>(v);
630 else
631 throw bad_conversion();
632 }, iValue);
633 return result;
634 }
635 template <typename T>
636 std::enable_if_t<std::is_arithmetic_v<T>, T&> as()
637 {
638 return std::get<T>(iValue);
639 }
640 const value_type& operator*() const
641 {
642 return iValue;
643 }
645 {
646 return iValue;
647 }
649 {
650 clear();
651 iValue = aValue;
652 update_contents();
653 return *this;
654 }
656 {
657 clear();
658 iValue = std::move(aValue);
659 update_contents();
660 return *this;
661 }
662 public:
664 {
665 return static_cast<json_type>(iValue.index());
666 }
667 bool is_composite() const
668 {
669 return type() == json_type::Object || type() == json_type::Array;
670 }
672 {
673 return is_composite() && !iNode.has_children();
674 }
676 {
677 return is_composite() && iNode.has_children();
678 }
679 const json_string& text() const
680 {
681 if (type() != json_type::Keyword)
682 return as<json_string>();
683 else
684 return as<json_keyword>().text;
685 }
686 bool has_name() const
687 {
688 return !std::holds_alternative<std::monostate>(iName);
689 }
690 bool name_is_keyword() const
691 {
692 return std::holds_alternative<json_keyword>(iName);
693 }
694 const json_string& name() const
695 {
696 if (!name_is_keyword())
697 return std::get<json_string>(iName);
698 else
699 return std::get<json_keyword>(iName).text;
700 }
701 void set_name(const json_string& aName)
702 {
703 iName = aName;
704 }
705 void set_name(const json_keyword& aName)
706 {
707 iName = aName;
708 }
709 public:
710 bool is_root() const
711 {
712 return !has_parent();
713 }
714 bool has_parent() const
715 {
716 return iNode.has_parent();
717 }
719 {
720 return *iNode.parent();
721 }
723 {
724 return *iNode.parent();
725 }
726 bool has_children() const
727 {
728 return iNode.has_children();
729 }
731 {
732 return iNode.first_child();
733 }
735 {
736 return iNode.first_child();
737 }
739 {
740 return iNode.last_child();
741 }
743 {
744 return iNode.last_child();
745 }
746 bool is_last_sibling() const
747 {
748 return iNode.is_last_sibling();
749 }
751 {
752 return iNode.next_sibling();
753 }
755 {
756 return iNode.next_sibling();
757 }
759 {
760 return iNode.next_parent_sibling();
761 }
763 {
764 return iNode.next_parent_sibling();
765 }
766 public:
768 {
769 return begin();
770 }
772 {
773 return end();
774 }
776 {
777 return first_child();
778 }
780 {
781 return nullptr;
782 }
784 {
785 return first_child();
786 }
788 {
789 return nullptr;
790 }
791 public:
792 template <typename Visitor>
793 void visit(Visitor&& aVisitor, bool aRecurse = true) const
794 {
795 std::visit([&aVisitor](auto&& arg)
796 {
797 if constexpr(!std::is_same_v<typename std::remove_cv<typename std::remove_reference<decltype(arg)>::type>::type, std::monostate>)
798 aVisitor(std::forward<decltype(arg)>(arg));
799 }, iValue);
800 switch (type())
801 {
803 case json_type::Array:
804 if (aRecurse)
805 for (auto& v : *this)
806 v.visit(std::forward<Visitor>(aVisitor));
807 break;
808 }
809 }
810 template <typename Visitor>
811 void visit(Visitor&& aVisitor, bool aRecurse = true)
812 {
813 std::visit([&aVisitor](auto&& arg)
814 {
815 if constexpr(!std::is_same_v<typename std::remove_cv<typename std::remove_reference<decltype(arg)>::type>::type, std::monostate>)
816 aVisitor(std::forward<decltype(arg)>(arg));
817 }, iValue);
818 switch (type())
819 {
821 case json_type::Array:
822 if (aRecurse)
823 for (auto i = begin(); i != end(); ++i)
824 i.value().visit(std::forward<Visitor>(aVisitor));
825 break;
826 default:
827 break;
828 }
829 }
830 public:
831 bool empty() const
832 {
833 return begin() == end();
834 }
835 std::size_t size() const
836 {
837 return std::distance(begin(), end()); // todo: this is O(n); have a size member instead for O(1)?
838 }
839 void clear()
840 {
841 if (has_parent())
842 {
843 auto& p = parent();
844 iNode.~node_type();
845 new(&iNode) node_type{ p };
846 }
847 else
848 {
849 iNode.~node_type();
850 new(&iNode) node_type{};
851 }
852 }
853 template <typename... Args>
854 reference emplace_back(Args&&... aArguments)
855 {
856 return *buy_child(std::forward<Args>(aArguments)...);
857 }
858 template <typename T>
859 void push_back(T&& aValue)
860 {
861 buy_child(std::forward<T>(aValue));
862 }
863 void pop_back()
864 {
865 iNode.destruct_child(last_child());
866 }
867 public:
869 {
870 return iDocumentSourceLocation;
871 }
873 {
874 iDocumentSourceLocation = aDocumentSourceLocation;
875 }
876 private:
877 template <typename... Args>
878 pointer buy_child(Args&&... aArguments)
879 {
880 return iNode.buy_child(*this, std::forward<Args>(aArguments)...);
881 }
882 void update_contents()
883 {
884 if (type() == json_type::Object)
885 std::get<json_object>(iValue).set_contents(*this);
886 else if (type() == json_type::Array)
887 std::get<json_array>(iValue).set_contents(*this);
888 }
889 private:
890 node_type iNode;
891 name_t iName;
892 value_type iValue;
893 json_document_source_location iDocumentSourceLocation;
894 };
895
896 template <json_syntax Syntax, typename Alloc, typename CharT, typename Traits, typename CharAlloc>
898 {
900 public:
901 static constexpr json_syntax syntax = Syntax;
902 typedef Alloc allocator_type;
903 typedef CharT character_type;
904 typedef Traits character_traits_type;
905 typedef CharAlloc character_allocator_type;
907 typedef std::optional<json_value> optional_json_value;
919 public:
922 typedef const value_type* const_pointer;
925 private:
926 template <typename IteratorTraits>
927 class iterator_base;
928 public:
929 class const_iterator;
930 class iterator;
931 private:
932 typedef std::basic_string<CharT, Traits, CharAlloc> string_type;
933 struct element
934 {
935 enum type_e
936 {
937 Unknown,
938 String,
939 Number,
940 Keyword,
941 EscapedUnicode,
942 Name
943 };
944 type_e type;
945 type_e auxType;
946 character_type* start;
947 character_type* auxStart;
948 typename json_value::name_t name;
949 };
950 public:
951 basic_json();
952 basic_json(const std::string& aPath, bool aValidateUtf = false);
953 template <typename Elem, typename ElemTraits>
954 basic_json(std::basic_istream<Elem, ElemTraits>& aInput, bool aValidateUtf = false);
955 public:
956 void clear();
957 bool read(const std::string& aPath, bool aValidateUtf = false);
958 template <typename Elem, typename ElemTraits>
959 bool read(std::basic_istream<Elem, ElemTraits>& aInput, bool aValidateUtf = false);
960 bool write(const std::string& aPath, const string_type& aIndent = string_type(2, character_type{' '}));
961 template <typename Elem, typename ElemTraits>
962 bool write(std::basic_ostream<Elem, ElemTraits>& aOutput, const string_type& aIndent = string_type(2, character_type{' '}));
963 public:
964 json_encoding encoding() const;
965 const json_string& document() const;
966 const string_type& error_text() const;
967 public:
968 bool has_root() const;
969 const json_value& croot() const;
970 const json_value& root() const;
971 json_value& root();
972 const json_value& at(const json_string& aPath) const;
973 json_value& at(const json_string& aPath);
974 template <typename Visitor>
975 void visit(Visitor&& aVisitor) const;
976 template <typename Visitor>
977 void visit(Visitor&& aVisitor);
978 const_iterator cbegin() const;
979 const_iterator cend() const;
980 const_iterator begin() const;
981 const_iterator end() const;
982 iterator begin();
983 iterator end();
984 public:
985 static string_type to_error_text(const json_document_source_location& aDocumentSourceLocation, const string_type& aExtraInfo = {});
986 static string_type to_error_text(const json_value& aNode, const string_type& aExtraInfo = {});
987 private:
989 string_type to_error_text(const string_type& aExtraInfo = {}) const;
990 private:
991 template <typename Elem, typename ElemTraits>
992 bool do_read(std::basic_istream<Elem, ElemTraits>& aInput, bool aValidateUtf = false);
993 bool do_parse();
994 json_type context() const;
995 template <typename T>
996 json_value* buy_value(element& aCurrentElement, T&& aValue);
997 void create_parse_error(const string_type& aExtraInfo = {}) const;
998 private:
999 json_encoding iEncoding;
1000 json_string iDocumentText;
1001 json_document_source_location iCursor;
1002 mutable string_type iErrorText;
1003 mutable optional_json_value iRoot;
1004 std::vector<json_value*> iCompositeValueStack;
1005 std::optional<char16_t> iUtf16HighSurrogate;
1006 };
1007
1021
1023 typedef fast_json::json_value fast_json_value;
1024 typedef fast_json::json_object fast_json_object;
1025 typedef fast_json::json_array fast_json_array;
1026 typedef fast_json::json_double fast_json_double;
1027 typedef fast_json::json_int64 fast_json_int64;
1028 typedef fast_json::json_uint64 fast_json_uint64;
1029 typedef fast_json::json_int fast_json_int;
1030 typedef fast_json::json_uint fast_json_uint;
1031 typedef fast_json::json_string fast_json_string;
1032 typedef fast_json::json_bool fast_json_bool;
1033 typedef fast_json::json_null fast_json_null;
1034 typedef fast_json::json_keyword fast_json_keyword;
1035
1037 typedef rjson::json_value rjson_value;
1038 typedef rjson::json_object rjson_object;
1039 typedef rjson::json_array rjson_array;
1040 typedef rjson::json_double rjson_double;
1041 typedef rjson::json_int64 rjson_int64;
1042 typedef rjson::json_uint64 rjson_uint64;
1043 typedef rjson::json_int rjson_int;
1044 typedef rjson::json_uint rjson_uint;
1045 typedef rjson::json_string rjson_string;
1046 typedef rjson::json_bool rjson_bool;
1047 typedef rjson::json_null rjson_null;
1048 typedef rjson::json_keyword rjson_keyword;
1049
1051 typedef fast_rjson::json_value fast_rjson_value;
1052 typedef fast_rjson::json_object fast_rjson_object;
1053 typedef fast_rjson::json_array fast_rjson_array;
1054 typedef fast_rjson::json_double fast_rjson_double;
1055 typedef fast_rjson::json_int64 fast_rjson_int64;
1056 typedef fast_rjson::json_uint64 fast_rjson_uint64;
1057 typedef fast_rjson::json_int fast_rjson_int;
1058 typedef fast_rjson::json_uint fast_rjson_uint;
1059 typedef fast_rjson::json_string fast_rjson_string;
1060 typedef fast_rjson::json_bool fast_rjson_bool;
1061 typedef fast_rjson::json_null fast_rjson_null;
1062 typedef fast_rjson::json_keyword fast_rjson_keyword;
1063
1065 typedef fjson::json_value fjson_value;
1066 typedef fjson::json_object fjson_object;
1067 typedef fjson::json_array fjson_array;
1068 typedef fjson::json_double fjson_double;
1069 typedef fjson::json_int64 fjson_int64;
1070 typedef fjson::json_uint64 fjson_uint64;
1071 typedef fjson::json_int fjson_int;
1072 typedef fjson::json_uint fjson_uint;
1073 typedef fjson::json_string fjson_string;
1074 typedef fjson::json_bool fjson_bool;
1075 typedef fjson::json_null fjson_null;
1076 typedef fjson::json_keyword fjson_keyword;
1077
1079 typedef fast_fjson::json_value fast_fjson_value;
1080 typedef fast_fjson::json_object fast_fjson_object;
1081 typedef fast_fjson::json_array fast_fjson_array;
1082 typedef fast_fjson::json_double fast_fjson_double;
1083 typedef fast_fjson::json_int64 fast_fjson_int64;
1084 typedef fast_fjson::json_uint64 fast_fjson_uint64;
1085 typedef fast_fjson::json_int fast_fjson_int;
1086 typedef fast_fjson::json_uint fast_fjson_uint;
1087 typedef fast_fjson::json_string fast_fjson_string;
1088 typedef fast_fjson::json_bool fast_fjson_bool;
1089 typedef fast_fjson::json_null fast_fjson_null;
1090 typedef fast_fjson::json_keyword fast_fjson_keyword;
1091}
1092
1093#include <neolib/file/json.inl>
1094
basic_json_array(json_value &aOwner)
Definition json.hpp:437
array_type::iterator end()
Definition json.hpp:462
json_value::json_string json_string
Definition json.hpp:428
array_type::const_iterator begin() const
Definition json.hpp:450
json_value & push_back(const value_type &aValue)
Definition json.hpp:467
array_type::iterator begin()
Definition json.hpp:458
json_value & back()
Definition json.hpp:479
void set_contents(json_value &aOwner)
Definition json.hpp:494
array_type::const_iterator end() const
Definition json.hpp:454
array_type::const_iterator cbegin() const
Definition json.hpp:442
json_value & contents() const
Definition json.hpp:488
json_value::value_type value_type
Definition json.hpp:427
json_value & operator[](std::size_t aIndex)
Definition json.hpp:483
array_type::const_iterator cend() const
Definition json.hpp:446
json_value & push_back(value_type &&aValue)
Definition json.hpp:473
std::enable_if_t< std::is_arithmetic_v< U >, U > at_or(const json_string &aKey, const U &aDefault) const
Definition json.hpp:364
json_value & at(const json_string &aKey)
Definition json.hpp:345
json_value::value_type value_type
Definition json.hpp:314
json_value::json_string json_string
Definition json.hpp:315
std::enable_if_t<!std::is_arithmetic_v< U >, U & > at_or(const json_string &aKey, U &aDefault)
Definition json.hpp:357
const json_value & at(const json_string &aKey) const
Definition json.hpp:338
bool has(const json_string &aKey) const
Definition json.hpp:334
json_value & contents() const
Definition json.hpp:388
json_value & operator[](const json_string &aKey)
Definition json.hpp:377
basic_json_object(json_value &aOwner)
Definition json.hpp:329
void set_contents(json_value &aOwner)
Definition json.hpp:394
std::enable_if_t< std::is_arithmetic_v< U >, U & > at_or(const json_string &aKey, U &aDefault)
Definition json.hpp:371
std::enable_if_t<!std::is_arithmetic_v< U >, const U & > at_or(const json_string &aKey, const U &aDefault) const
Definition json.hpp:350
bool has_children() const
Definition json.hpp:726
const_reference parent() const
Definition json.hpp:718
const_iterator begin() const
Definition json.hpp:775
const json_string & name() const
Definition json.hpp:694
basic_json_object< self_type > json_object
Definition json.hpp:573
const_iterator cbegin() const
Definition json.hpp:767
basic_json_value(const basic_json_value &)=delete
const_iterator end() const
Definition json.hpp:779
value_type & operator*()
Definition json.hpp:644
reference operator=(value_type &&aValue)
Definition json.hpp:655
basic_json_array< self_type > json_array
Definition json.hpp:574
reference operator=(const value_type &aValue)
Definition json.hpp:648
void push_back(T &&aValue)
Definition json.hpp:859
basic_json_keyword< self_type > json_keyword
Definition json.hpp:582
const json_document_source_location & document_source_location() const
Definition json.hpp:868
basic_json_value(basic_json_value &&)=delete
basic_quick_string< character_type, character_traits_type, character_allocator_type > json_string
Definition json.hpp:572
void set_document_source_location(const json_document_source_location &aDocumentSourceLocation)
Definition json.hpp:872
bool is_populated_composite() const
Definition json.hpp:675
std::variant< std::monostate, json_string, json_keyword > name_t
Definition json.hpp:584
pointer next_parent_sibling()
Definition json.hpp:762
const_pointer next_sibling() const
Definition json.hpp:750
const_pointer next_parent_sibling() const
Definition json.hpp:758
bool has_name() const
Definition json.hpp:686
bool empty() const
Definition json.hpp:831
bool is_composite() const
Definition json.hpp:667
static constexpr json_syntax syntax
Definition json.hpp:551
const_pointer last_child() const
Definition json.hpp:738
const_pointer first_child() const
Definition json.hpp:730
const value_type & operator*() const
Definition json.hpp:640
bool is_last_sibling() const
Definition json.hpp:746
std::variant< std::monostate, json_object, json_array, json_double, json_int64, json_uint64, json_int, json_uint, json_string, json_bool, json_null, json_keyword > value_type
Definition json.hpp:588
bool has_parent() const
Definition json.hpp:714
basic_json_value(reference aParent, const value_type &aValue)
Definition json.hpp:596
json_type type() const
Definition json.hpp:663
std::enable_if_t< std::is_arithmetic_v< T >, T > as() const
Definition json.hpp:621
self_type & reference
Definition json.hpp:564
void visit(Visitor &&aVisitor, bool aRecurse=true) const
Definition json.hpp:793
void set_name(const json_string &aName)
Definition json.hpp:701
std::enable_if_t<!std::is_arithmetic_v< T >, T & > as()
Definition json.hpp:616
bool is_empty_composite() const
Definition json.hpp:671
basic_json_value(reference aParent, value_type &&aValue)
Definition json.hpp:601
const json_string & text() const
Definition json.hpp:679
std::optional< json_string > optional_json_string
Definition json.hpp:586
const_iterator cend() const
Definition json.hpp:771
bool name_is_keyword() const
Definition json.hpp:690
std::allocator_traits< allocator_type >::template rebind_alloc< self_type > value_allocator
Definition json.hpp:559
CharAlloc character_allocator_type
Definition json.hpp:555
void set_name(const json_keyword &aName)
Definition json.hpp:705
std::enable_if_t< std::is_arithmetic_v< T >, T & > as()
Definition json.hpp:636
bool is_root() const
Definition json.hpp:710
self_type node_value_type
Definition json.hpp:557
basic_json_null< self_type > json_null
Definition json.hpp:581
const self_type & const_reference
Definition json.hpp:563
const self_type * const_pointer
Definition json.hpp:561
self_type * pointer
Definition json.hpp:562
std::size_t size() const
Definition json.hpp:835
std::enable_if_t<!std::is_arithmetic_v< T >, const T & > as() const
Definition json.hpp:611
reference emplace_back(Args &&... aArguments)
Definition json.hpp:854
void visit(Visitor &&aVisitor, bool aRecurse=true)
Definition json.hpp:811
const_iterator end() const
Definition json.inl:1925
bool write(const std::string &aPath, const string_type &aIndent=string_type(2, character_type{' '}))
Definition json.inl:1665
json_value::json_uint64 json_uint64
Definition json.hpp:912
json_value::json_uint json_uint
Definition json.hpp:914
json_value::json_array json_array
Definition json.hpp:909
static constexpr json_syntax syntax
Definition json.hpp:901
std::optional< json_value > optional_json_value
Definition json.hpp:907
json_value::json_keyword json_keyword
Definition json.hpp:918
void visit(Visitor &&aVisitor) const
Definition json.inl:1890
const value_type * const_pointer
Definition json.hpp:922
value_type * pointer
Definition json.hpp:921
json_value::value_type value_type
Definition json.hpp:920
json_encoding encoding() const
Definition json.inl:1819
json_value::json_object json_object
Definition json.hpp:908
Traits character_traits_type
Definition json.hpp:904
const_iterator begin() const
Definition json.inl:1917
static string_type to_error_text(const json_document_source_location &aDocumentSourceLocation, const string_type &aExtraInfo={})
Definition json.inl:1945
json_value::json_null json_null
Definition json.hpp:917
const json_string & document() const
Definition json.inl:1825
json_value::json_double json_double
Definition json.hpp:910
const_iterator cbegin() const
Definition json.inl:1905
Alloc allocator_type
Definition json.hpp:902
bool has_root() const
Definition json.inl:1837
const_iterator cend() const
Definition json.inl:1911
json_value::json_bool json_bool
Definition json.hpp:916
CharAlloc character_allocator_type
Definition json.hpp:905
json_value::json_string json_string
Definition json.hpp:915
bool read(const std::string &aPath, bool aValidateUtf=false)
Definition json.inl:1126
const json_value & root() const
Definition json.inl:1851
basic_json_value< syntax, allocator_type, character_type, character_traits_type, character_allocator_type > json_value
Definition json.hpp:906
json_value::json_int64 json_int64
Definition json.hpp:911
json_value::json_int json_int
Definition json.hpp:913
value_type & reference
Definition json.hpp:923
const json_value & croot() const
Definition json.inl:1843
const value_type & const_reference
Definition json.hpp:924
CharT character_type
Definition json.hpp:903
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 to_std_string() const
const json_value * next_parent_sibling() const
Definition json.hpp:236
json_value::value_type value_type
Definition json.hpp:157
const json_value * first_child() const
Definition json.hpp:208
json_value * buy_child(json_value &aParent, value_type &&aValue)
Definition json.hpp:187
const json_value * next_sibling() const
Definition json.hpp:228
basic_json_node(json_value &aParent)
Definition json.hpp:169
const json_value * last_child() const
Definition json.hpp:216
json_value * buy_child(json_value &aParent, const value_type &aValue)
Definition json.hpp:183
const json_value * parent() const
Definition json.hpp:196
fast_json::json_keyword fast_json_keyword
Definition json.hpp:1034
fast_fjson::json_string fast_fjson_string
Definition json.hpp:1087
rjson::json_int64 rjson_int64
Definition json.hpp:1041
std::optional< T > cache
Definition neolib.hpp:216
fast_json::json_uint fast_json_uint
Definition json.hpp:1030
fast_json::json_double fast_json_double
Definition json.hpp:1026
fast_json::json_int fast_json_int
Definition json.hpp:1029
fast_fjson::json_keyword fast_fjson_keyword
Definition json.hpp:1090
fast_json::json_value fast_json_value
Definition json.hpp:1023
json::json_array json_array
Definition json.hpp:1011
rjson::json_uint rjson_uint
Definition json.hpp:1044
basic_json< json_syntax::Functional > fjson
Definition json.hpp:1064
json::json_string json_string
Definition json.hpp:1017
fast_rjson::json_bool fast_rjson_bool
Definition json.hpp:1060
fast_fjson::json_uint fast_fjson_uint
Definition json.hpp:1086
basic_json< json_syntax::Standard, neolib::fast_pool_allocator< json_type > > fast_json
Definition json.hpp:1022
json::json_uint json_uint
Definition json.hpp:1016
fast_json::json_object fast_json_object
Definition json.hpp:1024
fast_json::json_bool fast_json_bool
Definition json.hpp:1032
fast_json::json_string fast_json_string
Definition json.hpp:1031
fast_fjson::json_int64 fast_fjson_int64
Definition json.hpp:1083
json::json_bool json_bool
Definition json.hpp:1018
json::json_int json_int
Definition json.hpp:1015
rjson::json_array rjson_array
Definition json.hpp:1039
fjson::json_int64 fjson_int64
Definition json.hpp:1069
fast_rjson::json_double fast_rjson_double
Definition json.hpp:1054
rjson::json_object rjson_object
Definition json.hpp:1038
json::json_null json_null
Definition json.hpp:1019
rjson::json_uint64 rjson_uint64
Definition json.hpp:1042
fjson::json_null fjson_null
Definition json.hpp:1075
json::json_object json_object
Definition json.hpp:1010
json_syntax
Definition json.hpp:65
rjson::json_int rjson_int
Definition json.hpp:1043
json_type
Definition json.hpp:94
fast_json::json_int64 fast_json_int64
Definition json.hpp:1027
json_encoding
Definition json.hpp:73
fast_fjson::json_double fast_fjson_double
Definition json.hpp:1082
json::json_int64 json_int64
Definition json.hpp:1013
fast_json::json_null fast_json_null
Definition json.hpp:1033
to_const_reference_t< T > to_const(T &&object)
Definition neolib.hpp:113
fjson::json_double fjson_double
Definition json.hpp:1068
rjson::json_value rjson_value
Definition json.hpp:1037
rjson::json_keyword rjson_keyword
Definition json.hpp:1048
json::json_value json_value
Definition json.hpp:1009
fast_fjson::json_int fast_fjson_int
Definition json.hpp:1085
fjson::json_keyword fjson_keyword
Definition json.hpp:1076
fast_rjson::json_uint fast_rjson_uint
Definition json.hpp:1058
rjson::json_bool rjson_bool
Definition json.hpp:1046
fast_fjson::json_null fast_fjson_null
Definition json.hpp:1089
json::json_keyword json_keyword
Definition json.hpp:1020
fast_rjson::json_string fast_rjson_string
Definition json.hpp:1059
fast_rjson::json_object fast_rjson_object
Definition json.hpp:1052
fast_fjson::json_uint64 fast_fjson_uint64
Definition json.hpp:1084
json::json_double json_double
Definition json.hpp:1012
fast_rjson::json_uint64 fast_rjson_uint64
Definition json.hpp:1056
rjson::json_string rjson_string
Definition json.hpp:1045
basic_json< json_syntax::Relaxed, neolib::fast_pool_allocator< json_type > > fast_rjson
Definition json.hpp:1050
fjson::json_value fjson_value
Definition json.hpp:1065
fast_rjson::json_int64 fast_rjson_int64
Definition json.hpp:1055
fast_json::json_uint64 fast_json_uint64
Definition json.hpp:1028
basic_json< json_syntax::Relaxed > rjson
Definition json.hpp:1036
rjson::json_null rjson_null
Definition json.hpp:1047
fjson::json_object fjson_object
Definition json.hpp:1066
fjson::json_bool fjson_bool
Definition json.hpp:1074
fast_fjson::json_object fast_fjson_object
Definition json.hpp:1080
rjson::json_double rjson_double
Definition json.hpp:1040
basic_json< json_syntax::Functional, neolib::fast_pool_allocator< json_type > > fast_fjson
Definition json.hpp:1078
fast_rjson::json_value fast_rjson_value
Definition json.hpp:1051
fjson::json_string fjson_string
Definition json.hpp:1073
fast_fjson::json_value fast_fjson_value
Definition json.hpp:1079
json::json_uint64 json_uint64
Definition json.hpp:1014
fast_json::json_array fast_json_array
Definition json.hpp:1025
basic_json< json_syntax::Standard > json
Definition json.hpp:1008
fjson::json_int fjson_int
Definition json.hpp:1071
fjson::json_array fjson_array
Definition json.hpp:1067
fast_rjson::json_keyword fast_rjson_keyword
Definition json.hpp:1062
fast_fjson::json_array fast_fjson_array
Definition json.hpp:1081
fast_rjson::json_int fast_rjson_int
Definition json.hpp:1057
fjson::json_uint64 fjson_uint64
Definition json.hpp:1070
fast_fjson::json_bool fast_fjson_bool
Definition json.hpp:1088
fast_rjson::json_array fast_rjson_array
Definition json.hpp:1053
fjson::json_uint fjson_uint
Definition json.hpp:1072
fast_rjson::json_null fast_rjson_null
Definition json.hpp:1061
Definition plf_hive.h:79
iterator_traits< it_type >::difference_type distance(const it_type first, const it_type last)
Definition plf_hive.h:107
json_value::json_string json_string
Definition json.hpp:522
bool operator==(std::nullptr_t) const
Definition json.hpp:533
bool operator!=(std::nullptr_t) const
Definition json.hpp:534
static const json_encoding DEFAULT_ENCODING
Definition json.hpp:90
json_error(const std::string &aReason)
Definition json.hpp:60
json_path_not_found(const std::string &aPath)
Definition json.hpp:61