libdonut  2.3.2
Application framework for cross-platform game development in C++20
json.hpp
Go to the documentation of this file.
1 #ifndef DONUT_JSON_HPP
2 #define DONUT_JSON_HPP
3 
4 #include <donut/Variant.hpp>
5 #include <donut/reflection.hpp>
6 #include <donut/unicode.hpp>
7 
8 #include <algorithm> // std::sort, std::equal_range, std::lower_bound, std::upper_bound
9 #include <array> // std::array
10 #include <charconv> // std::from_chars_result, std::from_chars
11 #include <cmath> // std::isnan, std::isinf, std::signbit
12 #include <compare> // std::partial_ordering, std::compare_partial_order_fallback
13 #include <cstddef> // std::size_t, std::nullptr_t
14 #include <cstdint> // std::uint8_t, std::uint32_t
15 #include <cstdlib> // std::strtoull, std::strtod
16 #include <cstring> // std::memcpy
17 #include <fmt/format.h> // fmt::format_to
18 #include <initializer_list> // std::initializer_list
19 #include <istream> // std::istream
20 #include <iterator> // std::begin, std::end, std::istreambuf_iterator, std::ostreambuf_iterator
21 #include <limits> // std::numeric_limits
22 #include <numeric> // std::accumulate
23 #include <optional> // std::optional
24 #include <ostream> // std::ostream
25 #include <span> // std::span, std::as_bytes
26 #include <sstream> // std::istringstream, std::ostringstream
27 #include <stdexcept> // std::runtime_error, std::out_of_range
28 #include <string> // std::...string
29 #include <string_view> // std::...string_view
30 #include <system_error> // std::errc
31 #include <tuple> // std::forward_as_tuple
32 #include <type_traits> // std::is_same_v, std::is_arithmetic_v, std::is_pointer_v, std::is_aggregate_v, std::is_constructible_v, std::remove_cvref_t
33 #include <utility> // std::pair, std::move, std::forward, std::piecewise_construct
34 #include <vector> // std::vector, std::erase(std::vector), std::erase_if(std::vector)
35 
36 namespace donut::json {
37 
38 namespace detail {
39 
40 template <typename T>
41 concept number = std::is_arithmetic_v<T> && !std::is_same_v<T, bool> && !std::is_same_v<T, char> && !std::is_same_v<T, char8_t> && !std::is_same_v<T, char16_t> &&
42  !std::is_same_v<T, char32_t> && !std::is_same_v<T, wchar_t>;
43 
44 // clang-format off
45 struct AlwaysTrue { constexpr bool operator()(const auto&...) const noexcept { return true; } };
46 struct Get { constexpr const auto& operator()(const auto& value) const noexcept { return value; } };
47 struct GetFirst { constexpr const auto& operator()(const auto& kv) const noexcept { return kv.first; } };
48 struct GetSecond { constexpr const auto& operator()(const auto& kv) const noexcept { return kv.second; } };
49 // clang-format on
50 
51 } // namespace detail
52 
61  std::size_t lineNumber;
62 
67  std::size_t columnNumber;
68 
76  [[nodiscard]] constexpr bool operator==(const SourceLocation& other) const = default;
77 };
78 
82 struct Error : std::runtime_error {
88 
89  Error(const std::string& message, const SourceLocation& source)
90  : std::runtime_error(message)
91  , source(source) {}
92 
93  Error(const char* message, const SourceLocation& source)
94  : std::runtime_error(message)
95  , source(source) {}
96 };
97 
106  std::size_t indentation = 0;
107 
112  std::size_t relativeIndentation = 4;
113 
118 
127  bool prettyPrint = true;
128 
142 
156 
165  const char* newlineString = "\r\n";
166 };
167 
172 
173 // Forward declaration of the definition below, so that Object and Array can contain objects of type Value through indirection, despite Value being defined in terms of them.
174 class Value;
175 
179 using Null = Monostate;
180 
184 using Boolean = bool;
185 
189 using String = std::string;
190 
194 using Number = double;
195 
199 class Object {
200 public:
201  using key_type = String;
203  using value_type = std::pair<String, Value>;
204  using size_type = typename std::vector<value_type>::size_type;
205  using difference_type = typename std::vector<value_type>::difference_type;
206  using reference = typename std::vector<value_type>::reference;
207  using const_reference = typename std::vector<value_type>::const_reference;
208  using pointer = typename std::vector<value_type>::pointer;
209  using const_pointer = typename std::vector<value_type>::const_pointer;
210  using iterator = typename std::vector<value_type>::iterator;
211  using const_iterator = typename std::vector<value_type>::const_iterator;
212  using reverse_iterator = typename std::vector<value_type>::reverse_iterator;
213  using const_reverse_iterator = typename std::vector<value_type>::const_reverse_iterator;
214 
215  Object() noexcept;
216  ~Object();
217 
218  template <typename InputIt>
219  Object(InputIt first, InputIt last);
220  Object(std::initializer_list<value_type> ilist);
221 
222  Object(const Object& other);
223  Object(Object&& other) noexcept;
224  Object& operator=(const Object& other);
225  Object& operator=(Object&& other) noexcept;
226 
227  Object& operator=(std::initializer_list<value_type> ilist);
228 
229  [[nodiscard]] Value& at(std::string_view name);
230  [[nodiscard]] const Value& at(std::string_view name) const;
231  [[nodiscard]] Value& operator[](const String& k);
232  [[nodiscard]] Value& operator[](String&& k);
233 
234  [[nodiscard]] iterator begin() noexcept;
235  [[nodiscard]] const_iterator begin() const noexcept;
236  [[nodiscard]] const_iterator cbegin() const noexcept;
237  [[nodiscard]] iterator end() noexcept;
238  [[nodiscard]] const_iterator end() const noexcept;
239  [[nodiscard]] const_iterator cend() const noexcept;
240  [[nodiscard]] reverse_iterator rbegin() noexcept;
241  [[nodiscard]] const_reverse_iterator rbegin() const noexcept;
242  [[nodiscard]] const_reverse_iterator crbegin() const noexcept;
243  [[nodiscard]] reverse_iterator rend() noexcept;
244  [[nodiscard]] const_reverse_iterator rend() const noexcept;
245  [[nodiscard]] const_reverse_iterator crend() const noexcept;
246 
247  [[nodiscard]] bool empty() const noexcept;
248  [[nodiscard]] size_type size() const noexcept;
249  [[nodiscard]] size_type max_size() const noexcept;
250 
251  void clear() noexcept;
252 
253  template <typename P>
254  std::pair<iterator, bool> insert(P&& value);
255 
256  template <typename P>
257  iterator insert(const_iterator pos, P&& value);
258 
259  template <typename InputIt>
260  void insert(InputIt first, InputIt last);
261  void insert(std::initializer_list<value_type> ilist);
262 
263  template <typename... Args>
264  std::pair<iterator, bool> emplace(Args&&... args);
265 
266  template <typename... Args>
267  iterator emplace_hint(const_iterator hint, Args&&... args);
268 
269  template <typename... Args>
270  std::pair<iterator, bool> try_emplace(const String& k, Args&&... args);
271 
272  template <typename... Args>
273  std::pair<iterator, bool> try_emplace(String&& k, Args&&... args);
274 
275  template <typename... Args>
276  iterator try_emplace(const_iterator, const String& k, Args&&... args);
277 
278  template <typename... Args>
279  iterator try_emplace(const_iterator, String&& k, Args&&... args);
280 
282  size_type erase(std::string_view name);
283 
284  void swap(Object& other) noexcept;
285  friend void swap(Object& a, Object& b) noexcept;
286 
287  [[nodiscard]] size_type count(std::string_view name) const noexcept;
288  [[nodiscard]] bool contains(std::string_view name) const noexcept;
289  [[nodiscard]] iterator find(std::string_view name) noexcept;
290  [[nodiscard]] const_iterator find(std::string_view name) const noexcept;
291  [[nodiscard]] std::pair<iterator, iterator> equal_range(std::string_view name) noexcept;
292  [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(std::string_view name) const noexcept;
293  [[nodiscard]] iterator lower_bound(std::string_view name) noexcept;
294  [[nodiscard]] const_iterator lower_bound(std::string_view name) const noexcept;
295  [[nodiscard]] iterator upper_bound(std::string_view name) noexcept;
296  [[nodiscard]] const_iterator upper_bound(std::string_view name) const noexcept;
297 
298  [[nodiscard]] bool operator==(const Object& other) const noexcept;
299  [[nodiscard]] std::partial_ordering operator<=>(const Object& other) const noexcept;
300 
301  template <typename Predicate>
302  friend size_type erase_if(Object& container, Predicate predicate);
303 
304 private:
305  struct Compare {
306  [[nodiscard]] bool operator()(const value_type& a, const value_type& b) const noexcept;
307  [[nodiscard]] bool operator()(const value_type& a, std::string_view b) const noexcept;
308  [[nodiscard]] bool operator()(std::string_view a, const value_type& b) const noexcept;
309  [[nodiscard]] bool operator()(std::string_view a, std::string_view b) const noexcept;
310  };
311 
312  std::vector<value_type> membersSortedByName;
313 };
314 
318 class Array {
319 public:
320  using value_type = Value;
321  using size_type = typename std::vector<value_type>::size_type;
322  using difference_type = typename std::vector<value_type>::difference_type;
323  using reference = typename std::vector<value_type>::reference;
324  using const_reference = typename std::vector<value_type>::const_reference;
325  using pointer = typename std::vector<value_type>::pointer;
326  using const_pointer = typename std::vector<value_type>::const_pointer;
327  using iterator = typename std::vector<value_type>::iterator;
328  using const_iterator = typename std::vector<value_type>::const_iterator;
329  using reverse_iterator = typename std::vector<value_type>::reverse_iterator;
330  using const_reverse_iterator = typename std::vector<value_type>::const_reverse_iterator;
331 
332  Array() noexcept;
333  ~Array();
334 
335  template <typename InputIt>
336  Array(InputIt first, InputIt last);
337  Array(size_type count, const Value& value);
338  Array(std::initializer_list<value_type> ilist);
339 
340  Array(const Array& other);
341  Array(Array&& other) noexcept;
342  Array& operator=(const Array& other);
343  Array& operator=(Array&& other) noexcept;
344 
345  Array& operator=(std::initializer_list<value_type> ilist);
346 
347  void swap(Array& other) noexcept;
348  friend void swap(Array& a, Array& b) noexcept;
349 
350  [[nodiscard]] pointer data() noexcept;
351  [[nodiscard]] const_pointer data() const noexcept;
352  [[nodiscard]] size_type size() const noexcept;
353  [[nodiscard]] size_type max_size() const noexcept;
354  [[nodiscard]] size_type capacity() const noexcept;
355  [[nodiscard]] bool empty() const noexcept;
356 
357  [[nodiscard]] iterator begin() noexcept;
358  [[nodiscard]] const_iterator begin() const noexcept;
359  [[nodiscard]] const_iterator cbegin() const noexcept;
360  [[nodiscard]] iterator end() noexcept;
361  [[nodiscard]] const_iterator end() const noexcept;
362  [[nodiscard]] const_iterator cend() const noexcept;
363  [[nodiscard]] reverse_iterator rbegin() noexcept;
364  [[nodiscard]] const_reverse_iterator rbegin() const noexcept;
365  [[nodiscard]] const_reverse_iterator crbegin() const noexcept;
366  [[nodiscard]] reverse_iterator rend() noexcept;
367  [[nodiscard]] const_reverse_iterator rend() const noexcept;
368  [[nodiscard]] const_reverse_iterator crend() const noexcept;
369 
370  [[nodiscard]] reference front();
371  [[nodiscard]] const_reference front() const;
372  [[nodiscard]] reference back();
373  [[nodiscard]] const_reference back() const;
374  [[nodiscard]] reference at(size_type pos);
375  [[nodiscard]] const_reference at(size_type pos) const;
376  [[nodiscard]] reference operator[](size_type pos);
377  [[nodiscard]] const_reference operator[](size_type pos) const;
378 
379  [[nodiscard]] bool operator==(const Array& other) const;
380  [[nodiscard]] std::partial_ordering operator<=>(const Array& other) const noexcept;
381 
382  template <typename U>
383  friend size_type erase(Array& container, const U& value);
384 
385  template <typename Predicate>
386  friend size_type erase_if(Array& container, Predicate predicate);
387 
388  void clear() noexcept;
389  void reserve(size_type newCap);
390  void shrink_to_fit();
391 
392  iterator insert(const_iterator pos, const Value& value);
393  iterator insert(const_iterator pos, Value&& value);
394  iterator insert(const_iterator pos, size_type count, const Value& value);
395 
396  template <typename InputIt>
397  iterator insert(const_iterator pos, InputIt first, InputIt last);
398  iterator insert(const_iterator pos, std::initializer_list<value_type> ilist);
399 
400  template <typename... Args>
401  iterator emplace(const_iterator pos, Args&&... args);
402 
405 
406  void push_back(const Value& value);
407  void push_back(Value&& value);
408 
409  template <typename... Args>
410  reference emplace_back(Args&&... args);
411 
412  void pop_back();
413 
414  void resize(size_type count);
415  void resize(size_type count, const Value& value);
416 
417 private:
418  std::vector<value_type> values;
419 };
420 
433 public:
448  [[nodiscard]] static Value parse(std::u8string_view jsonString);
449 
465  [[nodiscard]] static Value parse(std::string_view jsonString);
466 
470  Value() noexcept = default;
471 
475  Value(Null) noexcept {}
476 
480  Value(std::nullptr_t) noexcept {}
481 
487  Value(Boolean value) noexcept
488  : Variant(value) {}
489 
497  Value(const String& value)
498  : Variant(value) {}
499 
505  Value(String&& value) noexcept
506  : Variant(std::move(value)) {}
507 
516  Value(const char* value)
517  : Variant(String{value}) {}
518 
526  Value(std::string_view value)
527  : Variant(String{value}) {}
528 
537  Value(const char8_t* value)
538  : Variant(String{reinterpret_cast<const char*>(value)}) {
539  static_assert(sizeof(char) == sizeof(char8_t));
540  static_assert(alignof(char) == alignof(char8_t));
541  }
542 
551  Value(std::u8string_view value)
552  : Variant(String{value.begin(), value.end()}) {}
553 
560  Value(detail::number auto value) noexcept
561  : Variant(static_cast<Number>(value)) {}
562 
570  Value(const Object& value)
571  : Variant(value) {}
572 
578  Value(Object&& value) noexcept
579  : Variant(std::move(value)) {}
580 
588  Value(const Array& value)
589  : Variant(value) {}
590 
596  Value(Array&& value) noexcept
597  : Variant(std::move(value)) {}
598 
611  [[nodiscard]] std::string toString(const SerializationOptions& options = {}) const;
612 
620  [[nodiscard]] bool operator==(const Value& other) const {
621  return static_cast<const Variant&>(*this) == static_cast<const Variant&>(other);
622  }
623 
631  [[nodiscard]] std::partial_ordering operator<=>(const Value& other) const {
632  return std::compare_partial_order_fallback(static_cast<const Variant&>(*this), static_cast<const Variant&>(other));
633  }
634 };
635 
643 [[nodiscard]] constexpr bool isWhitespaceCharacter(char32_t codePoint) noexcept {
644  return codePoint == '\t' || codePoint == '\n' || codePoint == '\v' || codePoint == '\f' || codePoint == '\r' || codePoint == ' ' || codePoint == 0x00A0 ||
645  codePoint == 0x1680 || (codePoint >= 0x2000 && codePoint <= 0x200A) || codePoint == 0x2028 || codePoint == 0x2029 || codePoint == 0x202F || codePoint == 0x205F ||
646  codePoint == 0x3000 || codePoint == 0xFEFF;
647 }
648 
656 [[nodiscard]] constexpr bool isPunctuationCharacter(char32_t codePoint) noexcept {
657  return codePoint == ',' || codePoint == ':' || codePoint == '[' || codePoint == ']' || codePoint == '{' || codePoint == '}';
658 }
659 
669 [[nodiscard]] constexpr bool isLineTerminatorCharacter(char32_t codePoint) noexcept {
670  return codePoint == '\n' || codePoint == '\r' || codePoint == 0x2028 || codePoint == 0x2029;
671 }
672 
676 enum class TokenType : std::uint8_t {
677  END_OF_FILE,
688  STRING,
689  NUMBER_BINARY,
690  NUMBER_OCTAL,
697 };
698 
702 struct Token {
706 };
707 
714 template <typename It>
715 class Lexer {
716 public:
728  : it(std::move(it))
729  , end(end)
730  , source(source) {}
731 
744  skipWhitespace();
745  if (hasReachedEnd()) {
746  return {.string{}, .source = source, .type = TokenType::END_OF_FILE};
747  }
748  switch (peek()) {
749  case '{': [[fallthrough]];
750  case '}': [[fallthrough]];
751  case '[': [[fallthrough]];
752  case ']': [[fallthrough]];
753  case ':': [[fallthrough]];
754  case ',': return scanPunctuator();
755  case '\"': [[fallthrough]];
756  case '\'': return scanString();
757  case '0': [[fallthrough]];
758  case '1': [[fallthrough]];
759  case '2': [[fallthrough]];
760  case '3': [[fallthrough]];
761  case '4': [[fallthrough]];
762  case '5': [[fallthrough]];
763  case '6': [[fallthrough]];
764  case '7': [[fallthrough]];
765  case '8': [[fallthrough]];
766  case '9': [[fallthrough]];
767  case '+': [[fallthrough]];
768  case '-': [[fallthrough]];
769  case '.': return scanNumber();
770  default: return scanIdentifier();
771  }
772  }
773 
774 private:
775  void skipWhitespace() {
776  while (!hasReachedEnd()) {
777  if (isWhitespaceCharacter(peek())) {
778  if (isLineTerminatorCharacter(peek())) {
779  skipLineTerminatorSequence();
780  } else {
781  advance();
782  }
783  } else if (peek() == '/') {
784  advance();
785  if (hasReachedEnd()) {
786  throw Error{"Invalid token.", source};
787  }
788  if (peek() == '/') {
789  advance();
790  while (!hasReachedEnd()) {
791  if (isLineTerminatorCharacter(peek())) {
792  skipLineTerminatorSequence();
793  break;
794  }
795  advance();
796  }
797  } else if (peek() == '*') {
798  advance();
799  while (!hasReachedEnd()) {
800  if (isLineTerminatorCharacter(peek())) {
801  skipLineTerminatorSequence();
802  } else if (peek() == '*') {
803  advance();
804  if (!hasReachedEnd() && peek() == '/') {
805  advance();
806  break;
807  }
808  } else {
809  advance();
810  }
811  }
812  } else {
813  throw Error{"Invalid token.", source};
814  }
815  } else {
816  break;
817  }
818  }
819  }
820 
821  void skipLineTerminatorSequence() {
822  if (peek() == '\r') {
823  advance();
824  if (!hasReachedEnd() && peek() == '\n') {
825  advance();
826  }
827  } else {
828  advance();
829  }
830  ++source.lineNumber;
831  source.columnNumber = 1;
832  }
833 
834  void advance() {
835  if (!currentCodePoint) {
836  ++it;
837  }
838  currentCodePoint.reset();
839  ++source.columnNumber;
840  }
841 
842  [[nodiscard]] bool hasReachedEnd() const noexcept {
843  return it == end && !currentCodePoint;
844  }
845 
846  [[nodiscard]] char32_t peek() const {
847  if (!currentCodePoint) {
848  currentCodePoint = *it++;
849  }
850  return *currentCodePoint;
851  }
852 
853  [[nodiscard]] std::optional<char32_t> lookahead() const {
854  if (!currentCodePoint) {
855  currentCodePoint = *it++;
856  }
857  if (it != end) {
858  return *it;
859  }
860  return {};
861  }
862 
863  [[nodiscard]] Token scanPunctuator() {
864  String string{static_cast<char>(peek())};
865  const SourceLocation punctuatorSource = source;
866  TokenType type{};
867  switch (peek()) {
868  case ',': type = TokenType::PUNCTUATOR_COMMA; break;
869  case ':': type = TokenType::PUNCTUATOR_COLON; break;
870  case '[': type = TokenType::PUNCTUATOR_OPEN_SQUARE_BRACKET; break;
871  case ']': type = TokenType::PUNCTUATOR_CLOSE_SQUARE_BRACKET; break;
872  case '{': type = TokenType::PUNCTUATOR_OPEN_CURLY_BRACE; break;
873  case '}': type = TokenType::PUNCTUATOR_CLOSE_CURLY_BRACE; break;
874  default: break;
875  }
876  advance();
877  return {.string = std::move(string), .source = punctuatorSource, .type = type};
878  }
879 
880  [[nodiscard]] Token scanString() {
881  const char32_t quoteCharacter = peek();
882  String string{};
883  const SourceLocation stringSource = source;
884  advance();
885  while (!hasReachedEnd()) {
886  if (!unicode::isValidCodePoint(peek())) {
887  throw Error{"Invalid UTF-8.", source};
888  }
889  if (peek() == quoteCharacter) {
890  advance();
891  return {.string = std::move(string), .source = stringSource, .type = TokenType::STRING};
892  }
893  if (isLineTerminatorCharacter(peek())) {
894  throw Error{"Unexpected line terminator in string.", source};
895  }
896  if (peek() != '\\') {
898  string.append(std::string_view{reinterpret_cast<const char*>(codePointUTF8.codeUnits.data()), codePointUTF8.size});
899  advance();
900  continue;
901  }
902  advance();
903  if (hasReachedEnd()) {
904  throw Error{"Empty escape sequence.", source};
905  }
906  if (isLineTerminatorCharacter(peek())) {
907  skipLineTerminatorSequence();
908  continue;
909  }
910  switch (peek()) {
911  case '\"': string.push_back('\"'); break;
912  case '\'': string.push_back('\''); break;
913  case '\\': string.push_back('\\'); break;
914  case 'b': string.push_back('\b'); break;
915  case 'f': string.push_back('\f'); break;
916  case 'n': string.push_back('\n'); break;
917  case 'r': string.push_back('\r'); break;
918  case 't': string.push_back('\t'); break;
919  case 'v': string.push_back('\v'); break;
920  case '0': [[fallthrough]];
921  case '1': [[fallthrough]];
922  case '2': [[fallthrough]];
923  case '3': [[fallthrough]];
924  case '4': [[fallthrough]];
925  case '5': [[fallthrough]];
926  case '6': [[fallthrough]];
927  case '7': [[fallthrough]];
928  case '8': [[fallthrough]];
929  case '9': scanNumericEscapeSequence(string, 1, 3, 8, [](char32_t codePoint) noexcept -> bool { return (codePoint >= '0' && codePoint <= '7'); }); continue;
930  case 'x':
931  scanNumericEscapeSequence(string, 2, 2, 16, [](char32_t codePoint) noexcept -> bool {
932  return (codePoint >= '0' && codePoint <= '9') || (codePoint >= 'a' && codePoint <= 'f') || (codePoint >= 'A' && codePoint <= 'F');
933  });
934  continue;
935  case 'u':
936  scanNumericEscapeSequence(string, 4, 4, 16, [](char32_t codePoint) noexcept -> bool {
937  return (codePoint >= '0' && codePoint <= '9') || (codePoint >= 'a' && codePoint <= 'f') || (codePoint >= 'A' && codePoint <= 'F');
938  });
939  continue;
940  case 'U':
941  scanNumericEscapeSequence(string, 8, 8, 16, [](char32_t codePoint) noexcept -> bool {
942  return (codePoint >= '0' && codePoint <= '9') || (codePoint >= 'a' && codePoint <= 'f') || (codePoint >= 'A' && codePoint <= 'F');
943  });
944  continue;
945  default: {
947  string.append(std::string_view{reinterpret_cast<const char*>(codePointUTF8.codeUnits.data()), codePointUTF8.size});
948  break;
949  }
950  }
951  advance();
952  }
953  throw Error{"Missing end of string quote character.", source};
954  }
955 
956  [[nodiscard]] Token scanNumber() {
957  String string{};
958  const SourceLocation numberSource = source;
959  bool negative = false;
960  if (peek() == '+') {
961  advance();
962  } else if (peek() == '-') {
963  string.push_back('-');
964  advance();
965  negative = true;
966  }
967  if (hasReachedEnd()) {
968  throw Error{"Missing number.", source};
969  }
970  if (peek() == 'I') {
971  if (scanIdentifier().type == TokenType::NUMBER_POSITIVE_INFINITY) {
972  return {.string{}, .source = numberSource, .type = (negative) ? TokenType::NUMBER_NEGATIVE_INFINITY : TokenType::NUMBER_POSITIVE_INFINITY};
973  }
974  throw Error{"Invalid number.", numberSource};
975  }
976  if (peek() == 'N') {
977  if (scanIdentifier().type == TokenType::NUMBER_POSITIVE_NAN) {
978  return {.string{}, .source = numberSource, .type = (negative) ? TokenType::NUMBER_NEGATIVE_NAN : TokenType::NUMBER_POSITIVE_NAN};
979  }
980  throw Error{"Invalid number.", numberSource};
981  }
983  if (!hasReachedEnd() && peek() == '0') {
984  string.push_back('0');
985  advance();
986  if (!hasReachedEnd() && (peek() == 'b' || peek() == 'B')) {
987  string.push_back('b');
988  advance();
990  } else if (!hasReachedEnd() && (peek() == 'x' || peek() == 'X')) {
991  string.push_back('x');
992  advance();
994  } else if (hasReachedEnd() || peek() != '.') {
996  }
997  }
998  bool eNotation = false;
999  bool fraction = false;
1000  while (!hasReachedEnd()) {
1001  if (peek() == '.') {
1002  if (lookahead() == '.') {
1003  break;
1004  }
1005  if (type != TokenType::NUMBER_DECIMAL) {
1006  break;
1007  }
1008  if (eNotation) {
1009  throw Error{"Decimal point in E notation exponent.", source};
1010  }
1011  if (fraction) {
1012  throw Error{"Multiple decimal points in number.", source};
1013  }
1014  string.push_back('.');
1015  advance();
1016  fraction = true;
1017  } else if ((peek() == 'e' || peek() == 'E') && type != TokenType::NUMBER_HEXADECIMAL) {
1018  if (type != TokenType::NUMBER_DECIMAL) {
1019  break;
1020  }
1021  if (eNotation) {
1022  throw Error{"Multiple exponent symbols in E notation.", source};
1023  }
1024  string.push_back('e');
1025  advance();
1026  eNotation = true;
1027  fraction = true;
1028  if (hasReachedEnd()) {
1029  throw Error{"Missing exponent in E notation.", source};
1030  }
1031  if (peek() >= '0' && peek() <= '9') {
1032  string.push_back(static_cast<char>(peek()));
1033  advance();
1034  } else if ((peek() == '+' || peek() == '-')) {
1035  string.push_back(static_cast<char>(peek()));
1036  advance();
1037  if (!hasReachedEnd() && peek() >= '0' && peek() <= '9') {
1038  string.push_back(static_cast<char>(peek()));
1039  advance();
1040  } else {
1041  throw Error{"Missing exponent in E notation.", source};
1042  }
1043  }
1044  } else if ( //
1045  (type == TokenType::NUMBER_BINARY && (peek() == '0' || peek() == '1')) || //
1046  (type == TokenType::NUMBER_OCTAL && (peek() >= '0' && peek() <= '7')) || //
1047  (type == TokenType::NUMBER_DECIMAL && (peek() >= '0' && peek() <= '9')) || //
1048  (type == TokenType::NUMBER_HEXADECIMAL && ((peek() >= '0' && peek() <= '9') || (peek() >= 'a' && peek() <= 'f') || (peek() >= 'A' && peek() <= 'F')))) {
1049  string.push_back(static_cast<char>(peek()));
1050  advance();
1051  } else if (peek() == '_') {
1052  advance();
1053  } else {
1054  break;
1055  }
1056  }
1057  if (!hasReachedEnd()) {
1058  if (!isWhitespaceCharacter(peek()) && !isPunctuationCharacter(peek()) && peek() != '\"' && peek() != '\'' && peek() != '/') {
1059  throw Error{"Invalid character after number.", source};
1060  }
1061  }
1062  return {.string = std::move(string), .source = numberSource, .type = type};
1063  }
1064 
1065  [[nodiscard]] Token scanIdentifier() {
1066  String string{};
1067  const SourceLocation identifierSource = source;
1068  do {
1069  if (!unicode::isValidCodePoint(peek())) {
1070  throw Error{"Invalid UTF-8.", source};
1071  }
1073  string.append(std::string_view{reinterpret_cast<const char*>(codePointUTF8.codeUnits.data()), codePointUTF8.size});
1074  advance();
1075  } while (!hasReachedEnd() && !isWhitespaceCharacter(peek()) && !isPunctuationCharacter(peek()) && peek() != '\"' && peek() != '\'' && peek() != '/');
1077  if (string == "null") {
1078  string = {};
1080  } else if (string == "false") {
1081  string = {};
1083  } else if (string == "true") {
1084  string = {};
1086  } else if (string == "Infinity") {
1087  string = {};
1089  } else if (string == "NaN") {
1090  string = {};
1092  }
1093  return {.string = std::move(string), .source = identifierSource, .type = type};
1094  }
1095 
1096  void scanNumericEscapeSequence(String& output, std::size_t minDigitCount, std::size_t maxDigitCount, int radix, bool (*isDigit)(char32_t) noexcept) {
1097  const SourceLocation escapeSequenceSource = source;
1098  std::string digits{};
1099  digits.reserve(maxDigitCount);
1100  while (digits.size() < maxDigitCount && !hasReachedEnd() && isDigit(peek())) {
1101  digits.push_back(static_cast<char>(peek()));
1102  advance();
1103  }
1104  if (digits.size() < minDigitCount) {
1105  throw Error{"Invalid escape sequence length.", escapeSequenceSource};
1106  }
1107  const char* const digitsBegin = digits.data();
1108  const char* const digitsEnd = digitsBegin + digits.size();
1109  std::uint32_t codePointValue = 0;
1110  if (const std::from_chars_result parseResult = std::from_chars(digitsBegin, digitsEnd, codePointValue, radix);
1111  parseResult.ec != std::errc{} || parseResult.ptr != digitsEnd || !unicode::isValidCodePoint(static_cast<char32_t>(codePointValue))) {
1112  throw Error{"Invalid code point value.", escapeSequenceSource};
1113  }
1114  const unicode::EncodeUTF8FromCodePointResult codePointUTF8 = unicode::encodeUTF8FromCodePoint(static_cast<char32_t>(codePointValue));
1115  output.append(std::string_view{reinterpret_cast<const char*>(codePointUTF8.codeUnits.data()), codePointUTF8.size});
1116  }
1117 
1118  mutable unicode::UTF8Iterator<It> it;
1120  SourceLocation source;
1121  mutable std::optional<char32_t> currentCodePoint{};
1122 };
1123 
1131 template <typename It>
1132 class Parser {
1133 public:
1138  public:
1148  virtual void visitNull(const SourceLocation& source, Null value) {
1149  (void)value;
1150  throw Error{"Unexpected null.", source};
1151  }
1152 
1162  virtual void visitBoolean(const SourceLocation& source, Boolean value) {
1163  (void)value;
1164  throw Error{"Unexpected boolean.", source};
1165  }
1166 
1176  virtual void visitString(const SourceLocation& source, String&& value) {
1177  (void)std::move(value);
1178  throw Error{"Unexpected string.", source};
1179  }
1180 
1190  virtual void visitNumber(const SourceLocation& source, Number value) {
1191  (void)value;
1192  throw Error{"Unexpected number.", source};
1193  }
1194 
1209  virtual void visitObject(const SourceLocation& source, Parser& parser) {
1210  (void)parser;
1211  throw Error{"Unexpected object.", source};
1212  }
1213 
1228  virtual void visitArray(const SourceLocation& source, Parser& parser) {
1229  (void)parser;
1230  throw Error{"Unexpected array.", source};
1231  }
1232 
1233  protected:
1234  ~ValueVisitor() = default;
1235  };
1236 
1243  template <typename Visitor>
1245  Visitor visitor;
1246 
1247  ConcreteValueVisitor(Visitor visitor)
1248  : visitor(std::move(visitor)) {}
1249 
1250  void visitNull(const SourceLocation& source, Null value) override {
1251  if constexpr (requires { visitor.visitNull(source, value); }) {
1252  visitor.visitNull(source, value);
1253  } else {
1254  ValueVisitor::visitNull(source, value);
1255  }
1256  }
1257 
1258  void visitBoolean(const SourceLocation& source, Boolean value) override {
1259  if constexpr (requires { visitor.visitBoolean(source, value); }) {
1260  visitor.visitBoolean(source, value);
1261  } else {
1262  ValueVisitor::visitBoolean(source, value);
1263  }
1264  }
1265 
1266  void visitString(const SourceLocation& source, String&& value) override {
1267  if constexpr (requires { visitor.visitString(source, std::move(value)); }) {
1268  visitor.visitString(source, std::move(value));
1269  } else {
1270  ValueVisitor::visitString(source, std::move(value));
1271  }
1272  }
1273 
1274  void visitNumber(const SourceLocation& source, Number value) override {
1275  if constexpr (requires { visitor.visitNumber(source, value); }) {
1276  visitor.visitNumber(source, value);
1277  } else {
1278  ValueVisitor::visitNumber(source, value);
1279  }
1280  }
1281 
1282  void visitObject(const SourceLocation& source, Parser& parser) override {
1283  if constexpr (requires { visitor.visitObject(source, parser); }) {
1284  visitor.visitObject(source, parser);
1285  } else {
1286  ValueVisitor::visitObject(source, parser);
1287  }
1288  }
1289 
1290  void visitArray(const SourceLocation& source, Parser& parser) override {
1291  if constexpr (requires { visitor.visitArray(source, parser); }) {
1292  visitor.visitArray(source, parser);
1293  } else {
1294  ValueVisitor::visitArray(source, parser);
1295  }
1296  }
1297  };
1298 
1304  public:
1321  virtual void visitProperty(const SourceLocation& source, String&& key, Parser& parser) = 0;
1322 
1323  protected:
1324  ~PropertyVisitor() = default;
1325  };
1326 
1333  template <typename Visitor>
1335  Visitor visitor;
1336 
1337  ConcretePropertyVisitor(Visitor visitor)
1338  : visitor(std::move(visitor)) {}
1339 
1340  void visitProperty(const SourceLocation& source, String&& key, Parser& parser) override {
1341  if constexpr (requires { visitor.visitProperty(source, std::move(key), parser); }) {
1342  visitor.visitProperty(source, std::move(key), parser);
1343  }
1344  }
1345  };
1346 
1352  // clang-format off
1353  void visitNull(const SourceLocation& source, Null value) override { (void)source; (void)value; }
1354  void visitBoolean(const SourceLocation& source, Boolean value) override { (void)source; (void)value; }
1355  void visitString(const SourceLocation& source, String&& value) override { (void)source; (void)std::move(value); }
1356  void visitNumber(const SourceLocation& source, Number value) override { (void)source; (void)value; }
1357  void visitObject(const SourceLocation& source, Parser& parser) override { (void)source; parser.parseObject(SkipPropertyVisitor{}); }
1358  void visitArray(const SourceLocation& source, Parser& parser) override { (void)source; parser.parseValue(SkipValueVisitor{}); }
1359  // clang-format on
1360  };
1361 
1367  // clang-format off
1368  void visitProperty(const SourceLocation& source, String&& key, Parser& parser) override { (void)source; (void)std::move(key); parser.parseValue(SkipValueVisitor{}); }
1369  // clang-format on
1370  };
1371 
1377  explicit Parser(Lexer<It> lexer)
1378  : lexer(std::move(lexer)) {}
1379 
1386  explicit Parser(unicode::UTF8View codePoints) requires(std::is_same_v<It, const char8_t*>)
1387  : Parser(Lexer<It>{codePoints.begin(), codePoints.end(), SourceLocation{.lineNumber = 1, .columnNumber = 1}}) {}
1388 
1395  explicit Parser(std::u8string_view jsonString) requires(std::is_same_v<It, const char8_t*>)
1396  : Parser(unicode::UTF8View{jsonString}) {}
1397 
1405  explicit Parser(std::string_view jsonString) requires(std::is_same_v<It, const char8_t*>)
1406  : Parser(unicode::UTF8View{jsonString}) {}
1407 
1413  explicit Parser(std::istream& stream) requires(std::is_same_v<It, std::istreambuf_iterator<char>>)
1414  : Parser(Lexer<It>{unicode::UTF8Iterator<It>{It{stream}, It{}}, unicode::UTF8Sentinel{}, SourceLocation{.lineNumber = 1, .columnNumber = 1}}) {}
1415 
1421  explicit Parser(std::streambuf* streambuf) requires(std::is_same_v<It, std::istreambuf_iterator<char>>)
1422  : Parser(Lexer<It>{unicode::UTF8Iterator<It>{It{streambuf}, It{}}, unicode::UTF8Sentinel{}, SourceLocation{.lineNumber = 1, .columnNumber = 1}}) {}
1423 
1444  void parseFile(ValueVisitor& visitor) {
1445  parseValue(visitor);
1446  if (const Token& token = peek(); token.type != TokenType::END_OF_FILE) {
1447  throw Error{"Multiple top-level values.", token.source};
1448  }
1449  }
1450 
1470  void parseValue(ValueVisitor& visitor) {
1471  switch (const Token& token = peek(); token.type) {
1472  case TokenType::END_OF_FILE: throw Error{"Expected a value.", token.source};
1474  advance();
1475  visitor.visitNull(token.source, Null{});
1476  break;
1478  advance();
1479  visitor.visitBoolean(token.source, Boolean{false});
1480  break;
1482  advance();
1483  visitor.visitBoolean(token.source, Boolean{true});
1484  break;
1485  case TokenType::IDENTIFIER_NAME: throw Error{"Unexpected name identifier.", token.source};
1486  case TokenType::PUNCTUATOR_COMMA: throw Error{"Unexpected comma.", token.source};
1487  case TokenType::PUNCTUATOR_COLON: throw Error{"Unexpected colon.", token.source};
1489  const SourceLocation source = token.source;
1490  visitor.visitArray(source, *this);
1491  break;
1492  }
1493  case TokenType::PUNCTUATOR_CLOSE_SQUARE_BRACKET: throw Error{"Unexpected closing bracket.", token.source};
1495  const SourceLocation source = token.source;
1496  visitor.visitObject(source, *this);
1497  break;
1498  }
1499  case TokenType::PUNCTUATOR_CLOSE_CURLY_BRACE: throw Error{"Unexpected closing brace.", token.source};
1500  case TokenType::STRING: visitor.visitString(token.source, std::move(eat().string)); break;
1501  case TokenType::NUMBER_BINARY: visitor.visitNumber(token.source, parseNumberContents(eat(), 2)); break;
1502  case TokenType::NUMBER_OCTAL: visitor.visitNumber(token.source, parseNumberContents(eat(), 8)); break;
1503  case TokenType::NUMBER_DECIMAL: visitor.visitNumber(token.source, parseNumberContents(eat(), 10)); break;
1504  case TokenType::NUMBER_HEXADECIMAL: visitor.visitNumber(token.source, parseNumberContents(eat(), 16)); break;
1506  advance();
1507  visitor.visitNumber(token.source, Number{std::numeric_limits<Number>::infinity()});
1508  break;
1510  advance();
1511  visitor.visitNumber(token.source, Number{-std::numeric_limits<Number>::infinity()});
1512  break;
1514  advance();
1515  visitor.visitNumber(token.source, Number{std::numeric_limits<Number>::quiet_NaN()});
1516  break;
1518  advance();
1519  visitor.visitNumber(token.source, Number{-std::numeric_limits<Number>::quiet_NaN()});
1520  break;
1521  }
1522  }
1523 
1538  void parseObject(PropertyVisitor& visitor) {
1539  if (const Token& token = peek(); token.type != TokenType::PUNCTUATOR_OPEN_CURLY_BRACE) {
1540  throw Error{"Expected an object.", token.source};
1541  }
1542  advance();
1543  while (true) {
1544  String key{};
1545  switch (const Token& token = peek(); token.type) {
1546  case TokenType::END_OF_FILE: throw Error{"Missing end of object.", token.source};
1547  case TokenType::IDENTIFIER_NULL: throw Error{"Unexpected null.", token.source};
1548  case TokenType::IDENTIFIER_FALSE: throw Error{"Unexpected false.", token.source};
1549  case TokenType::IDENTIFIER_TRUE: throw Error{"Unexpected true.", token.source};
1550  case TokenType::IDENTIFIER_NAME: [[fallthrough]];
1551  case TokenType::STRING: key = std::move(eat().string); break;
1552  case TokenType::PUNCTUATOR_COMMA: [[fallthrough]];
1553  case TokenType::PUNCTUATOR_COLON: [[fallthrough]];
1554  case TokenType::PUNCTUATOR_OPEN_SQUARE_BRACKET: [[fallthrough]];
1555  case TokenType::PUNCTUATOR_CLOSE_SQUARE_BRACKET: [[fallthrough]];
1556  case TokenType::PUNCTUATOR_OPEN_CURLY_BRACE: throw Error{"Unexpected punctuator.", token.source};
1557  case TokenType::PUNCTUATOR_CLOSE_CURLY_BRACE: advance(); return;
1558  case TokenType::NUMBER_BINARY: [[fallthrough]];
1559  case TokenType::NUMBER_OCTAL: [[fallthrough]];
1560  case TokenType::NUMBER_DECIMAL: [[fallthrough]];
1561  case TokenType::NUMBER_HEXADECIMAL: [[fallthrough]];
1562  case TokenType::NUMBER_POSITIVE_INFINITY: [[fallthrough]];
1563  case TokenType::NUMBER_NEGATIVE_INFINITY: [[fallthrough]];
1564  case TokenType::NUMBER_POSITIVE_NAN: [[fallthrough]];
1565  case TokenType::NUMBER_NEGATIVE_NAN: throw Error{"Unexpected number.", token.source};
1566  }
1567  if (const Token token = eat(); token.type != TokenType::PUNCTUATOR_COLON) {
1568  throw Error{"Expected a colon.", token.source};
1569  }
1570  const SourceLocation source = peek().source;
1571  visitor.visitProperty(source, std::move(key), *this);
1572  if (peek().source == source) {
1573  struct SkipValue final : ValueVisitor {
1574  // clang-format off
1575  void visitNull(const SourceLocation& source, Null value) override { (void)source; (void)value; }
1576  void visitBoolean(const SourceLocation& source, Boolean value) override { (void)source; (void)value; }
1577  void visitString(const SourceLocation& source, String&& value) override { (void)source; (void)std::move(value); }
1578  void visitNumber(const SourceLocation& source, Number value) override { (void)source; (void)value; }
1579  void visitObject(const SourceLocation& source, Parser& parser) override { (void)source; (void)parser; }
1580  void visitArray(const SourceLocation& source, Parser& parser) override { (void)source; (void)parser; }
1581  // clang-format on
1582  };
1583  parseValue(SkipValue{});
1584  }
1585  if (const Token& token = peek(); token.type == TokenType::PUNCTUATOR_COMMA) {
1586  advance();
1587  } else if (token.type == TokenType::PUNCTUATOR_CLOSE_CURLY_BRACE) {
1588  advance();
1589  break;
1590  } else {
1591  throw Error{"Expected a comma or closing brace.", token.source};
1592  }
1593  }
1594  }
1595 
1614  void parseArray(ValueVisitor& visitor) {
1615  if (const Token& token = peek(); token.type != TokenType::PUNCTUATOR_OPEN_SQUARE_BRACKET) {
1616  throw Error{"Expected an array.", token.source};
1617  }
1618  advance();
1619  while (true) {
1620  if (peek().type == TokenType::PUNCTUATOR_CLOSE_SQUARE_BRACKET) {
1621  advance();
1622  return;
1623  }
1624  parseValue(visitor);
1625  if (const Token& token = peek(); token.type == TokenType::PUNCTUATOR_COMMA) {
1626  advance();
1627  } else if (token.type == TokenType::PUNCTUATOR_CLOSE_SQUARE_BRACKET) {
1628  advance();
1629  break;
1630  } else {
1631  throw Error{"Expected a comma or closing bracket.", token.source};
1632  }
1633  }
1634  }
1635 
1639  void parseFile(ValueVisitor&& visitor) { // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
1640  parseFile(visitor);
1641  }
1642 
1646  void parseValue(ValueVisitor&& visitor) { // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
1647  parseValue(visitor);
1648  }
1649 
1653  void parseObject(PropertyVisitor&& visitor) { // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
1654  parseObject(visitor);
1655  }
1656 
1660  void parseArray(ValueVisitor&& visitor) { // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
1661  parseArray(visitor);
1662  }
1663 
1667  template <typename Visitor>
1668  void parseFile(Visitor visitor) {
1669  parseFile(static_cast<ValueVisitor&&>(ConcreteValueVisitor<Visitor>{std::move(visitor)}));
1670  }
1671 
1675  template <typename Visitor>
1676  void parseValue(Visitor visitor) {
1677  parseValue(static_cast<ValueVisitor&&>(ConcreteValueVisitor<Visitor>{std::move(visitor)}));
1678  }
1679 
1683  template <typename Visitor>
1684  void parseObject(Visitor visitor) {
1685  parseObject(static_cast<PropertyVisitor&&>(ConcretePropertyVisitor<Visitor>{std::move(visitor)}));
1686  }
1687 
1691  template <typename Visitor>
1692  void parseArray(Visitor visitor) {
1693  parseArray(static_cast<ValueVisitor&&>(ConcreteValueVisitor<Visitor>{std::move(visitor)}));
1694  }
1695 
1707  void skipFile() {
1708  parseFile(SkipValueVisitor{});
1709  }
1710 
1721  void skipValue() {
1722  parseValue(SkipValueVisitor{});
1723  }
1724 
1740  Value result = parseValue();
1741  if (const Token& token = peek(); token.type != TokenType::END_OF_FILE) {
1742  throw Error{"Multiple top-level values.", token.source};
1743  }
1744  return result;
1745  }
1746 
1767  struct Visitor final : ValueVisitor {
1768  Value& result;
1769 
1770  explicit Visitor(Value& result) noexcept
1771  : result(result) {}
1772 
1773  // clang-format off
1774  void visitNull(const SourceLocation&, Null value) override { result = value; }
1775  void visitBoolean(const SourceLocation&, Boolean value) override { result = value; }
1776  void visitString(const SourceLocation&, String&& value) override { result = std::move(value); }
1777  void visitNumber(const SourceLocation&, Number value) override { result = value; }
1778  void visitObject(const SourceLocation&, Parser& parser) override { result = parser.parseObject(); }
1779  void visitArray(const SourceLocation&, Parser& parser) override { result = parser.parseArray(); }
1780  // clang-format on
1781  };
1782  Value result{};
1783  parseValue(Visitor{result});
1784  return result;
1785  }
1786 
1799  const Token token = eat();
1800  switch (token.type) {
1801  case TokenType::IDENTIFIER_NULL: return Null{};
1802  default: break;
1803  }
1804  throw Error{"Expected a null.", token.source};
1805  }
1806 
1819  const Token token = eat();
1820  switch (token.type) {
1821  case TokenType::IDENTIFIER_FALSE: return Boolean{false};
1822  case TokenType::IDENTIFIER_TRUE: return Boolean{true};
1823  default: break;
1824  }
1825  throw Error{"Expected a boolean.", token.source};
1826  }
1827 
1840  Token token = eat();
1841  switch (token.type) {
1842  case TokenType::STRING: return std::move(token.string);
1843  default: break;
1844  }
1845  throw Error{"Expected a string.", token.source};
1846  }
1847 
1860  Token token = eat();
1861  switch (token.type) {
1862  case TokenType::NUMBER_BINARY: return parseNumberContents(std::move(token), 2);
1863  case TokenType::NUMBER_OCTAL: return parseNumberContents(std::move(token), 8);
1864  case TokenType::NUMBER_DECIMAL: return parseNumberContents(std::move(token), 10);
1865  case TokenType::NUMBER_HEXADECIMAL: return parseNumberContents(std::move(token), 16);
1866  case TokenType::NUMBER_POSITIVE_INFINITY: return std::numeric_limits<Number>::infinity();
1867  case TokenType::NUMBER_NEGATIVE_INFINITY: return -std::numeric_limits<Number>::infinity();
1868  case TokenType::NUMBER_POSITIVE_NAN: return std::numeric_limits<Number>::quiet_NaN();
1869  case TokenType::NUMBER_NEGATIVE_NAN: return -std::numeric_limits<Number>::quiet_NaN();
1870  default: break;
1871  }
1872  throw Error{"Expected a number.", token.source};
1873  }
1874 
1888  const Token& token = peek();
1889  switch (token.type) {
1891  struct Visitor final : PropertyVisitor {
1892  Object& result;
1893 
1894  explicit Visitor(Object& result) noexcept
1895  : result(result) {}
1896 
1897  void visitProperty(const SourceLocation&, String&& key, Parser& parser) override {
1898  result.emplace(std::move(key), std::move(parser.parseValue()));
1899  }
1900  };
1901  Object result{};
1902  parseObject(Visitor{result});
1903  return result;
1904  }
1905  default: break;
1906  }
1907  throw Error{"Expected an object.", token.source};
1908  }
1909 
1923  const Token& token = peek();
1924  switch (token.type) {
1926  Array result{};
1927  struct Visitor final : ValueVisitor {
1928  Array& result;
1929 
1930  explicit Visitor(Array& result) noexcept
1931  : result(result) {}
1932 
1933  // clang-format off
1934  void visitNull(const SourceLocation&, Null value) override { result.emplace_back(value); }
1935  void visitBoolean(const SourceLocation&, Boolean value) override { result.emplace_back(value); }
1936  void visitString(const SourceLocation&, String&& value) override { result.emplace_back(std::move(value)); }
1937  void visitNumber(const SourceLocation&, Number value) override { result.emplace_back(value); }
1938  void visitObject(const SourceLocation&, Parser& parser) override { result.emplace_back(parser.parseObject()); }
1939  void visitArray(const SourceLocation&, Parser& parser) override { result.emplace_back(parser.parseArray()); }
1940  // clang-format on
1941  };
1942  parseArray(Visitor{result});
1943  return result;
1944  }
1945  default: break;
1946  }
1947  throw Error{"Expected an array.", token.source};
1948  }
1949 
1957  void advance() {
1958  if (!currentToken) {
1959  lexer.scan();
1960  }
1961  currentToken.reset();
1962  }
1963 
1980  [[nodiscard]] const Token& peek() const {
1981  if (!currentToken) {
1982  currentToken = lexer.scan();
1983  }
1984  return *currentToken;
1985  }
1986 
1998  [[nodiscard]] Token eat() {
1999  if (!currentToken) {
2000  currentToken = lexer.scan();
2001  }
2002  Token result = std::move(*currentToken);
2003  currentToken.reset();
2004  return result;
2005  }
2006 
2007 private:
2008  [[nodiscard]] static Number parseNumberContents(Token token, int radix) {
2009  const char* numberStringBegin = token.string.c_str();
2010  char* const numberStringEnd = token.string.data() + token.string.size();
2011  char* endPointer = numberStringEnd;
2012  if (radix == 10) {
2013  const double number_value = std::strtod(numberStringBegin, &endPointer);
2014  if (endPointer != numberStringEnd) {
2015  throw Error{"Invalid number.", token.source};
2016  }
2017  return Number{number_value};
2018  }
2019  bool negative = false;
2020  if (!token.string.empty() && token.string.front() == '-') {
2021  negative = true;
2022  ++numberStringBegin;
2023  }
2024  const unsigned long long integerNumberValue = std::strtoull(numberStringBegin, &endPointer, radix);
2025  if (endPointer != numberStringEnd) {
2026  throw Error{"Invalid number.", token.source};
2027  }
2028  const double numberValue = static_cast<double>(integerNumberValue);
2029  return Number{(negative) ? -numberValue : numberValue};
2030  }
2031 
2032  mutable Lexer<It> lexer;
2033  mutable std::optional<Token> currentToken{};
2034 };
2035 
2040 
2045 
2046 namespace detail {
2047 
2048 template <typename T, typename ObjectPropertyFilter = detail::AlwaysTrue, typename ArrayItemFilter = detail::AlwaysTrue>
2049 [[nodiscard]] std::size_t getRecursiveSize(const T& value, ObjectPropertyFilter objectPropertyFilter, ArrayItemFilter arrayItemFilter);
2050 
2051 } // namespace detail
2052 
2069 template <typename T>
2070 struct Serializer;
2071 
2087 template <typename T>
2088 struct Deserializer;
2089 
2106 template <typename T>
2107 void serialize(std::ostream& stream, const T& value, const SerializationOptions& options = {});
2108 
2126 template <typename T>
2127 void deserialize(std::istream& stream, T& value, const DeserializationOptions& options = {});
2128 
2142 inline std::ostream& operator<<(std::ostream& stream, const Value& value) {
2143  json::serialize(stream, value);
2144  return stream;
2145 }
2146 
2163 inline std::istream& operator>>(std::istream& stream, Value& value) {
2164  try {
2165  json::deserialize(stream, value);
2166  } catch (const Error&) {
2167  stream.setstate(std::istream::failbit);
2168  }
2169  return stream;
2170 }
2171 
2175 struct Writer {
2176 private:
2177  std::ostream& stream;
2178 
2179 public:
2184 
2191  explicit Writer(std::ostream& stream, const SerializationOptions& options = {})
2192  : stream(stream)
2193  , options(options) {}
2194 
2202  void write(char byte) {
2203  stream << byte;
2204  }
2205 
2213  void write(std::string_view bytes) {
2214  stream << bytes;
2215  }
2216 
2229  for (std::size_t i = 0; i < options.indentation; ++i) {
2230  write(options.indentationCharacter);
2231  }
2232  }
2233 
2239  void writeNewline() {
2240  stream << options.newlineString;
2241  }
2242 
2248  void writeNull() {
2249  write("null");
2250  }
2251 
2259  void writeBoolean(Boolean value) {
2260  write((value) ? "true" : "false");
2261  }
2262 
2271  void writeString(std::string_view bytes) {
2272  constexpr std::array<char, 16> HEXADECIMAL_DIGITS{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
2273  write('\"');
2274  for (const char byte : bytes) {
2275  if (byte >= ' ' && byte <= '~' && byte != '\"' && byte != '\\') {
2276  write(byte);
2277  } else {
2278  write('\\');
2279  switch (byte) {
2280  case '\"': write('\"'); break;
2281  case '\\': write('\\'); break;
2282  case '\b': write('b'); break;
2283  case '\f': write('f'); break;
2284  case '\n': write('n'); break;
2285  case '\r': write('r'); break;
2286  case '\t': write('t'); break;
2287  case '\v': write('v'); break;
2288  case '\0': write('0'); break;
2289  default:
2290  write('x');
2291  write(HEXADECIMAL_DIGITS[(byte >> 4) & 0x0F]);
2292  write(HEXADECIMAL_DIGITS[(byte & 0x0F)]);
2293  break;
2294  }
2295  }
2296  }
2297  write('\"');
2298  }
2299 
2308  template <typename CharT, typename Traits>
2309  void writeString(std::basic_string_view<CharT, Traits> value) requires(!std::is_same_v<CharT, char> || !std::is_same_v<Traits, std::char_traits<char>>) {
2310  const std::span<const std::byte> bytes = std::as_bytes(std::span{value.data(), value.size()});
2311  writeString(std::string_view{reinterpret_cast<const char*>(bytes.data()), bytes.size()});
2312  }
2313 
2324  void writeString(const auto& value) {
2325  if constexpr (requires { std::string_view{value}; }) {
2326  writeString(std::string_view{value});
2327  } else if constexpr (requires { std::u8string_view{value}; }) {
2328  writeString(std::u8string_view{value});
2329  } else if constexpr (requires { std::u16string_view{value}; }) {
2330  writeString(std::u16string_view{value});
2331  } else if constexpr (requires { std::u32string_view{value}; }) {
2332  writeString(std::u32string_view{value});
2333  } else if constexpr (requires { std::wstring_view{value}; }) {
2334  writeString(std::wstring_view{value});
2335  } else {
2336  std::ostringstream stringStream{};
2337  json::serialize(stringStream, value, {.prettyPrint = false});
2338  writeString(std::move(stringStream).str());
2339  }
2340  }
2341 
2349  void writeNumber(Number value) {
2350  if (std::isnan(value)) {
2351  if (std::signbit(value)) {
2352  stream << "-NaN";
2353  } else {
2354  stream << "NaN";
2355  }
2356  } else if (std::isinf(value)) {
2357  if (std::signbit(value)) {
2358  stream << "-Infinity";
2359  } else {
2360  stream << "Infinity";
2361  }
2362  } else {
2363  [[likely]] fmt::format_to(std::ostreambuf_iterator{stream}, "{}", value);
2364  }
2365  }
2366 
2384  template <typename PropertyFilter = detail::AlwaysTrue, typename GetKey = detail::GetFirst, typename GetValue = detail::GetSecond>
2385  void writeObject(const auto& value, PropertyFilter propertyFilter = {}, GetKey getKey = {}, GetValue getValue = {}) {
2386  auto it = std::begin(value);
2387  const auto end = std::end(value);
2388  while (it != end && !propertyFilter(*it)) {
2389  ++it;
2390  }
2391  if (options.prettyPrint) {
2392  if (it == end) {
2393  write("{}");
2394  } else if (detail::getRecursiveSize(value, propertyFilter, {}) - 1 <= options.prettyPrintMaxSingleLineObjectPropertyCount) {
2395  write("{ ");
2396  writeString(getKey(*it));
2397  write(": ");
2398  serialize(getValue(*it));
2399  for (++it; it != end; ++it) {
2400  if (propertyFilter(*it)) {
2401  write(", ");
2402  writeString(getKey(*it));
2403  write(": ");
2404  serialize(getValue(*it));
2405  }
2406  }
2407  write(" }");
2408  } else {
2409  write('{');
2410  writeNewline();
2411  options.indentation += options.relativeIndentation;
2412  writeIndentation();
2413  writeString(getKey(*it));
2414  write(": ");
2415  serialize(getValue(*it));
2416  for (++it; it != end; ++it) {
2417  if (propertyFilter(*it)) {
2418  write(',');
2419  writeNewline();
2420  writeIndentation();
2421  writeString(getKey(*it));
2422  write(": ");
2423  serialize(getValue(*it));
2424  }
2425  }
2426  writeNewline();
2427  options.indentation -= options.relativeIndentation;
2428  writeIndentation();
2429  write('}');
2430  }
2431  } else {
2432  write('{');
2433  if (it != end) {
2434  writeString(getKey(*it));
2435  write(':');
2436  serialize(getValue(*it));
2437  for (++it; it != end; ++it) {
2438  if (propertyFilter(*it)) {
2439  write(',');
2440  writeString(getKey(*it));
2441  write(':');
2442  serialize(getValue(*it));
2443  }
2444  }
2445  }
2446  write('}');
2447  }
2448  }
2449 
2464  template <typename ItemFilter = detail::AlwaysTrue, typename GetValue = detail::Get>
2465  void writeArray(const auto& value, ItemFilter itemFilter = {}, GetValue getValue = {}) {
2466  auto it = std::begin(value);
2467  const auto end = std::end(value);
2468  while (it != end && !itemFilter(*it)) {
2469  ++it;
2470  }
2471  if (options.prettyPrint) {
2472  if (it == end) {
2473  write("[]");
2474  } else if (detail::getRecursiveSize(value, {}, itemFilter) - 1 <= options.prettyPrintMaxSingleLineArrayItemCount) {
2475  write('[');
2476  serialize(getValue(*it));
2477  for (++it; it != end; ++it) {
2478  if (itemFilter(*it)) {
2479  write(", ");
2480  serialize(getValue(*it));
2481  }
2482  }
2483  write(']');
2484  } else {
2485  write('[');
2486  writeNewline();
2487  options.indentation += options.relativeIndentation;
2488  writeIndentation();
2489  serialize(getValue(*it));
2490  for (++it; it != end; ++it) {
2491  if (itemFilter(*it)) {
2492  write(',');
2493  writeNewline();
2494  writeIndentation();
2495  serialize(getValue(*it));
2496  }
2497  }
2498  writeNewline();
2499  options.indentation -= options.relativeIndentation;
2500  writeIndentation();
2501  write(']');
2502  }
2503  } else {
2504  write('[');
2505  if (it != end) {
2506  serialize(getValue(*it));
2507  for (++it; it != end; ++it) {
2508  if (itemFilter(*it)) {
2509  write(',');
2510  serialize(getValue(*it));
2511  }
2512  }
2513  }
2514  write(']');
2515  }
2516  }
2517 
2531  void writeOptional(const auto& value) {
2532  if (value) {
2533  serialize(*value);
2534  } else {
2535  writeNull();
2536  }
2537  }
2538 
2548  template <typename T>
2549  void writeAggregate(const T& value) {
2550  if constexpr (reflection::aggregate_size_v<T> == 0) {
2551  write("[]");
2552  } else if constexpr (reflection::aggregate_size_v<T> == 1) {
2553  const auto& [v] = value;
2554  serialize(v);
2555  } else if (options.prettyPrint) {
2556  if (detail::getRecursiveSize(value, {}, {}) - 1 <= options.prettyPrintMaxSingleLineArrayItemCount) {
2557  write('[');
2558  bool successor = false;
2559  reflection::forEach(reflection::fields(value), [&](const auto& v) {
2560  if (successor) {
2561  write(", ");
2562  }
2563  successor = true;
2564  serialize(v);
2565  });
2566  write(']');
2567  } else {
2568  write('[');
2569  writeNewline();
2570  options.indentation += options.relativeIndentation;
2571  bool successor = false;
2572  reflection::forEach(reflection::fields(value), [&](const auto& v) {
2573  if (successor) {
2574  write(',');
2575  writeNewline();
2576  }
2577  successor = true;
2578  writeIndentation();
2579  serialize(v);
2580  });
2581  writeNewline();
2582  options.indentation -= options.relativeIndentation;
2583  writeIndentation();
2584  write(']');
2585  }
2586  } else {
2587  write('[');
2588  bool successor = false;
2589  reflection::forEach(reflection::fields(value), [&](const auto& v) {
2590  if (successor) {
2591  write(',');
2592  }
2593  successor = true;
2594  serialize(v);
2595  });
2596  write(']');
2597  }
2598  }
2599 
2609  template <typename T>
2610  void serialize(const T& value) {
2612  }
2613 };
2614 
2618 struct Reader {
2619 private:
2620  using It = std::istreambuf_iterator<char>;
2621 
2622  Parser<It> parser;
2623 
2624 public:
2629 
2636  explicit Reader(std::istream& stream, const DeserializationOptions& options = {})
2637  : parser(stream)
2638  , options(options) {}
2639 
2653  const SourceLocation source = parser.peek().source;
2654  parser.parseNull();
2655  return source;
2656  }
2657 
2674  const SourceLocation source = parser.peek().source;
2675  value = parser.parseBoolean();
2676  return source;
2677  }
2678 
2695  const SourceLocation source = parser.peek().source;
2696  value = parser.parseString();
2697  return source;
2698  }
2699 
2715  String string{};
2716  const SourceLocation source = readString(string);
2717  if constexpr (requires { value = std::move(string); }) {
2718  value = std::move(string);
2719  } else if constexpr (requires { value = std::string{}; }) {
2720  value = std::string{std::move(string)};
2721  } else if constexpr (requires { value = std::u8string{}; }) {
2722  value = std::u8string{string.begin(), string.end()};
2723  } else if constexpr (requires { value = std::u16string{}; }) {
2724  if (string.size() % sizeof(char16_t) != 0) {
2725  throw Error{"Expected a sequence of complete UTF-16 code units.", source};
2726  }
2727  std::u16string temporaryString = std::u16string(string.size() / sizeof(char16_t), char16_t{});
2728  std::memcpy(temporaryString.data(), string.data(), string.size());
2729  value = std::move(temporaryString);
2730  } else if constexpr (requires { value = std::u32string{}; }) {
2731  if (string.size() % sizeof(char32_t) != 0) {
2732  throw Error{"Expected a sequence of complete UTF-32 code units.", source};
2733  }
2734  std::u32string temporaryString = std::u32string(string.size() / sizeof(char32_t), char32_t{});
2735  std::memcpy(temporaryString.data(), string.data(), string.size());
2736  value = std::move(temporaryString);
2737  } else if constexpr (requires { value = std::wstring{}; }) {
2738  if (string.size() % sizeof(wchar_t) != 0) {
2739  throw Error{"Expected a sequence of complete wide characters.", source};
2740  }
2741  std::wstring temporaryString = std::wstring(string.size() / sizeof(wchar_t), wchar_t{});
2742  std::memcpy(temporaryString.data(), string.data(), string.size());
2743  value = std::move(temporaryString);
2744  } else {
2745  std::istringstream stringStream{std::move(string)}; // NOLINT(performance-move-const-arg)
2746  json::deserialize(stringStream, value);
2747  }
2748  return source;
2749  }
2750 
2767  const SourceLocation source = parser.peek().source;
2768  value = parser.parseNumber();
2769  return source;
2770  }
2771 
2786  template <typename T>
2788  Number number{};
2789  const SourceLocation source = readNumber(number);
2790  value = static_cast<T>(number);
2791  return source;
2792  }
2793 
2810  const SourceLocation source = parser.peek().source;
2811  value = parser.parseObject();
2812  return source;
2813  }
2814 
2841  const SourceLocation source = parser.peek().source;
2842  if (const Token token = parser.eat(); token.type != TokenType::PUNCTUATOR_OPEN_CURLY_BRACE) {
2843  throw Error{"Expected an object.", token.source};
2844  }
2845  value.clear();
2847  while (true) {
2848  std::remove_cvref_t<decltype(std::begin(value)->first)> propertyKey{};
2849  std::remove_cvref_t<decltype(std::begin(value)->second)> propertyValue{};
2850  readString(propertyKey);
2851  if (const Token token = parser.eat(); token.type != TokenType::PUNCTUATOR_COLON) {
2852  throw Error{"Expected a colon.", token.source};
2853  }
2854  deserialize(propertyValue);
2855  value.emplace(std::move(propertyKey), std::move(propertyValue));
2856  const Token token = parser.eat();
2858  break;
2859  }
2860  if (token.type == TokenType::PUNCTUATOR_COMMA) {
2862  parser.advance();
2863  break;
2864  }
2865  } else {
2866  throw Error{"Expected a comma or closing brace.", token.source};
2867  }
2868  }
2869  }
2870  return source;
2871  }
2872 
2889  const SourceLocation source = parser.peek().source;
2890  value = parser.parseArray();
2891  return source;
2892  }
2893 
2917  SourceLocation readArray(auto& value) {
2918  const SourceLocation source = parser.peek().source;
2919  if (const Token token = parser.eat(); token.type != TokenType::PUNCTUATOR_OPEN_SQUARE_BRACKET) {
2920  throw Error{"Expected an array.", token.source};
2921  }
2922  value.clear();
2924  while (true) {
2925  std::remove_cvref_t<decltype(*std::begin(value))> item{};
2926  deserialize(item);
2927  value.push_back(std::move(item));
2928  const Token token = parser.eat();
2930  break;
2931  }
2932  if (token.type == TokenType::PUNCTUATOR_COMMA) {
2934  parser.advance();
2935  break;
2936  }
2937  } else {
2938  throw Error{"Expected a comma or closing bracket.", token.source};
2939  }
2940  }
2941  }
2942  return source;
2943  }
2944 
2961  const SourceLocation source = parser.peek().source;
2962  value = parser.parseValue();
2963  return source;
2964  }
2965 
2989  template <typename T>
2991  const SourceLocation source = parser.peek().source;
2992  if (parser.peek().type == TokenType::IDENTIFIER_NULL) {
2993  parser.advance();
2994  value = T{};
2995  } else {
2996  std::remove_cvref_t<decltype(*value)> result{};
2997  deserialize(result);
2998  value = std::move(result);
2999  }
3000  return source;
3001  }
3002 
3022  template <typename T>
3024  const SourceLocation source = parser.peek().source;
3025  if constexpr (reflection::aggregate_size_v<T> == 1) {
3026  auto& [v] = value;
3027  deserialize(v);
3028  } else {
3029  if (const Token token = parser.eat(); token.type != TokenType::PUNCTUATOR_OPEN_SQUARE_BRACKET) {
3030  throw Error{"Expected an array.", token.source};
3031  }
3032  bool successor = false;
3033  reflection::forEach(reflection::fields(value), [&](auto& v) -> void {
3034  if (successor) {
3035  if (const Token token = parser.eat(); token.type != TokenType::PUNCTUATOR_COMMA) {
3036  throw Error{"Expected a comma.", token.source};
3037  }
3038  }
3039  successor = true;
3040  deserialize(v);
3041  });
3042  Token token = parser.eat();
3043  if (token.type == TokenType::PUNCTUATOR_COMMA) {
3044  token = parser.eat();
3045  }
3046  if (token.type != TokenType::PUNCTUATOR_CLOSE_SQUARE_BRACKET) {
3047  throw Error{"Missing end of array.", token.source};
3048  }
3049  }
3050  return source;
3051  }
3052 
3062  template <typename T>
3063  void deserialize(T& value) {
3065  }
3066 };
3067 
3081 template <typename T>
3082 inline void serialize(std::ostream& stream, const T& value, const SerializationOptions& options) {
3083  Writer{stream, options}.serialize(value);
3084 }
3085 
3099 template <typename T>
3100 inline void deserialize(std::istream& stream, T& value, const DeserializationOptions& options) {
3101  Reader{stream, options}.deserialize(value);
3102 }
3103 
3104 namespace detail {
3105 
3106 struct NoVisitor {};
3107 
3108 template <typename Base, typename Callback>
3109 struct VisitNull : Base {
3110  [[no_unique_address]] Callback callback;
3111 
3112  VisitNull(Callback callback)
3113  : callback(std::move(callback)) {}
3114 
3115  VisitNull(Base base, Callback callback)
3116  : Base(std::move(base))
3117  , callback(std::move(callback)) {}
3118 
3119  void visitNull(const SourceLocation& source, Null value) {
3120  callback(source, value);
3121  }
3122 
3123  template <typename NewBase>
3124  [[nodiscard]] auto operator|(NewBase other) && {
3125  return VisitNull<NewBase, Callback>{std::move(other), std::move(callback)};
3126  }
3127 };
3128 
3129 template <typename Base, typename Callback>
3130 struct VisitBoolean : Base {
3131  [[no_unique_address]] Callback callback;
3132 
3133  VisitBoolean(Callback callback)
3134  : callback(std::move(callback)) {}
3135 
3136  VisitBoolean(Base base, Callback callback)
3137  : Base(std::move(base))
3138  , callback(std::move(callback)) {}
3139 
3140  void visitBoolean(const SourceLocation& source, Boolean value) {
3141  callback(source, value);
3142  }
3143 
3144  template <typename NewBase>
3145  [[nodiscard]] auto operator|(NewBase other) && {
3146  return VisitBoolean<NewBase, Callback>{std::move(other), std::move(callback)};
3147  }
3148 };
3149 
3150 template <typename Base, typename Callback>
3151 struct VisitString : Base {
3152  [[no_unique_address]] Callback callback;
3153 
3154  VisitString(Callback callback)
3155  : callback(std::move(callback)) {}
3156 
3157  VisitString(Base base, Callback callback)
3158  : Base(std::move(base))
3159  , callback(std::move(callback)) {}
3160 
3161  void visitString(const SourceLocation& source, String&& value) {
3162  callback(source, std::move(value));
3163  }
3164 
3165  template <typename NewBase>
3166  [[nodiscard]] auto operator|(NewBase other) && {
3167  return VisitString<NewBase, Callback>{std::move(other), std::move(callback)};
3168  }
3169 };
3170 
3171 template <typename Base, typename Callback>
3172 struct VisitNumber : Base {
3173  [[no_unique_address]] Callback callback;
3174 
3175  VisitNumber(Callback callback)
3176  : callback(std::move(callback)) {}
3177 
3178  VisitNumber(Base base, Callback callback)
3179  : Base(std::move(base))
3180  , callback(std::move(callback)) {}
3181 
3182  void visitNumber(const SourceLocation& source, Number value) {
3183  callback(source, value);
3184  }
3185 
3186  template <typename NewBase>
3187  [[nodiscard]] auto operator|(NewBase other) && {
3188  return VisitNumber<NewBase, Callback>{std::move(other), std::move(callback)};
3189  }
3190 };
3191 
3192 template <typename Base, typename Callback>
3193 struct VisitObject : Base {
3194  [[no_unique_address]] Callback callback;
3195 
3196  VisitObject(Callback callback)
3197  : callback(std::move(callback)) {}
3198 
3199  VisitObject(Base base, Callback callback)
3200  : Base(std::move(base))
3201  , callback(std::move(callback)) {}
3202 
3203  void visitObject(const SourceLocation& source, auto& parser) {
3204  callback(source, parser);
3205  }
3206 
3207  template <typename NewBase>
3208  [[nodiscard]] auto operator|(NewBase other) && {
3209  return VisitObject<NewBase, Callback>{std::move(other), std::move(callback)};
3210  }
3211 };
3212 
3213 template <typename Base, typename Callback>
3214 struct VisitArray : Base {
3215  [[no_unique_address]] Callback callback;
3216 
3217  VisitArray(Callback callback)
3218  : callback(std::move(callback)) {}
3219 
3220  VisitArray(Base base, Callback callback)
3221  : Base(std::move(base))
3222  , callback(std::move(callback)) {}
3223 
3224  void visitArray(const SourceLocation& source, auto& parser) {
3225  callback(source, parser);
3226  }
3227 
3228  template <typename NewBase>
3229  [[nodiscard]] auto operator|(NewBase other) && {
3230  return VisitArray<NewBase, Callback>{std::move(other), std::move(callback)};
3231  }
3232 };
3233 
3234 template <typename Base, typename Callback>
3235 struct VisitProperty : Base {
3236  [[no_unique_address]] Callback callback;
3237 
3238  VisitProperty(Callback callback)
3239  : callback(std::move(callback)) {}
3240 
3241  VisitProperty(Base base, Callback callback)
3242  : Base(std::move(base))
3243  , callback(std::move(callback)) {}
3244 
3245  void visitProperty(const SourceLocation& source, String&& key, auto& parser) {
3246  callback(source, std::move(key), parser);
3247  }
3248 
3249  template <typename NewBase>
3250  [[nodiscard]] auto operator|(NewBase other) && {
3251  return VisitProperty<NewBase, Callback>{std::move(other), std::move(callback)};
3252  }
3253 };
3254 
3255 } // namespace detail
3256 
3279 template <typename Callback>
3280 [[nodiscard]] inline auto onNull(Callback callback) {
3281  return detail::VisitNull<detail::NoVisitor, Callback>{std::move(callback)};
3282 }
3283 
3306 template <typename Callback>
3307 [[nodiscard]] inline auto onBoolean(Callback callback) {
3308  return detail::VisitBoolean<detail::NoVisitor, Callback>{std::move(callback)};
3309 }
3310 
3333 template <typename Callback>
3334 [[nodiscard]] inline auto onString(Callback callback) {
3335  return detail::VisitString<detail::NoVisitor, Callback>{std::move(callback)};
3336 }
3337 
3360 template <typename Callback>
3361 [[nodiscard]] inline auto onNumber(Callback callback) {
3362  return detail::VisitNumber<detail::NoVisitor, Callback>{std::move(callback)};
3363 }
3364 
3387 template <typename Callback>
3388 [[nodiscard]] inline auto onObject(Callback callback) {
3389  return detail::VisitObject<detail::NoVisitor, Callback>{std::move(callback)};
3390 }
3391 
3414 template <typename Callback>
3415 [[nodiscard]] inline auto onArray(Callback callback) {
3416  return detail::VisitArray<detail::NoVisitor, Callback>{std::move(callback)};
3417 }
3418 
3434 template <typename Callback>
3435 [[nodiscard]] inline auto onProperty(Callback callback) {
3436  return detail::VisitProperty<detail::NoVisitor, Callback>{std::move(callback)};
3437 }
3438 
3439 namespace detail {
3440 
3441 template <typename T>
3442 concept nullable = //
3443  !std::is_arithmetic_v<T> && //
3444  requires(const T& value) {
3445  static_cast<bool>(value);
3446  static_cast<bool>(!value);
3447  T{};
3448  };
3449 
3450 template <typename T>
3451 concept serializable_as_string = //
3452  std::is_same_v<T, String> || //
3453  requires(const T& value) { std::string_view{value}; } || //
3454  requires(const T& value) { std::u8string_view{value}; } || //
3455  requires(const T& value) { std::u16string_view{value}; } || //
3456  requires(const T& value) { std::u32string_view{value}; } || //
3457  requires(const T& value) { std::wstring_view{value}; };
3458 
3459 template <typename T>
3460 concept deserializable_as_string = //
3461  std::is_same_v<T, String> || //
3462  requires(T& value) { value = std::string{}; } || //
3463  requires(T& value) { value = std::u8string{}; } || //
3464  requires(T& value) { value = std::u16string{}; } || //
3465  requires(T& value) { value = std::u32string{}; } || //
3466  requires(T& value) { value = std::wstring{}; };
3467 
3468 template <typename T>
3469 concept serializable_as_object = //
3470  std::is_same_v<T, Object> || //
3471  requires(Writer& writer, const T& value) {
3472  writer.writeString(std::begin(value)->first);
3473  writer.serialize(std::begin(value)->second);
3474  };
3475 
3476 template <typename T>
3477 concept deserializable_as_object = //
3478  std::is_same_v<T, Object> || //
3479  requires(Reader& reader, T& value) {
3480  value.clear();
3481  std::remove_cvref_t<decltype(std::begin(value)->first)>{};
3482  std::remove_cvref_t<decltype(std::begin(value)->second)>{};
3483  reader.readString(std::begin(value)->first);
3484  reader.deserialize(std::begin(value)->second);
3485  value.emplace(std::remove_cvref_t<decltype(std::begin(value)->first)>{}, std::remove_cvref_t<decltype(std::begin(value)->second)>{});
3486  };
3487 
3488 template <typename T>
3489 concept serializable_as_array = //
3490  std::is_same_v<T, Array> || //
3491  requires(Writer& writer, const T& value) { writer.serialize(*std::begin(value)); };
3492 
3493 template <typename T>
3494 concept deserializable_as_array = //
3495  std::is_same_v<T, Array> || //
3496  requires(Reader& reader, T& value) {
3497  value.clear();
3498  std::remove_cvref_t<decltype(*std::begin(value))>{};
3499  reader.deserialize(*std::begin(value));
3500  value.push_back(std::remove_cvref_t<decltype(*std::begin(value))>{});
3501  };
3502 
3503 template <typename T>
3504 concept serializable_as_optional = //
3505  !std::is_pointer_v<T> && //
3506  requires(Writer& writer, const T& value) {
3507  static_cast<bool>(value);
3508  writer.serialize(*value);
3509  };
3510 
3511 template <typename T>
3512 concept deserializable_as_optional = //
3513  !std::is_pointer_v<T> && //
3514  requires(Reader& reader, T& value, std::remove_cvref_t<decltype(*value)> result) {
3515  value = T{};
3516  std::remove_cvref_t<decltype(*value)>{};
3517  reader.deserialize(result);
3518  value = std::move(result);
3519  };
3520 
3521 template <typename T>
3522 inline constexpr bool always_false_v = false;
3523 
3524 template <typename T, typename ObjectPropertyFilter, typename ArrayItemFilter>
3525 inline std::size_t getRecursiveSize(const T& value, ObjectPropertyFilter objectPropertyFilter, ArrayItemFilter arrayItemFilter) {
3526  if constexpr (std::is_same_v<T, Value>) {
3527  return match(value)([&](const auto& v) -> std::size_t { return getRecursiveSize(v, objectPropertyFilter, arrayItemFilter); });
3528  } else if constexpr (serializable_as_string<T>) {
3529  return 1;
3530  } else if constexpr (serializable_as_object<T>) {
3531  if constexpr (nullable<T>) {
3532  if (!value) {
3533  return 1;
3534  }
3535  }
3536  return std::accumulate(std::begin(value), std::end(value), std::size_t{1}, [&](std::size_t count, const auto& kv) -> std::size_t {
3537  if (objectPropertyFilter(kv)) {
3538  count += getRecursiveSize(kv.second, {}, {});
3539  }
3540  return count;
3541  });
3542  } else if constexpr (serializable_as_array<T>) {
3543  if constexpr (nullable<T>) {
3544  if (!value) {
3545  return 1;
3546  }
3547  }
3548  return std::accumulate(std::begin(value), std::end(value), std::size_t{1}, [&](std::size_t count, const auto& v) -> std::size_t {
3549  if (arrayItemFilter(v)) {
3550  count += getRecursiveSize(v, {}, {});
3551  }
3552  return count;
3553  });
3554  } else if constexpr (serializable_as_optional<T>) {
3555  return 1;
3556  } else if constexpr (std::is_aggregate_v<T>) {
3557  if constexpr (nullable<T>) {
3558  if (!value) {
3559  return 1;
3560  }
3561  }
3562  std::size_t result = 1;
3563  reflection::forEach(reflection::fields(value), [&](const auto& v) -> void { result += getRecursiveSize(v, {}, {}); });
3564  return result;
3565  } else {
3566  return 1;
3567  }
3568 }
3569 
3570 } // namespace detail
3571 
3572 template <typename T>
3573 struct Serializer {
3574  void serialize(Writer& writer, const T& value) {
3575  if constexpr (detail::nullable<T>) {
3576  if (!value) {
3577  writer.writeNull();
3578  return;
3579  }
3580  }
3581  if constexpr (detail::serializable_as_string<T>) {
3582  writer.writeString(value);
3583  } else if constexpr (detail::serializable_as_object<T>) {
3584  writer.writeObject(value);
3585  } else if constexpr (detail::serializable_as_array<T>) {
3586  writer.writeArray(value);
3587  } else if constexpr (detail::serializable_as_optional<T>) {
3588  writer.writeOptional(value);
3589  } else if constexpr (std::is_aggregate_v<T>) {
3590  writer.writeAggregate(value);
3591  } else {
3592  static_assert(detail::always_false_v<T>, "JSON serialization is not implemented for the given type.");
3593  }
3594  }
3595 };
3596 
3597 template <typename T>
3599  void deserialize(Reader& reader, T& value) {
3600  if constexpr (detail::serializable_as_string<T>) {
3601  reader.readString(value);
3602  } else if constexpr (detail::serializable_as_object<T>) {
3603  reader.readObject(value);
3604  } else if constexpr (detail::serializable_as_array<T>) {
3605  reader.readArray(value);
3606  } else if constexpr (detail::serializable_as_optional<T>) {
3607  reader.readOptional(value);
3608  } else if constexpr (std::is_aggregate_v<T>) {
3609  reader.readAggregate(value);
3610  } else {
3611  static_assert(detail::always_false_v<T>, "JSON deserialization is not implemented for the given type.");
3612  }
3613  }
3614 };
3615 
3617 template <>
3618 struct Serializer<Null> {
3619  void serialize(Writer& writer, Null) {
3620  writer.writeNull();
3621  }
3622 };
3623 
3624 template <>
3625 struct Serializer<std::nullptr_t> {
3626  void serialize(Writer& writer, std::nullptr_t) {
3627  writer.writeNull();
3628  }
3629 };
3630 
3631 template <>
3632 struct Serializer<Boolean> {
3633  void serialize(Writer& writer, Boolean value) {
3634  writer.writeBoolean(value);
3635  }
3636 };
3637 
3638 template <detail::number Num>
3639 struct Serializer<Num> {
3640  void serialize(Writer& writer, Num value) {
3641  writer.writeNumber(static_cast<Number>(value));
3642  }
3643 };
3644 
3645 template <>
3646 struct Serializer<char> {
3647  void serialize(Writer& writer, char value) {
3648  writer.writeString(std::string_view{&value, 1});
3649  }
3650 };
3651 
3652 template <>
3653 struct Serializer<char8_t> {
3654  void serialize(Writer& writer, char8_t value) {
3655  writer.writeString(std::u8string_view{&value, 1});
3656  }
3657 };
3658 
3659 template <>
3660 struct Serializer<char16_t> {
3661  void serialize(Writer& writer, char16_t value) {
3662  writer.writeString(std::u16string_view{&value, 1});
3663  }
3664 };
3665 
3666 template <>
3667 struct Serializer<char32_t> {
3668  void serialize(Writer& writer, char32_t value) {
3669  writer.writeString(std::u32string_view{&value, 1});
3670  }
3671 };
3672 
3673 template <>
3674 struct Serializer<wchar_t> {
3675  void serialize(Writer& writer, wchar_t value) {
3676  writer.writeString(std::wstring_view{&value, 1});
3677  }
3678 };
3679 
3680 template <>
3681 struct Serializer<Value> {
3682  void serialize(Writer& writer, const Value& value) {
3683  match(value)([&](const auto& v) -> void { writer.serialize(v); });
3684  }
3685 };
3687 
3689 template <>
3690 struct Deserializer<Null> {
3691  void deserialize(Reader& reader, Null&) {
3692  reader.readNull();
3693  }
3694 };
3695 
3696 template <>
3697 struct Deserializer<std::nullptr_t> {
3698  void deserialize(Reader& reader, std::nullptr_t&) {
3699  reader.readNull();
3700  }
3701 };
3702 
3703 template <>
3704 struct Deserializer<Boolean> {
3705  void deserialize(Reader& reader, Boolean& value) {
3706  reader.readBoolean(value);
3707  }
3708 };
3709 
3710 template <detail::number Num>
3711 struct Deserializer<Num> {
3712  void deserialize(Reader& reader, Num& value) {
3713  reader.readNumber(value);
3714  }
3715 };
3716 
3717 template <>
3718 struct Deserializer<char> {
3719  void deserialize(Reader& reader, char& value) {
3720  String string{};
3721  const SourceLocation source = reader.readString(string);
3722  if (string.size() != 1) {
3723  throw Error{"Expected only a single character.", source};
3724  }
3725  value = string.front();
3726  }
3727 };
3728 
3729 template <>
3730 struct Deserializer<char8_t> {
3731  void deserialize(Reader& reader, char8_t& value) {
3732  String string{};
3733  const SourceLocation source = reader.readString(string);
3734  if (string.size() != sizeof(char8_t)) {
3735  throw Error{"Expected only a single UTF-8 code unit.", source};
3736  }
3737  std::memcpy(&value, string.data(), sizeof(char8_t));
3738  }
3739 };
3740 
3741 template <>
3742 struct Deserializer<char16_t> {
3743  void deserialize(Reader& reader, char16_t& value) {
3744  String string{};
3745  const SourceLocation source = reader.readString(string);
3746  if (string.size() != sizeof(char16_t)) {
3747  throw Error{"Expected only a single UTF-16 code unit.", source};
3748  }
3749  std::memcpy(&value, string.data(), sizeof(char16_t));
3750  }
3751 };
3752 
3753 template <>
3754 struct Deserializer<char32_t> {
3755  void deserialize(Reader& reader, char32_t& value) {
3756  String string{};
3757  const SourceLocation source = reader.readString(string);
3758  if (string.size() != sizeof(char32_t)) {
3759  throw Error{"Expected only a single UTF-32 code unit.", source};
3760  }
3761  std::memcpy(&value, string.data(), sizeof(char32_t));
3762  }
3763 };
3764 
3765 template <>
3766 struct Deserializer<wchar_t> {
3767  void deserialize(Reader& reader, wchar_t& value) {
3768  String string{};
3769  const SourceLocation source = reader.readString(string);
3770  if (string.size() != sizeof(wchar_t)) {
3771  throw Error{"Expected only a single wide character.", source};
3772  }
3773  std::memcpy(&value, string.data(), sizeof(wchar_t));
3774  }
3775 };
3776 
3777 template <>
3778 struct Deserializer<Value> {
3779  void deserialize(Reader& reader, Value& value) {
3780  reader.readValue(value);
3781  }
3782 };
3784 
3785 inline Object::Object() noexcept = default;
3786 
3787 inline Object::~Object() = default;
3788 
3789 inline Object::Object(const Object& other) = default;
3790 
3791 inline Object::Object(Object&& other) noexcept = default;
3792 
3793 inline Object& Object::operator=(const Object& other) = default;
3794 
3795 inline Object& Object::operator=(Object&& other) noexcept = default;
3796 
3797 template <typename InputIt>
3798 inline Object::Object(InputIt first, InputIt last)
3799  : membersSortedByName(first, last) {
3800  std::sort(membersSortedByName.begin(), membersSortedByName.end(), Compare{});
3801 }
3802 
3803 inline Object::Object(std::initializer_list<value_type> ilist)
3804  : Object(ilist.begin(), ilist.end()) {}
3805 
3806 inline Object& Object::operator=(std::initializer_list<value_type> ilist) {
3807  membersSortedByName = ilist;
3808  std::sort(membersSortedByName.begin(), membersSortedByName.end(), Compare{});
3809  return *this;
3810 }
3811 
3812 inline Value& Object::at(std::string_view name) {
3813  if (const auto it = find(name); it != end()) {
3814  return it->second;
3815  }
3816  throw std::out_of_range{"JSON object does not contain a member with the given name."};
3817 }
3818 
3819 inline const Value& Object::at(std::string_view name) const {
3820  if (const auto it = find(name); it != end()) {
3821  return it->second;
3822  }
3823  throw std::out_of_range{"JSON object does not contain a member with the given name."};
3824 }
3825 
3826 inline Value& Object::operator[](const String& k) {
3827  return try_emplace(k).first->second;
3828 }
3829 
3831  return try_emplace(std::move(k)).first->second;
3832 }
3833 
3834 inline Object::iterator Object::begin() noexcept {
3835  return membersSortedByName.begin();
3836 }
3837 
3838 inline Object::const_iterator Object::begin() const noexcept {
3839  return membersSortedByName.begin();
3840 }
3841 
3842 inline Object::const_iterator Object::cbegin() const noexcept {
3843  return membersSortedByName.cbegin();
3844 }
3845 
3846 inline Object::iterator Object::end() noexcept {
3847  return membersSortedByName.end();
3848 }
3849 
3850 inline Object::const_iterator Object::end() const noexcept {
3851  return membersSortedByName.end();
3852 }
3853 
3854 inline Object::const_iterator Object::cend() const noexcept {
3855  return membersSortedByName.cend();
3856 }
3857 
3859  return membersSortedByName.rbegin();
3860 }
3861 
3863  return membersSortedByName.rbegin();
3864 }
3865 
3867  return membersSortedByName.crbegin();
3868 }
3869 
3871  return membersSortedByName.rend();
3872 }
3873 
3875  return membersSortedByName.rend();
3876 }
3877 
3879  return membersSortedByName.crend();
3880 }
3881 
3882 inline bool Object::empty() const noexcept {
3883  return membersSortedByName.empty();
3884 }
3885 
3886 inline Object::size_type Object::size() const noexcept {
3887  return membersSortedByName.size();
3888 }
3889 
3890 inline Object::size_type Object::max_size() const noexcept {
3891  return membersSortedByName.max_size();
3892 }
3893 
3894 inline void Object::clear() noexcept {
3895  membersSortedByName.clear();
3896 }
3897 
3898 template <typename P>
3899 inline std::pair<Object::iterator, bool> Object::insert(P&& value) {
3900  return emplace(std::forward<P>(value));
3901 }
3902 
3903 template <typename P>
3905  return emplace_hint(pos, std::forward<P>(value));
3906 }
3907 
3908 template <typename InputIt>
3909 inline void Object::insert(InputIt first, InputIt last) {
3910  while (first != last) {
3911  insert(*first++);
3912  }
3913 }
3914 
3915 inline void Object::insert(std::initializer_list<Object::value_type> ilist) {
3916  insert(ilist.begin(), ilist.end());
3917 }
3918 
3919 template <typename... Args>
3920 inline std::pair<Object::iterator, bool> Object::emplace(Args&&... args) {
3921  value_type value{std::forward<Args>(args)...};
3922  const auto [first, last] = equal_range(value.first);
3923  if (first != last) {
3924  return {first, false};
3925  }
3926  const auto it = membersSortedByName.insert(last, std::move(value));
3927  return {it, true};
3928 }
3929 
3930 template <typename... Args>
3932  return emplace(std::forward<Args>(args)...);
3933 }
3934 
3935 template <typename... Args>
3936 inline std::pair<Object::iterator, bool> Object::try_emplace(const String& k, Args&&... args) {
3937  const auto [first, last] = equal_range(k);
3938  if (first != last) {
3939  return {first, false};
3940  }
3941  const auto it = membersSortedByName.emplace(last, std::piecewise_construct, std::forward_as_tuple(k), std::forward_as_tuple(std::forward<Args>(args)...));
3942  return {it, true};
3943 }
3944 
3945 template <typename... Args>
3946 inline std::pair<Object::iterator, bool> Object::try_emplace(String&& k, Args&&... args) {
3947  const auto [first, last] = equal_range(k);
3948  if (first != last) {
3949  return {first, false};
3950  }
3951  const auto it = membersSortedByName.emplace(last, std::piecewise_construct, std::forward_as_tuple(std::move(k)), std::forward_as_tuple(std::forward<Args>(args)...));
3952  return {it, true};
3953 }
3954 
3955 template <typename... Args>
3956 inline Object::iterator Object::try_emplace(const_iterator, const String& k, Args&&... args) {
3957  return try_emplace(k, std::forward<Args>(args)...);
3958 }
3959 
3960 template <typename... Args>
3962  return try_emplace(std::move(k), std::forward<Args>(args)...);
3963 }
3964 
3966  return membersSortedByName.erase(pos);
3967 }
3968 
3969 inline Object::size_type Object::erase(std::string_view name) {
3970  const auto [first, last] = equal_range(name);
3971  const size_type count = static_cast<size_type>(last - first);
3972  membersSortedByName.erase(first, last);
3973  return count;
3974 }
3975 
3976 inline void Object::swap(Object& other) noexcept {
3977  membersSortedByName.swap(other.membersSortedByName);
3978 }
3979 
3980 inline void swap(Object& a, Object& b) noexcept {
3981  a.swap(b);
3982 }
3983 
3984 inline Object::size_type Object::count(std::string_view name) const noexcept {
3985  const auto [first, last] = equal_range(name);
3986  return static_cast<size_type>(last - first);
3987 }
3988 
3989 inline bool Object::contains(std::string_view name) const noexcept {
3990  return count(name) > 0;
3991 }
3992 
3993 inline Object::iterator Object::find(std::string_view name) noexcept {
3994  if (const auto [first, last] = equal_range(name); first != last) {
3995  return first;
3996  }
3997  return end();
3998 }
3999 
4000 inline Object::const_iterator Object::find(std::string_view name) const noexcept {
4001  if (const auto [first, last] = equal_range(name); first != last) {
4002  return first;
4003  }
4004  return end();
4005 }
4006 
4007 inline std::pair<Object::iterator, Object::iterator> Object::equal_range(std::string_view name) noexcept {
4008  return std::equal_range(membersSortedByName.begin(), membersSortedByName.end(), name, Compare{});
4009 }
4010 
4011 inline std::pair<Object::const_iterator, Object::const_iterator> Object::equal_range(std::string_view name) const noexcept {
4012  return std::equal_range(membersSortedByName.begin(), membersSortedByName.end(), name, Compare{});
4013 }
4014 
4015 inline Object::iterator Object::lower_bound(std::string_view name) noexcept {
4016  return std::lower_bound(membersSortedByName.begin(), membersSortedByName.end(), name, Compare{});
4017 }
4018 
4019 inline Object::const_iterator Object::lower_bound(std::string_view name) const noexcept {
4020  return std::lower_bound(membersSortedByName.begin(), membersSortedByName.end(), name, Compare{});
4021 }
4022 
4023 inline Object::iterator Object::upper_bound(std::string_view name) noexcept {
4024  return std::upper_bound(membersSortedByName.begin(), membersSortedByName.end(), name, Compare{});
4025 }
4026 
4027 inline Object::const_iterator Object::upper_bound(std::string_view name) const noexcept {
4028  return std::upper_bound(membersSortedByName.begin(), membersSortedByName.end(), name, Compare{});
4029 }
4030 
4031 inline bool Object::operator==(const Object& other) const noexcept {
4032  return membersSortedByName == other.membersSortedByName;
4033 }
4034 
4035 inline std::partial_ordering Object::operator<=>(const Object& other) const noexcept {
4036  return std::compare_partial_order_fallback(membersSortedByName, other.membersSortedByName);
4037 }
4038 
4039 template <typename Predicate>
4040 inline Object::size_type erase_if(Object& container, Predicate predicate) {
4041  return std::erase_if(container.membersSortedByName, predicate);
4042 }
4043 
4044 inline bool Object::Compare::operator()(const value_type& a, const value_type& b) const noexcept {
4045  return a.first < b.first;
4046 }
4047 
4048 inline bool Object::Compare::operator()(const value_type& a, std::string_view b) const noexcept {
4049  return a.first < b;
4050 }
4051 
4052 inline bool Object::Compare::operator()(std::string_view a, const value_type& b) const noexcept {
4053  return a < b.first;
4054 }
4055 
4056 inline bool Object::Compare::operator()(std::string_view a, std::string_view b) const noexcept {
4057  return a < b;
4058 }
4059 
4060 inline Array::Array() noexcept = default;
4061 
4062 inline Array::~Array() = default;
4063 
4064 inline Array::Array(const Array& other) = default;
4065 
4066 inline Array::Array(Array&& other) noexcept = default;
4067 
4068 inline Array& Array::operator=(const Array& other) = default;
4069 
4070 inline Array& Array::operator=(Array&& other) noexcept = default;
4071 
4072 template <typename InputIt>
4073 inline Array::Array(InputIt first, InputIt last)
4074  : values(first, last) {}
4075 
4076 inline Array::Array(size_type count, const Value& value)
4077  : values(count, value) {}
4078 
4079 inline Array::Array(std::initializer_list<value_type> ilist)
4080  : values(ilist) {}
4081 
4082 inline Array& Array::operator=(std::initializer_list<value_type> ilist) {
4083  values = ilist;
4084  return *this;
4085 }
4086 
4087 inline void Array::swap(Array& other) noexcept {
4088  values.swap(other.values);
4089 }
4090 
4091 inline void swap(Array& a, Array& b) noexcept {
4092  a.swap(b);
4093 }
4094 
4095 inline Array::pointer Array::data() noexcept {
4096  return values.data();
4097 }
4098 
4099 inline Array::const_pointer Array::data() const noexcept {
4100  return values.data();
4101 }
4102 
4103 inline Array::size_type Array::size() const noexcept {
4104  return values.size();
4105 }
4106 
4107 inline Array::size_type Array::max_size() const noexcept {
4108  return values.max_size();
4109 }
4110 
4111 inline Array::size_type Array::capacity() const noexcept {
4112  return values.capacity();
4113 }
4114 
4115 inline bool Array::empty() const noexcept {
4116  return values.empty();
4117 }
4118 
4119 inline Array::iterator Array::begin() noexcept {
4120  return values.begin();
4121 }
4122 
4123 inline Array::const_iterator Array::begin() const noexcept {
4124  return values.begin();
4125 }
4126 
4127 inline Array::const_iterator Array::cbegin() const noexcept {
4128  return values.cbegin();
4129 }
4130 
4131 inline Array::iterator Array::end() noexcept {
4132  return values.end();
4133 }
4134 
4135 inline Array::const_iterator Array::end() const noexcept {
4136  return values.end();
4137 }
4138 
4139 inline Array::const_iterator Array::cend() const noexcept {
4140  return values.cend();
4141 }
4142 
4144  return values.rbegin();
4145 }
4146 
4148  return values.rbegin();
4149 }
4150 
4152  return values.crbegin();
4153 }
4154 
4156  return values.rend();
4157 }
4158 
4160  return values.rend();
4161 }
4162 
4164  return values.crend();
4165 }
4166 
4168  return values.front();
4169 }
4170 
4172  return values.front();
4173 }
4174 
4176  return values.back();
4177 }
4178 
4180  return values.back();
4181 }
4182 
4184  return values.at(pos);
4185 }
4186 
4188  return values.at(pos);
4189 }
4190 
4192  return values[pos];
4193 }
4194 
4196  return values[pos];
4197 }
4198 
4199 inline bool Array::operator==(const Array& other) const {
4200  return values == other.values;
4201 }
4202 
4203 inline std::partial_ordering Array::operator<=>(const Array& other) const noexcept {
4204  return std::compare_partial_order_fallback(values, other.values);
4205 }
4206 
4207 template <typename U>
4208 inline Array::size_type erase(Array& container, const U& value) {
4209  return std::erase(container.values, value);
4210 }
4211 
4212 template <typename Predicate>
4213 inline Array::size_type erase_if(Array& container, Predicate predicate) {
4214  return std::erase_if(container.values, predicate);
4215 }
4216 
4217 inline void Array::clear() noexcept {
4218  values.clear();
4219 }
4220 
4221 inline void Array::reserve(size_type newCap) {
4222  values.reserve(newCap);
4223 }
4224 
4225 inline void Array::shrink_to_fit() {
4226  values.shrink_to_fit();
4227 }
4228 
4230  return values.insert(pos, value);
4231 }
4232 
4234  return values.insert(pos, std::move(value));
4235 }
4236 
4237 inline Array::iterator Array::insert(const_iterator pos, size_type count, const Value& value) {
4238  return values.insert(pos, count, value);
4239 }
4240 
4241 template <typename InputIt>
4242 inline Array::iterator Array::insert(const_iterator pos, InputIt first, InputIt last) {
4243  return values.insert(pos, first, last);
4244 }
4245 
4246 inline Array::iterator Array::insert(const_iterator pos, std::initializer_list<value_type> ilist) {
4247  return values.insert(pos, ilist);
4248 }
4249 
4250 template <typename... Args>
4251 inline Array::iterator Array::emplace(const_iterator pos, Args&&... args) {
4252  return values.emplace(pos, std::forward<Args>(args)...);
4253 }
4254 
4256  return values.erase(pos);
4257 }
4258 
4260  return values.erase(first, last);
4261 }
4262 
4263 inline void Array::push_back(const Value& value) {
4264  values.push_back(value);
4265 }
4266 
4267 inline void Array::push_back(Value&& value) {
4268  values.push_back(std::move(value));
4269 }
4270 
4271 template <typename... Args>
4272 inline Array::reference Array::emplace_back(Args&&... args) {
4273  return values.emplace_back(std::forward<Args>(args)...);
4274 }
4275 
4276 inline void Array::pop_back() {
4277  values.pop_back();
4278 }
4279 
4280 inline void Array::resize(size_type count) {
4281  values.resize(count);
4282 }
4283 
4284 inline void Array::resize(size_type count, const Value& value) {
4285  values.resize(count, value);
4286 }
4287 
4288 inline Value Value::parse(std::u8string_view jsonString) {
4289  unicode::UTF8View codePoints{jsonString};
4290  return Parser<const char8_t*>{{codePoints.begin(), codePoints.end(), {.lineNumber = 1, .columnNumber = 1}}}.parseFile();
4291 }
4292 
4293 inline Value Value::parse(std::string_view jsonString) {
4294  static_assert(sizeof(char) == sizeof(char8_t));
4295  static_assert(alignof(char) == alignof(char8_t));
4296  return parse(std::u8string_view{reinterpret_cast<const char8_t*>(jsonString.data()), jsonString.size()});
4297 }
4298 
4299 inline std::string Value::toString(const SerializationOptions& options) const {
4300  std::ostringstream stream{};
4301  json::serialize(stream, *this, options);
4302  return std::move(stream).str();
4303 }
4304 
4305 } // namespace donut::json
4306 
4307 #endif
Tagged union value type that holds a value of one of the given types.
Definition: Variant.hpp:291
return std::move(as< variant_index_v< T, Variant >>())
JSON array type whose API mimics that of std::vector<Value>.
Definition: json.hpp:318
void push_back(const Value &value)
Definition: json.hpp:4263
void resize(size_type count)
Definition: json.hpp:4280
void pop_back()
Definition: json.hpp:4276
const_reverse_iterator crend() const noexcept
Definition: json.hpp:4163
reverse_iterator rend() noexcept
Definition: json.hpp:4155
size_type capacity() const noexcept
Definition: json.hpp:4111
reference back()
Definition: json.hpp:4175
iterator begin() noexcept
Definition: json.hpp:4119
reference at(size_type pos)
Definition: json.hpp:4183
void reserve(size_type newCap)
Definition: json.hpp:4221
size_type size() const noexcept
Definition: json.hpp:4103
typename std::vector< value_type >::size_type size_type
Definition: json.hpp:321
size_type max_size() const noexcept
Definition: json.hpp:4107
void swap(Array &other) noexcept
Definition: json.hpp:4087
iterator insert(const_iterator pos, const Value &value)
Definition: json.hpp:4229
void shrink_to_fit()
Definition: json.hpp:4225
typename std::vector< value_type >::const_reference const_reference
Definition: json.hpp:324
typename std::vector< value_type >::reverse_iterator reverse_iterator
Definition: json.hpp:329
reference operator[](size_type pos)
Definition: json.hpp:4191
typename std::vector< value_type >::const_pointer const_pointer
Definition: json.hpp:326
reference front()
Definition: json.hpp:4167
typename std::vector< value_type >::difference_type difference_type
Definition: json.hpp:322
const_iterator cbegin() const noexcept
Definition: json.hpp:4127
const_reverse_iterator crbegin() const noexcept
Definition: json.hpp:4151
pointer data() noexcept
Definition: json.hpp:4095
Array & operator=(const Array &other)
void clear() noexcept
Definition: json.hpp:4217
typename std::vector< value_type >::const_iterator const_iterator
Definition: json.hpp:328
std::partial_ordering operator<=>(const Array &other) const noexcept
Definition: json.hpp:4203
iterator end() noexcept
Definition: json.hpp:4131
typename std::vector< value_type >::reference reference
Definition: json.hpp:323
bool empty() const noexcept
Definition: json.hpp:4115
iterator emplace(const_iterator pos, Args &&... args)
Definition: json.hpp:4251
bool operator==(const Array &other) const
Definition: json.hpp:4199
typename std::vector< value_type >::iterator iterator
Definition: json.hpp:327
reverse_iterator rbegin() noexcept
Definition: json.hpp:4143
friend size_type erase_if(Array &container, Predicate predicate)
Definition: json.hpp:4213
typename std::vector< value_type >::pointer pointer
Definition: json.hpp:325
reference emplace_back(Args &&... args)
Definition: json.hpp:4272
friend size_type erase(Array &container, const U &value)
Definition: json.hpp:4208
typename std::vector< value_type >::const_reverse_iterator const_reverse_iterator
Definition: json.hpp:330
const_iterator cend() const noexcept
Definition: json.hpp:4139
Lexical analyzer for scanning and tokenizing input in the JSON5 format.
Definition: json.hpp:715
Token scan()
Scan and consume the next token from the input.
Definition: json.hpp:743
Lexer(unicode::UTF8Iterator< It > it, unicode::UTF8Sentinel end, const SourceLocation &source)
Construct a lexer with a Unicode iterator pair as input.
Definition: json.hpp:727
JSON object type whose API mimics that of std::multimap<String, Value>.
Definition: json.hpp:199
std::pair< iterator, iterator > equal_range(std::string_view name) noexcept
Definition: json.hpp:4007
iterator erase(const_iterator pos)
Definition: json.hpp:3965
const_iterator cbegin() const noexcept
Definition: json.hpp:3842
std::pair< iterator, bool > insert(P &&value)
Definition: json.hpp:3899
std::pair< iterator, bool > emplace(Args &&... args)
Definition: json.hpp:3920
typename std::vector< value_type >::pointer pointer
Definition: json.hpp:208
reverse_iterator rbegin() noexcept
Definition: json.hpp:3858
iterator upper_bound(std::string_view name) noexcept
Definition: json.hpp:4023
typename std::vector< value_type >::const_reference const_reference
Definition: json.hpp:207
std::pair< String, Value > value_type
Definition: json.hpp:203
typename std::vector< value_type >::iterator iterator
Definition: json.hpp:210
size_type size() const noexcept
Definition: json.hpp:3886
typename std::vector< value_type >::const_iterator const_iterator
Definition: json.hpp:211
const_reverse_iterator crend() const noexcept
Definition: json.hpp:3878
std::pair< iterator, bool > try_emplace(const String &k, Args &&... args)
Definition: json.hpp:3936
typename std::vector< value_type >::difference_type difference_type
Definition: json.hpp:205
const_reverse_iterator crbegin() const noexcept
Definition: json.hpp:3866
iterator emplace_hint(const_iterator hint, Args &&... args)
Definition: json.hpp:3931
void clear() noexcept
Definition: json.hpp:3894
Object & operator=(const Object &other)
iterator lower_bound(std::string_view name) noexcept
Definition: json.hpp:4015
iterator begin() noexcept
Definition: json.hpp:3834
iterator find(std::string_view name) noexcept
Definition: json.hpp:3993
Value & at(std::string_view name)
Definition: json.hpp:3812
String key_type
Definition: json.hpp:201
typename std::vector< value_type >::const_reverse_iterator const_reverse_iterator
Definition: json.hpp:213
void swap(Object &other) noexcept
Definition: json.hpp:3976
Value & operator[](const String &k)
Definition: json.hpp:3826
typename std::vector< value_type >::reverse_iterator reverse_iterator
Definition: json.hpp:212
size_type max_size() const noexcept
Definition: json.hpp:3890
const_iterator cend() const noexcept
Definition: json.hpp:3854
bool contains(std::string_view name) const noexcept
Definition: json.hpp:3989
typename std::vector< value_type >::reference reference
Definition: json.hpp:206
bool operator==(const Object &other) const noexcept
Definition: json.hpp:4031
friend size_type erase_if(Object &container, Predicate predicate)
Definition: json.hpp:4040
std::partial_ordering operator<=>(const Object &other) const noexcept
Definition: json.hpp:4035
size_type count(std::string_view name) const noexcept
Definition: json.hpp:3984
reverse_iterator rend() noexcept
Definition: json.hpp:3870
iterator end() noexcept
Definition: json.hpp:3846
typename std::vector< value_type >::size_type size_type
Definition: json.hpp:204
typename std::vector< value_type >::const_pointer const_pointer
Definition: json.hpp:209
bool empty() const noexcept
Definition: json.hpp:3882
Polymorphic interface for visitation-based parsing of JSON object properties.
Definition: json.hpp:1303
virtual void visitProperty(const SourceLocation &source, String &&key, Parser &parser)=0
Callback for each object property.
Polymorphic interface for visitation-based parsing of JSON values.
Definition: json.hpp:1137
virtual void visitString(const SourceLocation &source, String &&value)
Callback for values of type String.
Definition: json.hpp:1176
virtual void visitObject(const SourceLocation &source, Parser &parser)
Callback for objects.
Definition: json.hpp:1209
virtual void visitBoolean(const SourceLocation &source, Boolean value)
Callback for values of type Boolean.
Definition: json.hpp:1162
virtual void visitNumber(const SourceLocation &source, Number value)
Callback for values of type Number.
Definition: json.hpp:1190
virtual void visitArray(const SourceLocation &source, Parser &parser)
Callback for arrays.
Definition: json.hpp:1228
virtual void visitNull(const SourceLocation &source, Null value)
Callback for values of type Null.
Definition: json.hpp:1148
Syntactic analyzer for parsing input in the JSON5 format obtained from a json::Lexer.
Definition: json.hpp:1132
void skipFile()
Parse a single JSON value from the input and discard the result, then make sure the rest of the input...
Definition: json.hpp:1707
Value parseValue()
Read a single JSON value from the input.
Definition: json.hpp:1766
void parseObject(PropertyVisitor &visitor)
Read a single JSON object from the input and visit each of its properties.
Definition: json.hpp:1538
void parseFile(ValueVisitor &visitor)
Read a single JSON value from the input and visit it, then make sure the rest of the input only consi...
Definition: json.hpp:1444
const Token & peek() const
Peek the next token without advancing the internal state of the underlying lexer.
Definition: json.hpp:1980
void parseObject(Visitor visitor)
Definition: json.hpp:1684
void parseFile(Visitor visitor)
Definition: json.hpp:1668
Object parseObject()
Read a single JSON value of type Object from the input.
Definition: json.hpp:1887
Value parseFile()
Read a single JSON value from the input and make sure the rest of the input only consists of whitespa...
Definition: json.hpp:1739
void parseValue(ValueVisitor &visitor)
Read a single JSON value from the input and visit it.
Definition: json.hpp:1470
Parser(std::istream &stream) requires(std
Construct a parser with an input stream as input.
Definition: json.hpp:1413
void skipValue()
Parse a single JSON value from the input and discard the result.
Definition: json.hpp:1721
Parser(std::string_view jsonString) requires(std
Construct a parser with a contiguous string of bytes, interpreted as UTF-8, as input.
Definition: json.hpp:1405
Null parseNull()
Read a single JSON value of type Null from the input.
Definition: json.hpp:1798
void parseFile(ValueVisitor &&visitor)
Definition: json.hpp:1639
void parseArray(ValueVisitor &&visitor)
Definition: json.hpp:1660
Token eat()
Scan and consume the next token from the input.
Definition: json.hpp:1998
void parseArray(ValueVisitor &visitor)
Read a single JSON array from the input and visit each of its values.
Definition: json.hpp:1614
Array parseArray()
Read a single JSON value of type Array from the input.
Definition: json.hpp:1922
String parseString()
Read a single JSON value of type String from the input.
Definition: json.hpp:1839
Parser(std::streambuf *streambuf) requires(std
Construct a parser with an input stream buffer as input.
Definition: json.hpp:1421
Parser(unicode::UTF8View codePoints) requires(std
Construct a parser with a contiguous UTF-8 view as input.
Definition: json.hpp:1386
Boolean parseBoolean()
Read a single JSON value of type Boolean from the input.
Definition: json.hpp:1818
void parseValue(ValueVisitor &&visitor)
Definition: json.hpp:1646
Parser(Lexer< It > lexer)
Construct a parser with an existing lexer as input.
Definition: json.hpp:1377
void parseArray(Visitor visitor)
Definition: json.hpp:1692
Parser(std::u8string_view jsonString) requires(std
Construct a parser with a contiguous UTF-8 string as input.
Definition: json.hpp:1395
void parseObject(PropertyVisitor &&visitor)
Definition: json.hpp:1653
void parseValue(Visitor visitor)
Definition: json.hpp:1676
Number parseNumber()
Read a single JSON value of type Number from the input.
Definition: json.hpp:1859
void advance()
Advance the internal state of the underlying lexer by one token.
Definition: json.hpp:1957
JSON value type.
Definition: json.hpp:432
Value(detail::number auto value) noexcept
Construct a Number value with the given underlying value.
Definition: json.hpp:560
std::string toString(const SerializationOptions &options={}) const
Get a JSON string representation of the value.
Definition: json.hpp:4299
Value(std::string_view value)
Construct a String value with the given underlying value.
Definition: json.hpp:526
Value(const Array &value)
Construct an Array value with the given underlying value.
Definition: json.hpp:588
Value() noexcept=default
Construct a Null value.
Value(String &&value) noexcept
Construct a String value from the given underlying value.
Definition: json.hpp:505
Value(const Object &value)
Construct an Object value with the given underlying value.
Definition: json.hpp:570
Value(Object &&value) noexcept
Construct an Object value from the given underlying value.
Definition: json.hpp:578
Value(Boolean value) noexcept
Construct a Boolean value with the given underlying value.
Definition: json.hpp:487
static Value parse(std::u8string_view jsonString)
Parse a value of any JSON type from a UTF-8 JSON string.
Definition: json.hpp:4288
bool operator==(const Value &other) const
Compare this value to another for equality.
Definition: json.hpp:620
Value(Array &&value) noexcept
Construct an Array value from the given underlying value.
Definition: json.hpp:596
Value(const char *value)
Construct a String value with the given underlying value.
Definition: json.hpp:516
std::partial_ordering operator<=>(const Value &other) const
Compare this value to another.
Definition: json.hpp:631
Value(const char8_t *value)
Construct a String value with the given underlying value.
Definition: json.hpp:537
Value(const String &value)
Construct a String value with the given underlying value.
Definition: json.hpp:497
Value(std::u8string_view value)
Construct a String value with the given underlying value.
Definition: json.hpp:551
Value(std::nullptr_t) noexcept
Construct a Null value.
Definition: json.hpp:480
Iterator type for decoding Unicode code points from a UTF-8 string, wrapping an existing iterator for...
Definition: unicode.hpp:193
Non-owning view type for decoding Unicode code points from a contiguous UTF-8 string.
Definition: unicode.hpp:331
Definition: json.hpp:36
std::string String
JSON string type.
Definition: json.hpp:189
std::istream & operator>>(std::istream &stream, Value &value)
Read a JSON value from an input stream using the default deserialization options.
Definition: json.hpp:2163
Array::size_type erase(Array &container, const U &value)
Definition: json.hpp:4208
bool Boolean
JSON boolean type.
Definition: json.hpp:184
auto onNull(Callback callback)
Build a Parser::ValueVisitor that handles Null values with a given callback function.
Definition: json.hpp:3280
std::ostream & operator<<(std::ostream &stream, const Value &value)
Write a JSON value to an output stream using the default serialization options.
Definition: json.hpp:2142
TokenType
Type of a scanned JSON5 token.
Definition: json.hpp:676
@ PUNCTUATOR_OPEN_CURLY_BRACE
Open curly brace '{' symbol.
@ NUMBER_OCTAL
Octal number literal, e.g. 0777.
@ IDENTIFIER_FALSE
Keyword false.
@ PUNCTUATOR_CLOSE_CURLY_BRACE
Closing curly brace '}' symbol.
@ NUMBER_BINARY
Binary number literal, e.g. 0b0000000111111111.
@ PUNCTUATOR_COLON
Colon ':' symbol.
@ NUMBER_NEGATIVE_INFINITY
Keyword -Infinity.
@ END_OF_FILE
End-of-file marker.
@ PUNCTUATOR_CLOSE_SQUARE_BRACKET
Closing square bracket ']' symbol.
@ STRING
Quoted string literal, e.g. "abc".
@ NUMBER_POSITIVE_NAN
Keyword NaN.
@ IDENTIFIER_NAME
Unquoted identifier, e.g. abc.
@ NUMBER_DECIMAL
Decimal number literal, e.g. 511.
@ IDENTIFIER_NULL
Keyword null.
@ NUMBER_POSITIVE_INFINITY
Keyword Infinity.
@ IDENTIFIER_TRUE
Keyword true.
@ NUMBER_NEGATIVE_NAN
Keyword -NaN.
@ NUMBER_HEXADECIMAL
Hexadecimal number literal, e.g. 0x01FF.
@ PUNCTUATOR_OPEN_SQUARE_BRACKET
Open square bracket '[' symbol.
@ PUNCTUATOR_COMMA
Comma ',' symbol.
Monostate Null
JSON null type.
Definition: json.hpp:179
void serialize(std::ostream &stream, const T &value, const SerializationOptions &options={})
Serialize a value of any JSON-serializable type to an output stream.
Definition: json.hpp:3082
Object::size_type erase_if(Object &container, Predicate predicate)
Definition: json.hpp:4040
constexpr bool isPunctuationCharacter(char32_t codePoint) noexcept
Check if a Unicode code point is considered to be punctuation in JSON5.
Definition: json.hpp:656
void deserialize(std::istream &stream, T &value, const DeserializationOptions &options={})
Deserialize a value of any JSON-serializable type from an input stream.
Definition: json.hpp:3100
constexpr bool isWhitespaceCharacter(char32_t codePoint) noexcept
Check if a Unicode code point is considered to be whitespace in JSON5.
Definition: json.hpp:643
auto onArray(Callback callback)
Build a Parser::ValueVisitor that handles arrays with a given callback function.
Definition: json.hpp:3415
void swap(Object &a, Object &b) noexcept
Definition: json.hpp:3980
Array::size_type erase_if(Array &container, Predicate predicate)
Definition: json.hpp:4213
auto onString(Callback callback)
Build a Parser::ValueVisitor that handles String values with a given callback function.
Definition: json.hpp:3334
constexpr bool isLineTerminatorCharacter(char32_t codePoint) noexcept
Check if a Unicode code point marks the beginning of a line terminator sequence in JSON5.
Definition: json.hpp:669
double Number
JSON number type.
Definition: json.hpp:194
auto onProperty(Callback callback)
Build a Parser::PropertyVisitor that handles object properties with a given callback function.
Definition: json.hpp:3435
auto onObject(Callback callback)
Build a Parser::ValueVisitor that handles objects with a given callback function.
Definition: json.hpp:3388
auto onNumber(Callback callback)
Build a Parser::ValueVisitor that handles Number values with a given callback function.
Definition: json.hpp:3361
auto onBoolean(Callback callback)
Build a Parser::ValueVisitor that handles Boolean values with a given callback function.
Definition: json.hpp:3307
constexpr auto fields(auto &&aggregate) noexcept
Get a tuple of references to each of the fields of an aggregate.
Definition: reflection.hpp:86
constexpr void forEach(auto &&tuple, auto fn)
Execute a function once for each element in a given tuple, sequentially.
Definition: reflection.hpp:207
Definition: utilities.hpp:165
constexpr bool isValidCodePoint(char32_t codePoint) noexcept
Check if a 32-bit unsigned integer value falls within the valid ranges for a Unicode code point.
Definition: unicode.hpp:22
constexpr EncodeUTF8FromCodePointResult encodeUTF8FromCodePoint(char32_t codePoint) noexcept
Encode a Unicode code point into a sequence of UTF-8 code units.
Definition: unicode.hpp:141
constexpr detail::Matcher< V > match(V &&variant)
Choose a function overload to execute based on the active alternative of a variant.
Definition: Variant.hpp:1737
Unit type for representing an empty alternative in Variant.
Definition: Variant.hpp:236
Options for JSON deserialization.
Definition: json.hpp:171
Base template to specialize in order to implement JSON deserialization for a specific type.
Definition: json.hpp:3598
void deserialize(Reader &reader, T &value)
Definition: json.hpp:3599
Exception type for errors originating from the JSON API.
Definition: json.hpp:82
Error(const char *message, const SourceLocation &source)
Definition: json.hpp:93
SourceLocation source
Location in the JSON source string that the error originated from, or (0, 0) if the error did not ori...
Definition: json.hpp:87
Error(const std::string &message, const SourceLocation &source)
Definition: json.hpp:89
Implementation of PropertyVisitor for freestanding classes that implement all or parts of its interfa...
Definition: json.hpp:1334
ConcretePropertyVisitor(Visitor visitor)
Definition: json.hpp:1337
Visitor visitor
Definition: json.hpp:1335
void visitProperty(const SourceLocation &source, String &&key, Parser &parser) override
Callback for each object property.
Definition: json.hpp:1340
Implementation of ValueVisitor for freestanding classes that implement all or parts of its interface ...
Definition: json.hpp:1244
void visitNull(const SourceLocation &source, Null value) override
Callback for values of type Null.
Definition: json.hpp:1250
void visitBoolean(const SourceLocation &source, Boolean value) override
Callback for values of type Boolean.
Definition: json.hpp:1258
ConcreteValueVisitor(Visitor visitor)
Definition: json.hpp:1247
Visitor visitor
Definition: json.hpp:1245
void visitObject(const SourceLocation &source, Parser &parser) override
Callback for objects.
Definition: json.hpp:1282
void visitNumber(const SourceLocation &source, Number value) override
Callback for values of type Number.
Definition: json.hpp:1274
void visitString(const SourceLocation &source, String &&value) override
Callback for values of type String.
Definition: json.hpp:1266
void visitArray(const SourceLocation &source, Parser &parser) override
Callback for arrays.
Definition: json.hpp:1290
Implementation of PropertyVisitor that skips over the parsed property and discards the result.
Definition: json.hpp:1366
void visitProperty(const SourceLocation &source, String &&key, Parser &parser) override
Callback for each object property.
Definition: json.hpp:1368
Implementation of ValueVisitor that skips over the parsed value and discards the result.
Definition: json.hpp:1351
void visitArray(const SourceLocation &source, Parser &parser) override
Callback for arrays.
Definition: json.hpp:1358
void visitObject(const SourceLocation &source, Parser &parser) override
Callback for objects.
Definition: json.hpp:1357
void visitBoolean(const SourceLocation &source, Boolean value) override
Callback for values of type Boolean.
Definition: json.hpp:1354
void visitNull(const SourceLocation &source, Null value) override
Callback for values of type Null.
Definition: json.hpp:1353
void visitNumber(const SourceLocation &source, Number value) override
Callback for values of type Number.
Definition: json.hpp:1356
void visitString(const SourceLocation &source, String &&value) override
Callback for values of type String.
Definition: json.hpp:1355
Stateful wrapper object of an input stream for JSON deserialization.
Definition: json.hpp:2618
SourceLocation readBoolean(Boolean &value)
Read a single JSON value of type Boolean from the input.
Definition: json.hpp:2673
Reader(std::istream &stream, const DeserializationOptions &options={})
Construct a reader with an input stream as input.
Definition: json.hpp:2636
SourceLocation readNull()
Read a single JSON value of type Null from the input.
Definition: json.hpp:2652
SourceLocation readString(auto &value)
Read a single JSON value of type String from the input into any value that can be assigned from a sta...
Definition: json.hpp:2714
SourceLocation readString(String &value)
Read a single JSON value of type String from the input.
Definition: json.hpp:2694
SourceLocation readArray(Array &value)
Read a single JSON value of type Array from the input.
Definition: json.hpp:2888
SourceLocation readAggregate(T &value)
Read a single JSON value from the input into any value of aggregate type whose fields are deserializa...
Definition: json.hpp:3023
SourceLocation readOptional(T &value)
Read a single nullable JSON value from the input into any value that is default-constructible,...
Definition: json.hpp:2990
SourceLocation readObject(auto &value)
Read a single JSON object from the input into any container of key-value pairs where the key and valu...
Definition: json.hpp:2840
SourceLocation readArray(auto &value)
Read a single JSON array from the input into any container of elements that are default-constructible...
Definition: json.hpp:2917
SourceLocation readObject(Object &value)
Read a single JSON value of type Object from the input.
Definition: json.hpp:2809
DeserializationOptions options
The current options of the deserialization process.
Definition: json.hpp:2628
SourceLocation readNumber(T &value)
Read a single JSON value of type Number from the input into any value that Number can be explicitly c...
Definition: json.hpp:2787
void deserialize(T &value)
Read a JSON value from the input into any value that is deserializable from JSON using its correspond...
Definition: json.hpp:3063
SourceLocation readNumber(Number &value)
Read a single JSON value of type Number from the input.
Definition: json.hpp:2766
SourceLocation readValue(Value &value)
Read a single JSON value from the input.
Definition: json.hpp:2960
Options for JSON serialization.
Definition: json.hpp:101
bool prettyPrint
Format the output in a way that is nicely human-readable.
Definition: json.hpp:127
std::size_t indentation
The starting indentation level, expressed as the number of indentation characters.
Definition: json.hpp:106
std::size_t prettyPrintMaxSingleLineArrayItemCount
Maximum size of an array before it is split into multiple lines when pretty printing.
Definition: json.hpp:155
char indentationCharacter
The character to use when performing indentation.
Definition: json.hpp:117
const char * newlineString
Non-owning pointer to a null-terminated ASCII string representing the newline sequence to use when pe...
Definition: json.hpp:165
std::size_t prettyPrintMaxSingleLineObjectPropertyCount
Maximum size of an object before it is split into multiple lines when pretty printing.
Definition: json.hpp:141
std::size_t relativeIndentation
The number of indentation characters that each new level of indentation will add.
Definition: json.hpp:112
Base template to specialize in order to implement JSON serialization for a specific type.
Definition: json.hpp:3573
void serialize(Writer &writer, const T &value)
Definition: json.hpp:3574
Line and column numbers of a location in a JSON source string.
Definition: json.hpp:56
std::size_t lineNumber
Line number, starting at 1 for the first line.
Definition: json.hpp:61
std::size_t columnNumber
Column number, starting at 1 for the first column.
Definition: json.hpp:67
constexpr bool operator==(const SourceLocation &other) const =default
Compare this source location to another for equality.
Token data scanned from JSON.
Definition: json.hpp:702
SourceLocation source
Location of the scanned string in the JSON source string.
Definition: json.hpp:704
TokenType type
Scanned token type.
Definition: json.hpp:705
String string
Scanned string.
Definition: json.hpp:703
Stateful wrapper object of an output stream for JSON serialization.
Definition: json.hpp:2175
void writeString(const auto &value)
Write a single JSON value of type String to the output from any string-view-like or JSON-serializable...
Definition: json.hpp:2324
void write(std::string_view bytes)
Write a raw sequence of bytes to the output without any extra formatting.
Definition: json.hpp:2213
SerializationOptions options
The current options of the serialization process.
Definition: json.hpp:2183
void writeNewline()
Write a newline sequence to the output.
Definition: json.hpp:2239
void writeBoolean(Boolean value)
Write a single JSON value of type Boolean to the output.
Definition: json.hpp:2259
void writeIndentation()
Write a sequence of indentation characters to the output.
Definition: json.hpp:2228
void writeArray(const auto &value, ItemFilter itemFilter={}, GetValue getValue={})
Write a single JSON array to the output from any range of JSON-serializable values.
Definition: json.hpp:2465
void writeOptional(const auto &value)
Write a single JSON value to the output from any value that supports conversion to bool and the deref...
Definition: json.hpp:2531
void writeObject(const auto &value, PropertyFilter propertyFilter={}, GetKey getKey={}, GetValue getValue={})
Write a single JSON object to the output from any range of JSON-serializable key-value pairs.
Definition: json.hpp:2385
void write(char byte)
Write a single raw byte to the output without any extra formatting.
Definition: json.hpp:2202
void writeString(std::string_view bytes)
Write a single JSON value of type String to the output from a raw byte string.
Definition: json.hpp:2271
void serialize(const T &value)
Write any JSON-serializable value to the output using its corresponding implementation of Serializer.
Definition: json.hpp:2610
void writeAggregate(const T &value)
Write a single JSON value to the output from any value of aggregate type.
Definition: json.hpp:2549
void writeNull()
Write a single JSON value of type Null to the output.
Definition: json.hpp:2248
Writer(std::ostream &stream, const SerializationOptions &options={})
Construct a writer with an output stream as output.
Definition: json.hpp:2191
void writeString(std::basic_string_view< CharT, Traits > value) requires(!std
Write a single JSON value of type String to the output from a raw string, interpreted as raw bytes.
Definition: json.hpp:2309
void writeNumber(Number value)
Write a single JSON value of type Number to the output.
Definition: json.hpp:2349
Result of the encodeUTF8FromCodePoint() function.
Definition: unicode.hpp:123
std::size_t size
The length of the encoded code unit sequence stored in the codeUnits array.
Definition: unicode.hpp:125
std::array< char8_t, 4 > codeUnits
Array of UTF-8 code units that encode the given code point.
Definition: unicode.hpp:124
Sentinel type for UTF8Iterator.
Definition: unicode.hpp:183