11    using namespace Internal;
 
   16        void SkipSpaces(std::string_view::const_iterator& iter, 
size_t& length);
 
   17        Value 
NumberFromString(
const std::string& s, 
const bool is_scientific, 
const bool is_double);
 
   18        Value 
ParseNumber(std::string_view::const_iterator& iter, 
size_t& length);
 
   19        Value 
ParseString(std::string_view::const_iterator& iter, 
size_t& length);
 
   20        Value 
ParseObject(std::string_view::const_iterator& iter, 
size_t& length);
 
   21        Value 
ParseArray(std::string_view::const_iterator& iter, 
size_t& length);
 
   22        Value 
ParseValue(std::string_view::const_iterator& iter, 
size_t& length);
 
   76            if (init.size() == 2 && init.begin()->is_string())
 
   78                val = 
Object({ { init.begin()->get<std::string>(), *(init.begin() + 1) } });
 
   84            for (
const auto& j : init)
 
   96            for (
const auto& j : init)
 
   98                new_val.insert(*j.get_object().begin());
 
  101            val = std::move(new_val);
 
 
  111            return get<Object>();
 
 
  121            return get<std::string>();
 
 
  126            return get<Object>();
 
 
  136            return get<std::string>();
 
 
  141            return is<std::monostate>();
 
 
  146            return is<std::string>();
 
 
  151            return is<Json::Object>();
 
 
  156            return is<Json::Array>();
 
 
  166            return std::holds_alternative<long long int>(
val)
 
  167                || std::holds_alternative<unsigned long long int>(
val);
 
 
  172            return std::holds_alternative<long long int>(
val)
 
  173                || std::holds_alternative<unsigned long long int>(
val)
 
  174                || std::holds_alternative<double>(
val);
 
 
  179            if (std::holds_alternative<std::monostate>(
val))
 
  186                throw std::runtime_error(
"Json::Value is not an object");
 
  189            return get<Object>()[s];
 
 
  196                throw std::runtime_error(
"Json::Value is not an object");
 
  199            return get<Object>().at(s);
 
 
  206                throw std::runtime_error(
"Json::Value is not an array");
 
  209            return get<Array>()[i];
 
 
  216                throw std::runtime_error(
"Json::Value is not an array");
 
  219            return get<Array>().at(i);
 
 
  225                std::istreambuf_iterator<char>(is),
 
  226                std::istreambuf_iterator<char>()
 
 
  234            return is<Object>() && get<Object>().count(s);
 
 
  239            if (std::holds_alternative<std::monostate>(
val))
 
  246                return get<Object>().size();
 
  251                return get<Array>().size();
 
  254            throw std::runtime_error(
"Json::Value is neither an array nor an object");
 
 
  259            if (std::holds_alternative<std::monostate>(
val))
 
  266                throw std::runtime_error(
"Can't push_back in a non-array Json::Value");
 
  269            get<Array>().push_back(value);
 
 
  274            if (std::holds_alternative<std::monostate>(
val))
 
  281                throw std::runtime_error(
"Can't push_back in a non-array Json::Value");
 
  284            get<Array>().push_back(std::move(value));
 
 
  287        std::string 
Value::Dump(
const int indent, 
const char indent_char)
 const 
  289            return Dump(0, indent, indent_char);
 
 
  292        std::string 
Value::Dump(
const size_t depth_level, 
const int indent, 
const char indent_char)
 const 
  294            std::ostringstream oss;
 
  296            std::visit([&](
auto&& arg)
 
  298                    using T = std::decay_t<
decltype(arg)>;
 
  300                    if constexpr (std::is_same_v<T, std::monostate>)
 
  304                    else if constexpr (std::is_same_v<T, RecursiveWrapper<Object>>)
 
  306                        const Object& o = arg.get();
 
  313                        const std::string new_line = (indent == -1 ? 
"" : 
"\n");
 
  314                        const std::string line_indentation = indent > -1 ? std::string(depth_level * indent, indent_char) : 
"";
 
  315                        const std::string value_indentation = indent > -1 ? std::string(indent, indent_char) : 
"";
 
  317                        oss << 
"{" << new_line;
 
  319                        for (
const auto& [k, v] : o)
 
  323                                oss << 
"," << new_line;
 
  329                            oss << line_indentation << value_indentation << 
"\"" << k << 
"\"" << (indent == -1 ? 
":" : 
": ") << v.Dump(depth_level + 1, indent, indent_char);
 
  331                        oss << new_line << line_indentation << 
"}";
 
  333                    else if constexpr (std::is_same_v<T, RecursiveWrapper<Array>>)
 
  335                        const Array& a = arg.get();
 
  341                        const std::string new_line = (indent == -1 ? 
"" : 
"\n");
 
  342                        const std::string line_indentation = indent > -1 ? std::string(depth_level * indent, indent_char) : 
"";
 
  343                        const std::string value_indentation = indent > -1 ? std::string(indent, indent_char) : 
"";
 
  345                        oss << 
'[' << new_line;
 
  347                        for (
const auto& v : a)
 
  351                                oss << 
',' << new_line;
 
  357                            oss << line_indentation << value_indentation << v.Dump(depth_level + 1, indent, indent_char);
 
  359                        oss << new_line << line_indentation << 
']';
 
  361                    else if constexpr (std::is_same_v<T, std::string>)
 
  365                    else if constexpr (std::is_same_v<T, bool>)
 
  367                        oss << (arg ? 
"true" : 
"false");
 
  369                    else if constexpr (std::is_same_v<T, double>)
 
  371                        if (arg == std::floor(arg))
 
  373                            oss << std::setprecision(1) << std::fixed << arg;
 
 
  390        Value Parse(std::string_view::const_iterator iter, 
size_t length, 
bool no_except)
 
  392            const size_t init_length = length;
 
  398                    throw std::runtime_error(std::to_string(length) + 
" unread characters remaining after parsing");
 
  402            catch (
const std::runtime_error& e)
 
  408                throw std::runtime_error(e.what() + std::string(
" (at pos ") + std::to_string(init_length - length) + 
')');
 
 
  419            size_t length = s.size();
 
  420            std::string_view sview(s.begin().operator->(), s.end() - s.begin());
 
  423                return Parse(sview.begin(), length);
 
  425            catch (
const std::runtime_error& e)
 
  431                throw std::runtime_error(e.what() + std::string(
" (at pos ") + std::to_string(s.size() - length) + 
')');
 
 
  437            std::ostringstream out;
 
  439            while (it != s.end())
 
 
  478        void SkipSpaces(std::string_view::const_iterator& iter, 
size_t& length)
 
 
  500            const size_t s_size = s.size();
 
  502            for (
size_t i = 0; i < s_size; ++i)
 
  507                    if ((i == 0 && s_size > 1 && s[1] != 
'.' && s[1] != 
'e' && s[1] != 
'E') ||
 
  508                        (i == 1 && s_size > 2 && s[0] == 
'-' && s[2] != 
'.' && s[2] != 
'e' && s[2] != 
'E'))
 
  510                        throw std::runtime_error(
"Unexpected leading 0 when parsing number");
 
  514                    if (i == s_size - 1 ||
 
  515                        (i != 0 && (s[i - 1] == 
'.' || s[i - 1] == 
'+'))
 
  518                        throw std::runtime_error(
"Unexpected - character when parsing number");
 
  522                    if (i == 0 || i == s_size - 1 || (s[i - 1] != 
'e' && s[i - 1] != 
'E'))
 
  524                        throw std::runtime_error(
"Unexpected + character when parsing number");
 
  535                        throw std::runtime_error(
"Unexpected exponent sign found when parsing a number");
 
  546                        throw std::runtime_error(
"Unexpected . sign found when parsing a number");
 
 
  559                throw std::runtime_error(
"Trying to convert empty string to number");
 
  564            if (is_scientific || is_double)
 
  572                if (s.size() > 20 || (s.size() == 20 && s > 
"-9223372036854775808"))
 
  576                return std::stoll(s);
 
  580            if (s.size() > 20 || (s.size() == 20 && s > 
"18446744073709551615"))
 
  584            return std::stoull(s);
 
 
  589            std::string_view::const_iterator start = iter;
 
  591            bool is_scientific = 
false;
 
  592            bool is_double = 
false;
 
  602                        throw std::runtime_error(
"Multiple exponent char encountered while parsing number");
 
  604                    is_scientific = 
true;
 
  611                        throw std::runtime_error(
"Multiple decimal separator encountered while parsing number");
 
  633                    return NumberFromString(std::string(start, iter), is_scientific, is_double);
 
  638            return NumberFromString(std::string(start, iter), is_scientific, is_double);
 
 
  644            return cp <= 0x0010ffffu && !(cp >= 0xd800u && cp <= 0xdfffu);
 
 
  649            const unsigned long codepoint = std::stoul(hex_chars, 
nullptr, 16);
 
  653                throw std::runtime_error(
"Trying to parse an invalid codepoint to UTF8 while reading string");
 
  656            if (codepoint < 0x80)
 
  659                    + 
static_cast<char>(codepoint);
 
  661            else if (codepoint < 0x800)
 
  664                    + 
static_cast<char>((codepoint >> 6) | 0xc0)
 
  665                    + 
static_cast<char>((codepoint & 0x3f) | 0x80);
 
  667            else if (codepoint < 0x10000)
 
  670                    + 
static_cast<char>((codepoint >> 12) | 0xe0)
 
  671                    + 
static_cast<char>(((codepoint >> 6) & 0x3f) | 0x80)
 
  672                    + 
static_cast<char>((codepoint & 0x3f) | 0x80);
 
  677                    + 
static_cast<char>((codepoint >> 18) | 0xf0)
 
  678                    + 
static_cast<char>(((codepoint >> 12) & 0x3f) | 0x80)
 
  679                    + 
static_cast<char>(((codepoint >> 6) & 0x3f) | 0x80)
 
  680                    + 
static_cast<char>((codepoint & 0x3f) | 0x80);
 
 
  688                throw std::runtime_error(
"Not enough input when reading string");
 
  692                throw std::runtime_error(std::string(
"Unexpected char found at beginning of string \"") + *iter + 
"\"");
 
  697            std::ostringstream output;
 
  707                    throw std::runtime_error(
"Unexpected unescaped special character encountered when parsing string");
 
  715                        throw std::runtime_error(
"Missing data after escape character when parsing string");
 
  722                            output << *iter << *(iter + 1);
 
  764                                throw std::runtime_error(
"Missing data after \\u character when parsing string");
 
  771                            throw std::runtime_error(
"Unexpected escape character encountered when parsing string");
 
  777                    if (*iter > -1 && *iter < 32)
 
  780                        throw std::runtime_error(
"Unexpected control character encountered when parsing string");
 
  789            throw std::runtime_error(
"Not enough input when reading string");
 
 
  796                throw std::runtime_error(
"Not enough input when reading Json::Object");
 
  800                throw std::runtime_error(std::string(
"Unexpected char found at beginning of Json::Object \"") + *iter + 
"\"");
 
  809                throw std::runtime_error(
"Not enough input when reading Json::Object");
 
  830                    throw std::runtime_error(std::string(
"Unexpected char \"") + *iter + 
"\" when reading Json::Object while expecting :");
 
  848                else if (*iter != 
',')
 
  850                    throw std::runtime_error(std::string(
"Unexpected char \"") + *iter + 
"\" when reading Json::Object while expecting ,");
 
  857            throw std::runtime_error(
"Not enough input when reading Json::Object");
 
 
  864                throw std::runtime_error(
"Not enough input when reading Json::Array");
 
  868                throw std::runtime_error(std::string(
"Unexpected char found at beginning of Json::Array \"") + *iter + 
"\"");
 
  879                throw std::runtime_error(
"Not enough input when reading Json::Array");
 
  894                output.push_back(value);
 
  904                else if (*iter != 
',')
 
  906                    throw std::runtime_error(std::string(
"Unexpected char \"") + *iter + 
"\" when reading Json::Array while expecting ,");
 
  913            throw std::runtime_error(
"Not enough input when reading Json::Array");
 
 
  935                    || *(iter + 1) != 
'u' 
  936                    || *(iter + 2) != 
'l' 
  937                    || *(iter + 3) != 
'l')
 
  939                    throw std::runtime_error(
"Unexpected char \"n\"");
 
  949                    || *(iter + 1) != 
'r' 
  950                    || *(iter + 2) != 
'u' 
  951                    || *(iter + 3) != 
'e')
 
  953                    throw std::runtime_error(
"Unexpected char \"t\"");
 
  964                    || *(iter + 1) != 
'a' 
  965                    || *(iter + 2) != 
'l' 
  966                    || *(iter + 3) != 
's' 
  967                    || *(iter + 4) != 
'e')
 
  969                    throw std::runtime_error(
"Unexpected char \"f\"");
 
  992                throw std::runtime_error(std::string(
"Unexpected char \"") + *iter + 
"\"");
 
 
Template magic to have a full type instead of an incomplete one as required for example by std::varia...
Real class declaration, just a derived class of std::vector<Value>
Real class declaration, just a derived class of std::map<std::string, Value>
Main class, basically a JsonVariant with extra utility functions it doesn't inherit JsonVariant direc...
Internal::JsonVariant val
std::string Dump(const int indent=-1, const char indent_char=' ') const
public dump interface
void push_back(const Value &value)
Value & operator[](const std::string &s)
Value(std::nullptr_t=nullptr)
bool contains(const std::string &s) const
std::string & get_string()
Value ParseString(std::string_view::const_iterator &iter, size_t &length)
Value ParseObject(std::string_view::const_iterator &iter, size_t &length)
Value ParseNumber(std::string_view::const_iterator &iter, size_t &length)
bool IsValidCodepoint(const unsigned long cp)
Value ParseValue(std::string_view::const_iterator &iter, size_t &length)
std::string CodepointToUtf8(const std::string &hex_chars)
Value ParseArray(std::string_view::const_iterator &iter, size_t &length)
Value NumberFromString(const std::string &s, const bool is_scientific, const bool is_double)
Value Parse(std::string_view::const_iterator iter, size_t length, bool no_except=false)
Parse a string_view from iter for at most length characters.
void SkipSpaces(std::string_view::const_iterator &iter, size_t &length)
std::istream & operator>>(std::istream &is, Value &v)
void ValidateStringNumber(const std::string &s)
std::string EscapeChars(const std::string &s)