17 #include <fmt/format.h>
18 #include <initializer_list>
29 #include <string_view>
30 #include <system_error>
32 #include <type_traits>
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>;
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; } };
82 struct Error : std::runtime_error {
90 : std::runtime_error(message)
94 : std::runtime_error(message)
204 using size_type =
typename std::vector<value_type>::size_type;
206 using reference =
typename std::vector<value_type>::reference;
208 using pointer =
typename std::vector<value_type>::pointer;
210 using iterator =
typename std::vector<value_type>::iterator;
218 template <typename InputIt>
219 Object(InputIt first, InputIt last);
229 [[nodiscard]]
Value&
at(std::string_view name);
230 [[nodiscard]] const
Value&
at(std::string_view name) const;
247 [[nodiscard]]
bool empty() const noexcept;
251 void clear() noexcept;
253 template <typename P>
256 template <typename P>
259 template <typename InputIt>
260 void insert(InputIt first, InputIt last);
263 template <typename... Args>
266 template <typename... Args>
269 template <typename... Args>
272 template <typename... Args>
275 template <typename... Args>
278 template <typename... Args>
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;
298 [[nodiscard]]
bool operator==(const
Object& other) const noexcept;
299 [[nodiscard]] std::partial_ordering operator<=>(const
Object& other) const noexcept;
301 template <typename Predicate>
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;
312 std::vector<value_type> membersSortedByName;
321 using size_type =
typename std::vector<value_type>::size_type;
323 using reference =
typename std::vector<value_type>::reference;
325 using pointer =
typename std::vector<value_type>::pointer;
327 using iterator =
typename std::vector<value_type>::iterator;
335 template <typename InputIt>
336 Array(InputIt first, InputIt last);
355 [[nodiscard]]
bool empty() const noexcept;
379 [[nodiscard]]
bool operator==(const
Array& other) const;
380 [[nodiscard]] std::partial_ordering operator<=>(const
Array& other) const noexcept;
382 template <typename U>
385 template <typename Predicate>
388 void clear() noexcept;
396 template <typename InputIt>
400 template <typename... Args>
409 template <typename... Args>
448 [[nodiscard]]
static Value parse(std::u8string_view jsonString);
465 [[nodiscard]]
static Value parse(std::string_view jsonString);
539 static_assert(
sizeof(
char) ==
sizeof(char8_t));
540 static_assert(
alignof(
char) ==
alignof(char8_t));
560 Value(detail::number
auto value) noexcept
621 return static_cast<const Variant&
>(*this) ==
static_cast<const Variant&
>(other);
632 return std::compare_partial_order_fallback(
static_cast<const Variant&
>(*
this),
static_cast<const Variant&
>(other));
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;
657 return codePoint ==
',' || codePoint ==
':' || codePoint ==
'[' || codePoint ==
']' || codePoint ==
'{' || codePoint ==
'}';
670 return codePoint ==
'\n' || codePoint ==
'\r' || codePoint == 0x2028 || codePoint == 0x2029;
714 template <
typename It>
745 if (hasReachedEnd()) {
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();
775 void skipWhitespace() {
776 while (!hasReachedEnd()) {
779 skipLineTerminatorSequence();
783 }
else if (peek() ==
'/') {
785 if (hasReachedEnd()) {
786 throw Error{
"Invalid token.", source};
790 while (!hasReachedEnd()) {
792 skipLineTerminatorSequence();
797 }
else if (peek() ==
'*') {
799 while (!hasReachedEnd()) {
801 skipLineTerminatorSequence();
802 }
else if (peek() ==
'*') {
804 if (!hasReachedEnd() && peek() ==
'/') {
813 throw Error{
"Invalid token.", source};
821 void skipLineTerminatorSequence() {
822 if (peek() ==
'\r') {
824 if (!hasReachedEnd() && peek() ==
'\n') {
831 source.columnNumber = 1;
835 if (!currentCodePoint) {
838 currentCodePoint.reset();
839 ++source.columnNumber;
842 [[nodiscard]]
bool hasReachedEnd() const noexcept {
843 return it ==
end && !currentCodePoint;
846 [[nodiscard]] char32_t peek()
const {
847 if (!currentCodePoint) {
848 currentCodePoint = *it++;
850 return *currentCodePoint;
853 [[nodiscard]] std::optional<char32_t> lookahead()
const {
854 if (!currentCodePoint) {
855 currentCodePoint = *it++;
863 [[nodiscard]] Token scanPunctuator() {
864 String string{
static_cast<char>(peek())};
865 const SourceLocation punctuatorSource = source;
877 return {.string = std::move(
string), .source = punctuatorSource, .type = type};
880 [[nodiscard]] Token scanString() {
881 const char32_t quoteCharacter = peek();
883 const SourceLocation stringSource = source;
885 while (!hasReachedEnd()) {
887 throw Error{
"Invalid UTF-8.", source};
889 if (peek() == quoteCharacter) {
891 return {.string = std::move(
string), .source = stringSource, .type =
TokenType::STRING};
894 throw Error{
"Unexpected line terminator in string.", source};
896 if (peek() !=
'\\') {
898 string.append(std::string_view{
reinterpret_cast<const char*
>(codePointUTF8.
codeUnits.data()), codePointUTF8.
size});
903 if (hasReachedEnd()) {
904 throw Error{
"Empty escape sequence.", source};
907 skipLineTerminatorSequence();
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;
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');
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');
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');
947 string.append(std::string_view{
reinterpret_cast<const char*
>(codePointUTF8.
codeUnits.data()), codePointUTF8.
size});
953 throw Error{
"Missing end of string quote character.", source};
956 [[nodiscard]] Token scanNumber() {
958 const SourceLocation numberSource = source;
959 bool negative =
false;
962 }
else if (peek() ==
'-') {
963 string.push_back(
'-');
967 if (hasReachedEnd()) {
968 throw Error{
"Missing number.", source};
974 throw Error{
"Invalid number.", numberSource};
980 throw Error{
"Invalid number.", numberSource};
983 if (!hasReachedEnd() && peek() ==
'0') {
984 string.push_back(
'0');
986 if (!hasReachedEnd() && (peek() ==
'b' || peek() ==
'B')) {
987 string.push_back(
'b');
990 }
else if (!hasReachedEnd() && (peek() ==
'x' || peek() ==
'X')) {
991 string.push_back(
'x');
994 }
else if (hasReachedEnd() || peek() !=
'.') {
998 bool eNotation =
false;
999 bool fraction =
false;
1000 while (!hasReachedEnd()) {
1001 if (peek() ==
'.') {
1002 if (lookahead() ==
'.') {
1009 throw Error{
"Decimal point in E notation exponent.", source};
1012 throw Error{
"Multiple decimal points in number.", source};
1014 string.push_back(
'.');
1022 throw Error{
"Multiple exponent symbols in E notation.", source};
1024 string.push_back(
'e');
1028 if (hasReachedEnd()) {
1029 throw Error{
"Missing exponent in E notation.", source};
1031 if (peek() >=
'0' && peek() <=
'9') {
1032 string.push_back(
static_cast<char>(peek()));
1034 }
else if ((peek() ==
'+' || peek() ==
'-')) {
1035 string.push_back(
static_cast<char>(peek()));
1037 if (!hasReachedEnd() && peek() >=
'0' && peek() <=
'9') {
1038 string.push_back(
static_cast<char>(peek()));
1041 throw Error{
"Missing exponent in E notation.", source};
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()));
1051 }
else if (peek() ==
'_') {
1057 if (!hasReachedEnd()) {
1059 throw Error{
"Invalid character after number.", source};
1062 return {.string = std::move(
string), .source = numberSource, .type = type};
1065 [[nodiscard]] Token scanIdentifier() {
1067 const SourceLocation identifierSource = source;
1070 throw Error{
"Invalid UTF-8.", source};
1073 string.append(std::string_view{
reinterpret_cast<const char*
>(codePointUTF8.
codeUnits.data()), codePointUTF8.
size});
1077 if (
string ==
"null") {
1080 }
else if (
string ==
"false") {
1083 }
else if (
string ==
"true") {
1086 }
else if (
string ==
"Infinity") {
1089 }
else if (
string ==
"NaN") {
1093 return {.string = std::move(
string), .source = identifierSource, .type = type};
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()));
1104 if (digits.size() < minDigitCount) {
1105 throw Error{
"Invalid escape sequence length.", escapeSequenceSource};
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};
1115 output.append(std::string_view{
reinterpret_cast<const char*
>(codePointUTF8.
codeUnits.data()), codePointUTF8.
size});
1120 SourceLocation source;
1121 mutable std::optional<char32_t> currentCodePoint{};
1131 template <
typename It>
1150 throw Error{
"Unexpected null.", source};
1164 throw Error{
"Unexpected boolean.", source};
1177 (void)std::move(value);
1178 throw Error{
"Unexpected string.", source};
1192 throw Error{
"Unexpected number.", source};
1211 throw Error{
"Unexpected object.", source};
1230 throw Error{
"Unexpected array.", source};
1243 template <
typename Visitor>
1248 : visitor(std::move(visitor)) {}
1251 if constexpr (requires { visitor.visitNull(source, value); }) {
1252 visitor.visitNull(source, value);
1254 ValueVisitor::visitNull(source, value);
1259 if constexpr (requires { visitor.visitBoolean(source, value); }) {
1260 visitor.visitBoolean(source, value);
1262 ValueVisitor::visitBoolean(source, value);
1267 if constexpr (requires { visitor.visitString(source, std::move(value)); }) {
1268 visitor.visitString(source, std::move(value));
1270 ValueVisitor::visitString(source, std::move(value));
1275 if constexpr (requires { visitor.visitNumber(source, value); }) {
1276 visitor.visitNumber(source, value);
1278 ValueVisitor::visitNumber(source, value);
1283 if constexpr (requires { visitor.visitObject(source, parser); }) {
1284 visitor.visitObject(source, parser);
1286 ValueVisitor::visitObject(source, parser);
1291 if constexpr (requires { visitor.visitArray(source, parser); }) {
1292 visitor.visitArray(source, parser);
1294 ValueVisitor::visitArray(source, parser);
1333 template <
typename Visitor>
1338 : visitor(std::move(visitor)) {}
1341 if constexpr (requires { visitor.visitProperty(source, std::move(key), parser); }) {
1342 visitor.visitProperty(source, std::move(key), parser);
1378 : lexer(std::move(lexer)) {}
1395 explicit Parser(std::u8string_view jsonString) requires(std::is_same_v<It, const char8_t*>)
1405 explicit Parser(std::string_view jsonString) requires(std::is_same_v<It, const char8_t*>)
1413 explicit Parser(std::istream& stream) requires(std::is_same_v<It, std::istreambuf_iterator<char>>)
1421 explicit Parser(std::streambuf* streambuf) requires(std::is_same_v<It, std::istreambuf_iterator<char>>)
1445 parseValue(visitor);
1447 throw Error{
"Multiple top-level values.", token.
source};
1471 switch (
const Token& token = peek(); token.
type) {
1507 visitor.
visitNumber(token.source,
Number{std::numeric_limits<Number>::infinity()});
1511 visitor.
visitNumber(token.source,
Number{-std::numeric_limits<Number>::infinity()});
1515 visitor.
visitNumber(token.source,
Number{std::numeric_limits<Number>::quiet_NaN()});
1519 visitor.
visitNumber(token.source,
Number{-std::numeric_limits<Number>::quiet_NaN()});
1545 switch (
const Token& token = peek(); token.
type) {
1572 if (peek().source == source) {
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; }
1583 parseValue(SkipValue{});
1591 throw Error{
"Expected a comma or closing brace.", token.
source};
1624 parseValue(visitor);
1631 throw Error{
"Expected a comma or closing bracket.", token.
source};
1647 parseValue(visitor);
1654 parseObject(visitor);
1661 parseArray(visitor);
1667 template <
typename Visitor>
1675 template <
typename Visitor>
1683 template <
typename Visitor>
1691 template <
typename Visitor>
1740 Value result = parseValue();
1742 throw Error{
"Multiple top-level values.", token.
source};
1770 explicit Visitor(
Value& result) noexcept
1776 void visitString(
const SourceLocation&,
String&& value)
override { result = std::move(value); }
1783 parseValue(Visitor{result});
1799 const Token token = eat();
1800 switch (token.
type) {
1819 const Token token = eat();
1820 switch (token.
type) {
1840 Token token = eat();
1841 switch (token.
type) {
1860 Token token = eat();
1861 switch (token.
type) {
1888 const Token& token = peek();
1889 switch (token.
type) {
1894 explicit Visitor(
Object& result) noexcept
1902 parseObject(Visitor{result});
1923 const Token& token = peek();
1924 switch (token.
type) {
1930 explicit Visitor(
Array& result) noexcept
1936 void visitString(
const SourceLocation&,
String&& value)
override { result.emplace_back(std::move(value)); }
1942 parseArray(Visitor{result});
1958 if (!currentToken) {
1961 currentToken.reset();
1981 if (!currentToken) {
1982 currentToken = lexer.scan();
1984 return *currentToken;
1999 if (!currentToken) {
2000 currentToken = lexer.scan();
2002 Token result = std::move(*currentToken);
2003 currentToken.reset();
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;
2013 const double number_value = std::strtod(numberStringBegin, &endPointer);
2014 if (endPointer != numberStringEnd) {
2017 return Number{number_value};
2019 bool negative =
false;
2020 if (!token.
string.empty() && token.
string.front() ==
'-') {
2022 ++numberStringBegin;
2024 const unsigned long long integerNumberValue = std::strtoull(numberStringBegin, &endPointer, radix);
2025 if (endPointer != numberStringEnd) {
2026 throw Error{
"Invalid number.", token.
source};
2028 const double numberValue =
static_cast<double>(integerNumberValue);
2029 return Number{(negative) ? -numberValue : numberValue};
2032 mutable Lexer<It> lexer;
2033 mutable std::optional<Token> currentToken{};
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);
2069 template <
typename T>
2087 template <
typename T>
2088 struct Deserializer;
2106 template <
typename T>
2107 void serialize(std::ostream& stream,
const T& value,
const SerializationOptions& options = {});
2126 template <
typename T>
2127 void deserialize(std::istream& stream, T& value,
const DeserializationOptions& options = {});
2166 }
catch (
const Error&) {
2167 stream.setstate(std::istream::failbit);
2177 std::ostream& stream;
2193 , options(options) {}
2229 for (std::size_t i = 0; i < options.
indentation; ++i) {
2260 write((value) ?
"true" :
"false");
2272 constexpr std::array<char, 16> HEXADECIMAL_DIGITS{
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F'};
2274 for (
const char byte : bytes) {
2275 if (
byte >=
' ' &&
byte <=
'~' &&
byte !=
'\"' &&
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;
2291 write(HEXADECIMAL_DIGITS[(
byte >> 4) & 0x0F]);
2292 write(HEXADECIMAL_DIGITS[(
byte & 0x0F)]);
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()});
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});
2336 std::ostringstream stringStream{};
2338 writeString(std::move(stringStream).str());
2350 if (std::isnan(value)) {
2351 if (std::signbit(value)) {
2356 }
else if (std::isinf(value)) {
2357 if (std::signbit(value)) {
2358 stream <<
"-Infinity";
2360 stream <<
"Infinity";
2363 [[likely]] fmt::format_to(std::ostreambuf_iterator{stream},
"{}", value);
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)) {
2396 writeString(getKey(*it));
2399 for (++it; it !=
end; ++it) {
2400 if (propertyFilter(*it)) {
2402 writeString(getKey(*it));
2413 writeString(getKey(*it));
2416 for (++it; it !=
end; ++it) {
2417 if (propertyFilter(*it)) {
2421 writeString(getKey(*it));
2434 writeString(getKey(*it));
2437 for (++it; it !=
end; ++it) {
2438 if (propertyFilter(*it)) {
2440 writeString(getKey(*it));
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)) {
2477 for (++it; it !=
end; ++it) {
2478 if (itemFilter(*it)) {
2490 for (++it; it !=
end; ++it) {
2491 if (itemFilter(*it)) {
2507 for (++it; it !=
end; ++it) {
2508 if (itemFilter(*it)) {
2548 template <
typename T>
2550 if constexpr (reflection::aggregate_size_v<T> == 0) {
2552 }
else if constexpr (reflection::aggregate_size_v<T> == 1) {
2553 const auto& [v] = value;
2558 bool successor =
false;
2571 bool successor =
false;
2588 bool successor =
false;
2609 template <
typename T>
2620 using It = std::istreambuf_iterator<char>;
2638 , options(options) {}
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};
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};
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};
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);
2745 std::istringstream stringStream{std::move(
string)};
2786 template <
typename T>
2790 value =
static_cast<T
>(number);
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);
2855 value.emplace(std::move(propertyKey), std::move(propertyValue));
2866 throw Error{
"Expected a comma or closing brace.", token.
source};
2925 std::remove_cvref_t<decltype(*std::begin(value))> item{};
2927 value.push_back(std::move(item));
2938 throw Error{
"Expected a comma or closing bracket.", token.
source};
2989 template <
typename T>
2996 std::remove_cvref_t<decltype(*value)> result{};
2998 value = std::move(result);
3022 template <
typename T>
3025 if constexpr (reflection::aggregate_size_v<T> == 1) {
3032 bool successor =
false;
3036 throw Error{
"Expected a comma.", token.source};
3044 token = parser.
eat();
3047 throw Error{
"Missing end of array.", token.
source};
3062 template <
typename T>
3081 template <
typename T>
3083 Writer{stream, options}.serialize(value);
3099 template <
typename T>
3101 Reader{stream, options}.deserialize(value);
3106 struct NoVisitor {};
3108 template <
typename Base,
typename Callback>
3109 struct VisitNull : Base {
3110 [[no_unique_address]] Callback callback;
3112 VisitNull(Callback callback)
3113 : callback(std::move(callback)) {}
3115 VisitNull(Base base, Callback callback)
3116 : Base(std::move(base))
3117 , callback(std::move(callback)) {}
3119 void visitNull(
const SourceLocation& source,
Null value) {
3120 callback(source, value);
3123 template <
typename NewBase>
3124 [[nodiscard]]
auto operator|(NewBase other) && {
3125 return VisitNull<NewBase, Callback>{std::move(other), std::move(callback)};
3129 template <
typename Base,
typename Callback>
3130 struct VisitBoolean : Base {
3131 [[no_unique_address]] Callback callback;
3133 VisitBoolean(Callback callback)
3134 : callback(std::move(callback)) {}
3136 VisitBoolean(Base base, Callback callback)
3137 : Base(std::move(base))
3138 , callback(std::move(callback)) {}
3140 void visitBoolean(
const SourceLocation& source,
Boolean value) {
3141 callback(source, value);
3144 template <
typename NewBase>
3145 [[nodiscard]]
auto operator|(NewBase other) && {
3146 return VisitBoolean<NewBase, Callback>{std::move(other), std::move(callback)};
3150 template <
typename Base,
typename Callback>
3151 struct VisitString : Base {
3152 [[no_unique_address]] Callback callback;
3154 VisitString(Callback callback)
3155 : callback(std::move(callback)) {}
3157 VisitString(Base base, Callback callback)
3158 : Base(std::move(base))
3159 , callback(std::move(callback)) {}
3161 void visitString(
const SourceLocation& source,
String&& value) {
3162 callback(source, std::move(value));
3165 template <
typename NewBase>
3166 [[nodiscard]]
auto operator|(NewBase other) && {
3167 return VisitString<NewBase, Callback>{std::move(other), std::move(callback)};
3171 template <
typename Base,
typename Callback>
3172 struct VisitNumber : Base {
3173 [[no_unique_address]] Callback callback;
3175 VisitNumber(Callback callback)
3176 : callback(std::move(callback)) {}
3178 VisitNumber(Base base, Callback callback)
3179 : Base(std::move(base))
3180 , callback(std::move(callback)) {}
3182 void visitNumber(
const SourceLocation& source,
Number value) {
3183 callback(source, value);
3186 template <
typename NewBase>
3187 [[nodiscard]]
auto operator|(NewBase other) && {
3188 return VisitNumber<NewBase, Callback>{std::move(other), std::move(callback)};
3192 template <
typename Base,
typename Callback>
3193 struct VisitObject : Base {
3194 [[no_unique_address]] Callback callback;
3196 VisitObject(Callback callback)
3197 : callback(std::move(callback)) {}
3199 VisitObject(Base base, Callback callback)
3200 : Base(std::move(base))
3201 , callback(std::move(callback)) {}
3203 void visitObject(
const SourceLocation& source,
auto& parser) {
3204 callback(source, parser);
3207 template <
typename NewBase>
3208 [[nodiscard]]
auto operator|(NewBase other) && {
3209 return VisitObject<NewBase, Callback>{std::move(other), std::move(callback)};
3213 template <
typename Base,
typename Callback>
3214 struct VisitArray : Base {
3215 [[no_unique_address]] Callback callback;
3217 VisitArray(Callback callback)
3218 : callback(std::move(callback)) {}
3220 VisitArray(Base base, Callback callback)
3221 : Base(std::move(base))
3222 , callback(std::move(callback)) {}
3224 void visitArray(
const SourceLocation& source,
auto& parser) {
3225 callback(source, parser);
3228 template <
typename NewBase>
3229 [[nodiscard]]
auto operator|(NewBase other) && {
3230 return VisitArray<NewBase, Callback>{std::move(other), std::move(callback)};
3234 template <
typename Base,
typename Callback>
3235 struct VisitProperty : Base {
3236 [[no_unique_address]] Callback callback;
3238 VisitProperty(Callback callback)
3239 : callback(std::move(callback)) {}
3241 VisitProperty(Base base, Callback callback)
3242 : Base(std::move(base))
3243 , callback(std::move(callback)) {}
3245 void visitProperty(
const SourceLocation& source,
String&& key,
auto& parser) {
3246 callback(source, std::move(key), parser);
3249 template <
typename NewBase>
3250 [[nodiscard]]
auto operator|(NewBase other) && {
3251 return VisitProperty<NewBase, Callback>{std::move(other), std::move(callback)};
3279 template <
typename Callback>
3280 [[nodiscard]]
inline auto onNull(Callback callback) {
3281 return detail::VisitNull<detail::NoVisitor, Callback>{std::move(callback)};
3306 template <
typename Callback>
3308 return detail::VisitBoolean<detail::NoVisitor, Callback>{std::move(callback)};
3333 template <
typename Callback>
3334 [[nodiscard]]
inline auto onString(Callback callback) {
3335 return detail::VisitString<detail::NoVisitor, Callback>{std::move(callback)};
3360 template <
typename Callback>
3361 [[nodiscard]]
inline auto onNumber(Callback callback) {
3362 return detail::VisitNumber<detail::NoVisitor, Callback>{std::move(callback)};
3387 template <
typename Callback>
3388 [[nodiscard]]
inline auto onObject(Callback callback) {
3389 return detail::VisitObject<detail::NoVisitor, Callback>{std::move(callback)};
3414 template <
typename Callback>
3415 [[nodiscard]]
inline auto onArray(Callback callback) {
3416 return detail::VisitArray<detail::NoVisitor, Callback>{std::move(callback)};
3434 template <
typename Callback>
3436 return detail::VisitProperty<detail::NoVisitor, Callback>{std::move(callback)};
3441 template <
typename T>
3443 !std::is_arithmetic_v<T> &&
3444 requires(
const T& value) {
3445 static_cast<bool>(value);
3446 static_cast<bool>(!value);
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}; };
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{}; };
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);
3476 template <
typename T>
3477 concept deserializable_as_object =
3478 std::is_same_v<T, Object> ||
3479 requires(Reader& reader, T& value) {
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)>{});
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)); };
3493 template <
typename T>
3494 concept deserializable_as_array =
3495 std::is_same_v<T, Array> ||
3496 requires(Reader& reader, T& value) {
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))>{});
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);
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) {
3516 std::remove_cvref_t<decltype(*value)>{};
3517 reader.deserialize(result);
3518 value = std::move(result);
3521 template <
typename T>
3522 inline constexpr
bool always_false_v =
false;
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>) {
3530 }
else if constexpr (serializable_as_object<T>) {
3531 if constexpr (nullable<T>) {
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, {}, {});
3542 }
else if constexpr (serializable_as_array<T>) {
3543 if constexpr (nullable<T>) {
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, {}, {});
3554 }
else if constexpr (serializable_as_optional<T>) {
3556 }
else if constexpr (std::is_aggregate_v<T>) {
3557 if constexpr (nullable<T>) {
3562 std::size_t result = 1;
3572 template <
typename T>
3575 if constexpr (detail::nullable<T>) {
3581 if constexpr (detail::serializable_as_string<T>) {
3583 }
else if constexpr (detail::serializable_as_object<T>) {
3585 }
else if constexpr (detail::serializable_as_array<T>) {
3587 }
else if constexpr (detail::serializable_as_optional<T>) {
3589 }
else if constexpr (std::is_aggregate_v<T>) {
3592 static_assert(detail::always_false_v<T>,
"JSON serialization is not implemented for the given type.");
3597 template <
typename T>
3600 if constexpr (detail::serializable_as_string<T>) {
3602 }
else if constexpr (detail::serializable_as_object<T>) {
3604 }
else if constexpr (detail::serializable_as_array<T>) {
3606 }
else if constexpr (detail::serializable_as_optional<T>) {
3608 }
else if constexpr (std::is_aggregate_v<T>) {
3611 static_assert(detail::always_false_v<T>,
"JSON deserialization is not implemented for the given type.");
3618 struct Serializer<
Null> {
3625 struct Serializer<std::nullptr_t> {
3626 void serialize(Writer& writer, std::nullptr_t) {
3634 writer.writeBoolean(value);
3638 template <detail::number Num>
3639 struct Serializer<Num> {
3640 void serialize(Writer& writer, Num value) {
3641 writer.writeNumber(
static_cast<Number>(value));
3646 struct Serializer<char> {
3647 void serialize(Writer& writer,
char value) {
3648 writer.writeString(std::string_view{&value, 1});
3653 struct Serializer<char8_t> {
3654 void serialize(Writer& writer, char8_t value) {
3655 writer.writeString(std::u8string_view{&value, 1});
3660 struct Serializer<char16_t> {
3661 void serialize(Writer& writer, char16_t value) {
3662 writer.writeString(std::u16string_view{&value, 1});
3667 struct Serializer<char32_t> {
3668 void serialize(Writer& writer, char32_t value) {
3669 writer.writeString(std::u32string_view{&value, 1});
3674 struct Serializer<wchar_t> {
3675 void serialize(Writer& writer,
wchar_t value) {
3676 writer.writeString(std::wstring_view{&value, 1});
3681 struct Serializer<Value> {
3682 void serialize(Writer& writer,
const Value& value) {
3683 match(value)([&](
const auto& v) ->
void { writer.serialize(v); });
3690 struct Deserializer<
Null> {
3697 struct Deserializer<std::nullptr_t> {
3698 void deserialize(Reader& reader, std::nullptr_t&) {
3704 struct Deserializer<
Boolean> {
3706 reader.readBoolean(value);
3710 template <detail::number Num>
3711 struct Deserializer<Num> {
3713 reader.readNumber(value);
3718 struct Deserializer<char> {
3721 const SourceLocation source = reader.readString(
string);
3722 if (
string.size() != 1) {
3723 throw Error{
"Expected only a single character.", source};
3725 value =
string.front();
3730 struct Deserializer<char8_t> {
3731 void deserialize(Reader& reader, char8_t& value) {
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};
3737 std::memcpy(&value,
string.data(),
sizeof(char8_t));
3742 struct Deserializer<char16_t> {
3743 void deserialize(Reader& reader, char16_t& value) {
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};
3749 std::memcpy(&value,
string.data(),
sizeof(char16_t));
3754 struct Deserializer<char32_t> {
3755 void deserialize(Reader& reader, char32_t& value) {
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};
3761 std::memcpy(&value,
string.data(),
sizeof(char32_t));
3766 struct Deserializer<wchar_t> {
3767 void deserialize(Reader& reader,
wchar_t& value) {
3769 const SourceLocation source = reader.readString(
string);
3770 if (
string.size() !=
sizeof(
wchar_t)) {
3771 throw Error{
"Expected only a single wide character.", source};
3773 std::memcpy(&value,
string.data(),
sizeof(
wchar_t));
3778 struct Deserializer<Value> {
3780 reader.readValue(value);
3787 inline Object::~Object() = default;
3789 inline Object::Object(const Object& other) = default;
3791 inline Object::Object(Object&& other) noexcept = default;
3793 inline Object& Object::operator=(const Object& other) = default;
3795 inline Object& Object::operator=(Object&& other) noexcept = default;
3797 template <typename InputIt>
3799 : membersSortedByName(first, last) {
3800 std::sort(membersSortedByName.begin(), membersSortedByName.end(), Compare{});
3804 :
Object(ilist.begin(), ilist.end()) {}
3807 membersSortedByName = ilist;
3808 std::sort(membersSortedByName.begin(), membersSortedByName.end(), Compare{});
3813 if (
const auto it =
find(name); it !=
end()) {
3816 throw std::out_of_range{
"JSON object does not contain a member with the given name."};
3820 if (
const auto it =
find(name); it !=
end()) {
3823 throw std::out_of_range{
"JSON object does not contain a member with the given name."};
3835 return membersSortedByName.begin();
3839 return membersSortedByName.begin();
3843 return membersSortedByName.cbegin();
3847 return membersSortedByName.end();
3851 return membersSortedByName.end();
3855 return membersSortedByName.cend();
3859 return membersSortedByName.rbegin();
3863 return membersSortedByName.rbegin();
3867 return membersSortedByName.crbegin();
3871 return membersSortedByName.rend();
3875 return membersSortedByName.rend();
3879 return membersSortedByName.crend();
3883 return membersSortedByName.empty();
3887 return membersSortedByName.size();
3891 return membersSortedByName.max_size();
3895 membersSortedByName.clear();
3898 template <
typename P>
3900 return emplace(std::forward<P>(value));
3903 template <
typename P>
3908 template <
typename InputIt>
3910 while (first != last) {
3915 inline void Object::insert(std::initializer_list<Object::value_type> ilist) {
3916 insert(ilist.begin(), ilist.end());
3919 template <
typename... 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};
3926 const auto it = membersSortedByName.insert(last, std::move(value));
3930 template <
typename... Args>
3932 return emplace(std::forward<Args>(args)...);
3935 template <
typename... Args>
3938 if (first != last) {
3939 return {first,
false};
3941 const auto it = membersSortedByName.emplace(last, std::piecewise_construct, std::forward_as_tuple(k), std::forward_as_tuple(std::forward<Args>(args)...));
3945 template <
typename... Args>
3948 if (first != last) {
3949 return {first,
false};
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)...));
3955 template <
typename... Args>
3957 return try_emplace(k, std::forward<Args>(args)...);
3960 template <
typename... Args>
3962 return try_emplace(std::move(k), std::forward<Args>(args)...);
3966 return membersSortedByName.erase(pos);
3972 membersSortedByName.erase(first, last);
3977 membersSortedByName.swap(other.membersSortedByName);
3985 const auto [first, last] = equal_range(name);
3986 return static_cast<size_type>(last - first);
3990 return count(name) > 0;
3994 if (
const auto [first, last] = equal_range(name); first != last) {
4001 if (
const auto [first, last] = equal_range(name); first != last) {
4008 return std::equal_range(membersSortedByName.begin(), membersSortedByName.end(), name, Compare{});
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{});
4016 return std::lower_bound(membersSortedByName.begin(), membersSortedByName.end(), name, Compare{});
4020 return std::lower_bound(membersSortedByName.begin(), membersSortedByName.end(), name, Compare{});
4024 return std::upper_bound(membersSortedByName.begin(), membersSortedByName.end(), name, Compare{});
4028 return std::upper_bound(membersSortedByName.begin(), membersSortedByName.end(), name, Compare{});
4032 return membersSortedByName == other.membersSortedByName;
4036 return std::compare_partial_order_fallback(membersSortedByName, other.membersSortedByName);
4039 template <
typename Predicate>
4041 return std::erase_if(container.membersSortedByName, predicate);
4044 inline bool Object::Compare::operator()(
const value_type& a,
const value_type& b)
const noexcept {
4045 return a.first < b.first;
4048 inline bool Object::Compare::operator()(
const value_type& a, std::string_view b)
const noexcept {
4052 inline bool Object::Compare::operator()(std::string_view a,
const value_type& b)
const noexcept {
4056 inline bool Object::Compare::operator()(std::string_view a, std::string_view b)
const noexcept {
4062 inline Array::~Array() = default;
4064 inline Array::Array(const Array& other) = default;
4066 inline Array::Array(Array&& other) noexcept = default;
4068 inline Array& Array::operator=(const Array& other) = default;
4070 inline Array& Array::operator=(Array&& other) noexcept = default;
4072 template <typename InputIt>
4074 : values(first, last) {}
4077 : values(count, value) {}
4088 values.swap(other.values);
4096 return values.data();
4100 return values.data();
4104 return values.size();
4108 return values.max_size();
4112 return values.capacity();
4116 return values.empty();
4120 return values.begin();
4124 return values.begin();
4128 return values.cbegin();
4132 return values.end();
4136 return values.end();
4140 return values.cend();
4144 return values.rbegin();
4148 return values.rbegin();
4152 return values.crbegin();
4156 return values.rend();
4160 return values.rend();
4164 return values.crend();
4168 return values.front();
4172 return values.front();
4176 return values.back();
4180 return values.back();
4184 return values.at(pos);
4188 return values.at(pos);
4200 return values == other.values;
4204 return std::compare_partial_order_fallback(values, other.values);
4207 template <
typename U>
4212 template <
typename Predicate>
4222 values.reserve(newCap);
4226 values.shrink_to_fit();
4230 return values.insert(pos, value);
4234 return values.insert(pos, std::move(value));
4238 return values.insert(pos, count, value);
4241 template <
typename InputIt>
4243 return values.insert(pos, first, last);
4247 return values.insert(pos, ilist);
4250 template <
typename... Args>
4252 return values.emplace(pos, std::forward<Args>(args)...);
4256 return values.erase(pos);
4260 return values.erase(first, last);
4264 values.push_back(value);
4268 values.push_back(std::move(value));
4271 template <
typename... Args>
4273 return values.emplace_back(std::forward<Args>(args)...);
4281 values.resize(count);
4285 values.resize(count, value);
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()});
4300 std::ostringstream stream{};
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
~PropertyVisitor()=default
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
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