#include #include // numeric_limits #include // move() #include #include // strto*() #include // enable_if, is_* #include // strlen() namespace butl { namespace json { inline invalid_json_input:: invalid_json_input (std::string n, std::uint64_t l, std::uint64_t c, std::uint64_t p, const std::string& d) : invalid_json_input (move (n), l, c, p, d.c_str ()) { } inline invalid_json_input:: invalid_json_input (std::string n, std::uint64_t l, std::uint64_t c, std::uint64_t p, const char* d) : invalid_argument (d), name (std::move (n)), line (l), column (c), position (p) { } inline parser:: parser (std::istream& is, const std::string& n, bool mv, const char* sep) noexcept : parser (is, n.c_str (), mv, sep) { } inline parser:: parser (const void* t, std::size_t s, const std::string& n, bool mv, const char* sep) noexcept : parser (t, s, n.c_str (), mv, sep) { } inline parser:: parser (const std::string& t, const std::string& n, bool mv, const char* sep) noexcept : parser (t.data (), t.size (), n.c_str (), mv, sep) { } inline parser:: parser (const std::string& t, const char* n, bool mv, const char* sep) noexcept : parser (t.data (), t.size (), n, mv, sep) { } inline parser:: parser (const char* t, const std::string& n, bool mv, const char* sep) noexcept : parser (t, std::strlen (t), n.c_str (), mv, sep) { } inline parser:: parser (const char* t, const char* n, bool mv, const char* sep) noexcept : parser (t, std::strlen (t), n, mv, sep) { } inline const std::string& parser:: name () { if (!name_p_) { assert (parsed_ && !peeked_ && !value_p_); cache_parsed_data (); assert (name_p_); } return name_; } inline std::string& parser:: value () { if (!value_p_) { assert (parsed_ && !peeked_ && !name_p_); cache_parsed_data (); assert (value_p_); } return value_; } // Note: one day we will be able to use C++17 from_chars() which was made // exactly for this. // template inline typename std::enable_if::value, T>::type parse_value (const char* b, size_t, const parser&) { return *b == 't'; } template inline typename std::enable_if< std::is_integral::value && std::is_signed::value && !std::is_same::value, T>::type parse_value (const char* b, size_t n, const parser& p) { char* e (nullptr); errno = 0; // We must clear it according to POSIX. std::int64_t v (strtoll (b, &e, 10)); // Can't throw. if (e == b || e != b + n || errno == ERANGE || v < std::numeric_limits::min () || v > std::numeric_limits::max ()) p.throw_invalid_value ("signed integer", b, n); return static_cast (v); } template inline typename std::enable_if< std::is_integral::value && std::is_unsigned::value && !std::is_same::value, T>::type parse_value (const char* b, size_t n, const parser& p) { char* e (nullptr); errno = 0; // We must clear it according to POSIX. std::uint64_t v (strtoull (b, &e, 10)); // Can't throw. if (e == b || e != b + n || errno == ERANGE || v > std::numeric_limits::max ()) p.throw_invalid_value ("unsigned integer", b, n); return static_cast (v); } template inline typename std::enable_if::value, T>::type parse_value (const char* b, size_t n, const parser& p) { char* e (nullptr); errno = 0; // We must clear it according to POSIX. T r (std::strtof (b, &e)); if (e == b || e != b + n || errno == ERANGE) p.throw_invalid_value ("float", b, n); return r; } template inline typename std::enable_if::value, T>::type parse_value (const char* b, size_t n, const parser& p) { char* e (nullptr); errno = 0; // We must clear it according to POSIX. T r (std::strtod (b, &e)); if (e == b || e != b + n || errno == ERANGE) p.throw_invalid_value ("double", b, n); return r; } template inline typename std::enable_if::value, T>::type parse_value (const char* b, size_t n, const parser& p) { char* e (nullptr); errno = 0; // We must clear it according to POSIX. T r (std::strtold (b, &e)); if (e == b || e != b + n || errno == ERANGE) p.throw_invalid_value ("long double", b, n); return r; } template inline T parser:: value () const { if (!value_p_) { assert (parsed_ && !peeked_ && value_event (translate (*parsed_))); return parse_value (raw_s_, raw_n_, *this); } return parse_value (value_.data (), value_.size (), *this); } inline void parser:: next_expect_name (const std::string& n, bool su) { next_expect_name (n.c_str (), su); } // next_expect_() // inline std::string& parser:: next_expect_string () { next_expect (event::string); return value (); } template inline T parser:: next_expect_string () { next_expect (event::string); return value (); } inline std::string& parser:: next_expect_number () { next_expect (event::number); return value (); } template inline T parser:: next_expect_number () { next_expect (event::number); return value (); } inline std::string& parser:: next_expect_boolean () { next_expect (event::boolean); return value (); } template inline T parser:: next_expect_boolean () { next_expect (event::boolean); return value (); } // next_expect__null() // inline std::string* parser:: next_expect_string_null () { return next_expect (event::string, event::null) ? &value () : nullptr; } template inline optional parser:: next_expect_string_null () { return next_expect (event::string, event::null) ? optional (value ()) : nullopt; } inline std::string* parser:: next_expect_number_null () { return next_expect (event::number, event::null) ? &value () : nullptr; } template inline optional parser:: next_expect_number_null () { return next_expect (event::number, event::null) ? optional (value ()) : nullopt; } inline std::string* parser:: next_expect_boolean_null () { return next_expect (event::boolean, event::null) ? &value () : nullptr; } template inline optional parser:: next_expect_boolean_null () { return next_expect (event::boolean, event::null) ? optional (value ()) : nullopt; } // next_expect_member_string() // inline std::string& parser:: next_expect_member_string (const char* n, bool su) { next_expect_name (n, su); return next_expect_string (); } inline std::string& parser:: next_expect_member_string (const std::string& n, bool su) { return next_expect_member_string (n.c_str (), su); } template inline T parser:: next_expect_member_string (const char* n, bool su) { next_expect_name (n, su); return next_expect_string (); } template inline T parser:: next_expect_member_string (const std::string& n, bool su) { return next_expect_member_string (n.c_str (), su); } // next_expect_member_number() // inline std::string& parser:: next_expect_member_number (const char* n, bool su) { next_expect_name (n, su); return next_expect_number (); } inline std::string& parser:: next_expect_member_number (const std::string& n, bool su) { return next_expect_member_number (n.c_str (), su); } template inline T parser:: next_expect_member_number (const char* n, bool su) { next_expect_name (n, su); return next_expect_number (); } template inline T parser:: next_expect_member_number (const std::string& n, bool su) { return next_expect_member_number (n.c_str (), su); } // next_expect_member_boolean() // inline std::string& parser:: next_expect_member_boolean (const char* n, bool su) { next_expect_name (n, su); return next_expect_boolean (); } inline std::string& parser:: next_expect_member_boolean (const std::string& n, bool su) { return next_expect_member_boolean (n.c_str (), su); } template inline T parser:: next_expect_member_boolean (const char* n, bool su) { next_expect_name (n, su); return next_expect_boolean (); } template inline T parser:: next_expect_member_boolean (const std::string& n, bool su) { return next_expect_member_boolean (n.c_str (), su); } // next_expect_member_string_null() // inline std::string* parser:: next_expect_member_string_null (const char* n, bool su) { next_expect_name (n, su); return next_expect_string_null (); } inline std::string* parser:: next_expect_member_string_null (const std::string& n, bool su) { return next_expect_member_string_null (n.c_str (), su); } template inline optional parser:: next_expect_member_string_null (const char* n, bool su) { next_expect_name (n, su); return next_expect_string_null (); } template inline optional parser:: next_expect_member_string_null (const std::string& n, bool su) { return next_expect_member_string_null (n.c_str (), su); } // next_expect_member_number_null() // inline std::string* parser:: next_expect_member_number_null (const char* n, bool su) { next_expect_name (n, su); return next_expect_number_null (); } inline std::string* parser:: next_expect_member_number_null (const std::string& n, bool su) { return next_expect_member_number_null (n.c_str (), su); } template inline optional parser:: next_expect_member_number_null (const char* n, bool su) { next_expect_name (n, su); return next_expect_number_null (); } template inline optional parser:: next_expect_member_number_null (const std::string& n, bool su) { return next_expect_member_number_null (n.c_str (), su); } // next_expect_member_boolean_null() // inline std::string* parser:: next_expect_member_boolean_null (const char* n, bool su) { next_expect_name (n, su); return next_expect_boolean_null (); } inline std::string* parser:: next_expect_member_boolean_null (const std::string& n, bool su) { return next_expect_member_boolean_null (n.c_str (), su); } template inline optional parser:: next_expect_member_boolean_null (const char* n, bool su) { next_expect_name (n, su); return next_expect_boolean_null (); } template inline optional parser:: next_expect_member_boolean_null (const std::string& n, bool su) { return next_expect_member_boolean_null (n.c_str (), su); } // next_expect_member_object[_null]() // inline void parser:: next_expect_member_object (const char* n, bool su) { next_expect_name (n, su); next_expect (event::begin_object); } inline void parser:: next_expect_member_object (const std::string& n, bool su) { next_expect_member_object (n.c_str (), su); } inline bool parser:: next_expect_member_object_null (const char* n, bool su) { next_expect_name (n, su); return next_expect (event::begin_object, event::null); } inline bool parser:: next_expect_member_object_null (const std::string& n, bool su) { return next_expect_member_object_null (n.c_str (), su); } // next_expect_member_array[_null]() // inline void parser:: next_expect_member_array (const char* n, bool su) { next_expect_name (n, su); next_expect (event::begin_array); } inline void parser:: next_expect_member_array (const std::string& n, bool su) { next_expect_member_array (n.c_str (), su); } inline bool parser:: next_expect_member_array_null (const char* n, bool su) { next_expect_name (n, su); return next_expect (event::begin_array, event::null); } inline bool parser:: next_expect_member_array_null (const std::string& n, bool su) { return next_expect_member_array_null (n.c_str (), su); } } }