diff --git a/source/cli/meojson/json.hpp b/source/cli/meojson/json.hpp index 571d575..81ff96d 100644 --- a/source/cli/meojson/json.hpp +++ b/source/cli/meojson/json.hpp @@ -14,8 +14,6 @@ #include "packed_bytes.hpp" -#define MEOJSON_INLINE inline - namespace json { template @@ -35,13 +33,17 @@ using wvalue = basic_value; using warray = basic_array; using wobject = basic_object; -using u16value = basic_value; -using u16array = basic_array; -using u16object = basic_object; - -using u32value = basic_value; -using u32array = basic_array; -using u32object = basic_object; +namespace utils +{ + template + using iterator_t = decltype(std::declval().begin()); + template + using remove_cvref_t = std::remove_cv_t>; + template + using iter_value_t = typename std::iterator_traits>::value_type; + template + using range_value_t = iter_value_t>; +} // ********************************* // * basic_value declare * @@ -90,16 +92,33 @@ class basic_value basic_value(basic_array arr); basic_value(basic_object obj); - basic_value(std::initializer_list>> init_list); + basic_value(std::initializer_list::value_type> init_list); // Constructed from raw data template basic_value(value_type type, args_t&&... args); - // Prohibit conversion of other types to basic_value - template + template ::value_type, + utils::range_value_t>, + bool> = true> + basic_value(collection_t&& collection) : basic_value(basic_array(std::forward(collection))) + {} + template ::value_type, + utils::range_value_t>, + bool> = true> + basic_value(map_t&& map) : basic_value(basic_object(std::forward(map))) + {} + + template >, bool> = true> basic_value(value_t) = delete; + // I don't know if you want to convert char to string or number, so I delete these constructors. + basic_value(char) = delete; + basic_value(wchar_t) = delete; + basic_value(char16_t) = delete; + basic_value(char32_t) = delete; + ~basic_value(); bool valid() const noexcept { return _type != value_type::invalid; } @@ -175,6 +194,11 @@ class basic_value return format(indent, 0); } + template typename vector_t = std::vector> + vector_t to_vector() const; + template typename map_t = std::map> + map_t to_map() const; + basic_value& operator=(const basic_value& rhs); basic_value& operator=(basic_value&&) noexcept; @@ -261,19 +285,17 @@ class basic_array basic_array() = default; basic_array(const basic_array& rhs) = default; basic_array(basic_array&& rhs) noexcept = default; - basic_array(const raw_array& arr); - basic_array(raw_array&& arr) noexcept; - basic_array(std::initializer_list init_list); + basic_array(std::initializer_list init_list); basic_array(typename raw_array::size_type size); explicit basic_array(const basic_value& val); explicit basic_array(basic_value&& val); - template ::value_type>>> - basic_array(array_t arr) - { - _array_data.assign(std::make_move_iterator(arr.begin()), std::make_move_iterator(arr.end())); - } + + template >>> + basic_array(collection_t arr) + : _array_data(std::make_move_iterator(arr.begin()), std::make_move_iterator(arr.end())) + {} ~basic_array() noexcept = default; @@ -291,6 +313,8 @@ class basic_array { return format(indent, 0); } + template typename vector_t = std::vector> + vector_t to_vector() const; // Usage: get(key_1, key_2, ..., default_value); template @@ -377,17 +401,13 @@ class basic_object basic_object() = default; basic_object(const basic_object& rhs) = default; basic_object(basic_object&& rhs) noexcept = default; - basic_object(const raw_object& raw_obj); - basic_object(raw_object&& raw_obj); basic_object(std::initializer_list init_list); explicit basic_object(const basic_value& val); explicit basic_object(basic_value&& val); - template ::value_type>>> - basic_object(map_t map) - { - _object_data.insert(std::make_move_iterator(map.begin()), std::make_move_iterator(map.end())); - } + template >>> + basic_object(map_t map) : _object_data(std::make_move_iterator(map.begin()), std::make_move_iterator(map.end())) + {} ~basic_object() = default; @@ -405,6 +425,8 @@ class basic_object { return format(indent, 0); } + template typename map_t = std::map> + map_t to_map() const; // Usage: get(key_1, key_2, ..., default_value); template @@ -532,6 +554,10 @@ class exception : public std::exception template auto parse(const parsing_t& content); + +template +auto parse(char_t* content); + template , istream_t>>> auto parse(istream_t& istream, bool check_bom); @@ -543,23 +569,15 @@ namespace literals { value operator""_json(const char* str, size_t len); wvalue operator""_json(const wchar_t* str, size_t len); - u16value operator""_json(const char16_t* str, size_t len); - u32value operator""_json(const char32_t* str, size_t len); value operator""_jvalue(const char* str, size_t len); wvalue operator""_jvalue(const wchar_t* str, size_t len); - u16value operator""_jvalue(const char16_t* str, size_t len); - u32value operator""_jvalue(const char32_t* str, size_t len); array operator""_jarray(const char* str, size_t len); warray operator""_jarray(const wchar_t* str, size_t len); - u16array operator""_jarray(const char16_t* str, size_t len); - u32array operator""_jarray(const char32_t* str, size_t len); object operator""_jobject(const char* str, size_t len); wobject operator""_jobject(const wchar_t* str, size_t len); - u16object operator""_jobject(const char16_t* str, size_t len); - u32object operator""_jobject(const char32_t* str, size_t len); } template @@ -596,131 +614,114 @@ static constexpr string_t null_string() return { 'n', 'u', 'l', 'l' }; } +template +string_t to_basic_string(any_t&& arg) +{ + if constexpr (std::is_same_v) { + return std::to_string(std::forward(arg)); + } + else if constexpr (std::is_same_v) { + return std::to_wstring(std::forward(arg)); + } + else { + static_assert(!sizeof(any_t), "Unsupported type"); + } +} + template static constexpr string_t unescape_string(const string_t& str); template -MEOJSON_INLINE basic_value::basic_value() = default; +inline basic_value::basic_value() = default; template -MEOJSON_INLINE basic_value::basic_value(const basic_value& rhs) +inline basic_value::basic_value(const basic_value& rhs) : _type(rhs._type), _raw_data(deep_copy(rhs._raw_data)) -{ - ; -} +{} template -MEOJSON_INLINE basic_value::basic_value(basic_value&& rhs) noexcept = default; +inline basic_value::basic_value(basic_value&& rhs) noexcept = default; template -MEOJSON_INLINE basic_value::basic_value(bool b) +inline basic_value::basic_value(bool b) : _type(value_type::boolean), _raw_data(string_t(b ? true_string() : false_string())) -{ - ; -} +{} template -MEOJSON_INLINE basic_value::basic_value(int num) : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(int num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(unsigned num) - : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(unsigned num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(long num) : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(long num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(unsigned long num) - : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(unsigned long num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(long long num) - : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(long long num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(unsigned long long num) - : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(unsigned long long num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(float num) : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(float num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(double num) - : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(double num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(long double num) - : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(long double num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(const char_t* str) - : _type(value_type::string), _raw_data(string_t(str)) -{ - ; -} +inline basic_value::basic_value(const char_t* str) : _type(value_type::string), _raw_data(string_t(str)) +{} template -MEOJSON_INLINE basic_value::basic_value(string_t str) : _type(value_type::string), _raw_data(std::move(str)) -{ - ; -} +inline basic_value::basic_value(string_t str) : _type(value_type::string), _raw_data(std::move(str)) +{} template -MEOJSON_INLINE basic_value::basic_value(basic_array arr) +inline basic_value::basic_value(basic_array arr) : _type(value_type::array), _raw_data(std::make_unique>(std::move(arr))) -{ - ; -} +{} template -MEOJSON_INLINE basic_value::basic_value(basic_object obj) +inline basic_value::basic_value(basic_object obj) : _type(value_type::object), _raw_data(std::make_unique>(std::move(obj))) -{ - ; -} +{} template -MEOJSON_INLINE basic_value::basic_value( - std::initializer_list>> init_list) +inline basic_value::basic_value(std::initializer_list::value_type> init_list) : _type(value_type::object), _raw_data(std::make_unique>(init_list)) -{ - ; -} +{} // for Pimpl template -MEOJSON_INLINE basic_value::~basic_value() = default; +inline basic_value::~basic_value() = default; template template -MEOJSON_INLINE bool basic_value::is() const noexcept +inline bool basic_value::is() const noexcept { if constexpr (std::is_same_v, value_t>) { return true; @@ -746,44 +747,44 @@ MEOJSON_INLINE bool basic_value::is() const noexcept } template -MEOJSON_INLINE bool basic_value::contains(const string_t& key) const +inline bool basic_value::contains(const string_t& key) const { return is_object() && as_object().contains(key); } template -MEOJSON_INLINE bool basic_value::contains(size_t pos) const +inline bool basic_value::contains(size_t pos) const { return is_array() && as_array().contains(pos); } template -MEOJSON_INLINE const basic_value& basic_value::at(size_t pos) const +inline const basic_value& basic_value::at(size_t pos) const { return as_array().at(pos); } template -MEOJSON_INLINE const basic_value& basic_value::at(const string_t& key) const +inline const basic_value& basic_value::at(const string_t& key) const { return as_object().at(key); } template -MEOJSON_INLINE bool basic_value::erase(size_t pos) +inline bool basic_value::erase(size_t pos) { return as_array().erase(pos); } template -MEOJSON_INLINE bool basic_value::erase(const string_t& key) +inline bool basic_value::erase(const string_t& key) { return as_object().erase(key); } template template -MEOJSON_INLINE auto basic_value::get(key_then_default_value_t&&... keys_then_default_value) const +inline auto basic_value::get(key_then_default_value_t&&... keys_then_default_value) const { return get(std::forward_as_tuple(keys_then_default_value...), std::make_index_sequence {}); @@ -791,8 +792,8 @@ MEOJSON_INLINE auto basic_value::get(key_then_default_value_t&&... key template template -MEOJSON_INLINE auto basic_value::get(std::tuple keys_then_default_value, - std::index_sequence) const +inline auto basic_value::get(std::tuple keys_then_default_value, + std::index_sequence) const { constexpr unsigned long default_value_index = sizeof...(key_then_default_value_t) - 1; return get_helper(std::get(keys_then_default_value), @@ -801,8 +802,8 @@ MEOJSON_INLINE auto basic_value::get(std::tuple template -MEOJSON_INLINE auto basic_value::get_helper(const value_t& default_value, first_key_t&& first, - rest_keys_t&&... rest) const +inline auto basic_value::get_helper(const value_t& default_value, first_key_t&& first, + rest_keys_t&&... rest) const { if constexpr (std::is_constructible_v) { return is_object() ? as_object().get_helper(default_value, std::forward(first), @@ -821,7 +822,7 @@ MEOJSON_INLINE auto basic_value::get_helper(const value_t& default_val template template -MEOJSON_INLINE auto basic_value::get_helper(const value_t& default_value, unique_key_t&& first) const +inline auto basic_value::get_helper(const value_t& default_value, unique_key_t&& first) const { if constexpr (std::is_constructible_v) { return is_object() ? as_object().get_helper(default_value, std::forward(first)) : default_value; @@ -836,7 +837,7 @@ MEOJSON_INLINE auto basic_value::get_helper(const value_t& default_val template template -MEOJSON_INLINE auto basic_array::get(key_then_default_value_t&&... keys_then_default_value) const +inline auto basic_array::get(key_then_default_value_t&&... keys_then_default_value) const { return get(std::forward_as_tuple(keys_then_default_value...), std::make_index_sequence {}); @@ -844,8 +845,8 @@ MEOJSON_INLINE auto basic_array::get(key_then_default_value_t&&... key template template -MEOJSON_INLINE auto basic_array::get(std::tuple keys_then_default_value, - std::index_sequence) const +inline auto basic_array::get(std::tuple keys_then_default_value, + std::index_sequence) const { constexpr unsigned long default_value_index = sizeof...(key_then_default_value_t) - 1; return get_helper(std::get(keys_then_default_value), @@ -854,7 +855,7 @@ MEOJSON_INLINE auto basic_array::get(std::tuple template -MEOJSON_INLINE auto basic_object::get(key_then_default_value_t&&... keys_then_default_value) const +inline auto basic_object::get(key_then_default_value_t&&... keys_then_default_value) const { return get(std::forward_as_tuple(keys_then_default_value...), std::make_index_sequence {}); @@ -862,8 +863,8 @@ MEOJSON_INLINE auto basic_object::get(key_then_default_value_t&&... ke template template -MEOJSON_INLINE auto basic_object::get(std::tuple keys_then_default_value, - std::index_sequence) const +inline auto basic_object::get(std::tuple keys_then_default_value, + std::index_sequence) const { constexpr unsigned long default_value_index = sizeof...(key_then_default_value_t) - 1; return get_helper(std::get(keys_then_default_value), @@ -872,20 +873,20 @@ MEOJSON_INLINE auto basic_object::get(std::tuple template -MEOJSON_INLINE std::optional basic_value::find(size_t pos) const +inline std::optional basic_value::find(size_t pos) const { return is_array() ? as_array().template find(pos) : std::nullopt; } template template -MEOJSON_INLINE std::optional basic_value::find(const string_t& key) const +inline std::optional basic_value::find(const string_t& key) const { return is_object() ? as_object().template find(key) : std::nullopt; } template -MEOJSON_INLINE bool basic_value::as_boolean() const +inline bool basic_value::as_boolean() const { if (is_boolean()) { if (const string_t& b_str = as_basic_type_str(); b_str == true_string()) { @@ -904,7 +905,7 @@ MEOJSON_INLINE bool basic_value::as_boolean() const } template -MEOJSON_INLINE int basic_value::as_integer() const +inline int basic_value::as_integer() const { if (is_number()) { return std::stoi(as_basic_type_str()); @@ -915,14 +916,14 @@ MEOJSON_INLINE int basic_value::as_integer() const } template -MEOJSON_INLINE unsigned basic_value::as_unsigned() const +inline unsigned basic_value::as_unsigned() const { // I don't know why there is no std::stou. return static_cast(as_unsigned_long()); } template -MEOJSON_INLINE long basic_value::as_long() const +inline long basic_value::as_long() const { if (is_number()) { return std::stol(as_basic_type_str()); @@ -933,7 +934,7 @@ MEOJSON_INLINE long basic_value::as_long() const } template -MEOJSON_INLINE unsigned long basic_value::as_unsigned_long() const +inline unsigned long basic_value::as_unsigned_long() const { if (is_number()) { return std::stoul(as_basic_type_str()); @@ -944,7 +945,7 @@ MEOJSON_INLINE unsigned long basic_value::as_unsigned_long() const } template -MEOJSON_INLINE long long basic_value::as_long_long() const +inline long long basic_value::as_long_long() const { if (is_number()) { return std::stoll(as_basic_type_str()); @@ -955,7 +956,7 @@ MEOJSON_INLINE long long basic_value::as_long_long() const } template -MEOJSON_INLINE unsigned long long basic_value::as_unsigned_long_long() const +inline unsigned long long basic_value::as_unsigned_long_long() const { if (is_number()) { return std::stoull(as_basic_type_str()); @@ -966,7 +967,7 @@ MEOJSON_INLINE unsigned long long basic_value::as_unsigned_long_long() } template -MEOJSON_INLINE float basic_value::as_float() const +inline float basic_value::as_float() const { if (is_number()) { return std::stof(as_basic_type_str()); @@ -977,7 +978,7 @@ MEOJSON_INLINE float basic_value::as_float() const } template -MEOJSON_INLINE double basic_value::as_double() const +inline double basic_value::as_double() const { if (is_number()) { return std::stod(as_basic_type_str()); @@ -988,7 +989,7 @@ MEOJSON_INLINE double basic_value::as_double() const } template -MEOJSON_INLINE long double basic_value::as_long_double() const +inline long double basic_value::as_long_double() const { if (is_number()) { return std::stold(as_basic_type_str()); @@ -999,7 +1000,7 @@ MEOJSON_INLINE long double basic_value::as_long_double() const } template -MEOJSON_INLINE string_t basic_value::as_string() const +inline string_t basic_value::as_string() const { if (is_string()) { return as_basic_type_str(); @@ -1010,7 +1011,7 @@ MEOJSON_INLINE string_t basic_value::as_string() const } template -MEOJSON_INLINE const basic_array& basic_value::as_array() const +inline const basic_array& basic_value::as_array() const { if (is_array()) { return *std::get(_raw_data); @@ -1020,7 +1021,7 @@ MEOJSON_INLINE const basic_array& basic_value::as_array() co } template -MEOJSON_INLINE const basic_object& basic_value::as_object() const +inline const basic_object& basic_value::as_object() const { if (is_object()) { return *std::get(_raw_data); @@ -1030,7 +1031,7 @@ MEOJSON_INLINE const basic_object& basic_value::as_object() } template -MEOJSON_INLINE basic_array& basic_value::as_array() +inline basic_array& basic_value::as_array() { if (empty()) { *this = basic_array(); @@ -1044,7 +1045,7 @@ MEOJSON_INLINE basic_array& basic_value::as_array() } template -MEOJSON_INLINE basic_object& basic_value::as_object() +inline basic_object& basic_value::as_object() { if (empty()) { *this = basic_object(); @@ -1059,26 +1060,26 @@ MEOJSON_INLINE basic_object& basic_value::as_object() template template -MEOJSON_INLINE value_t basic_value::as() const +inline value_t basic_value::as() const { return static_cast(*this); } template -MEOJSON_INLINE const string_t& basic_value::as_basic_type_str() const +inline const string_t& basic_value::as_basic_type_str() const { return std::get(_raw_data); } template -MEOJSON_INLINE string_t& basic_value::as_basic_type_str() +inline string_t& basic_value::as_basic_type_str() { return std::get(_raw_data); } template template -MEOJSON_INLINE decltype(auto) basic_value::emplace(args_t&&... args) +inline decltype(auto) basic_value::emplace(args_t&&... args) { constexpr bool is_array_args = std::is_constructible_v::value_type, args_t...>; constexpr bool is_object_args = std::is_constructible_v::value_type, args_t...>; @@ -1095,26 +1096,26 @@ MEOJSON_INLINE decltype(auto) basic_value::emplace(args_t&&... args) template template -MEOJSON_INLINE decltype(auto) basic_value::array_emplace(args_t&&... args) +inline decltype(auto) basic_value::array_emplace(args_t&&... args) { return emplace(std::forward(args)...); } template template -MEOJSON_INLINE decltype(auto) basic_value::object_emplace(args_t&&... args) +inline decltype(auto) basic_value::object_emplace(args_t&&... args) { return emplace(std::forward(args)...); } template -MEOJSON_INLINE void basic_value::clear() noexcept +inline void basic_value::clear() noexcept { *this = basic_value(); } template -MEOJSON_INLINE string_t basic_value::to_string() const +inline string_t basic_value::to_string() const { switch (_type) { case value_type::null: @@ -1134,7 +1135,7 @@ MEOJSON_INLINE string_t basic_value::to_string() const } template -MEOJSON_INLINE string_t basic_value::format(size_t indent, size_t indent_times) const +inline string_t basic_value::format(size_t indent, size_t indent_times) const { switch (_type) { case value_type::null: @@ -1152,7 +1153,21 @@ MEOJSON_INLINE string_t basic_value::format(size_t indent, size_t inde } template -MEOJSON_INLINE basic_value& basic_value::operator=(const basic_value& rhs) +template typename vector_t> +inline vector_t basic_value::to_vector() const +{ + return as_array().template to_vector(); +} + +template +template typename map_t> +inline map_t basic_value::to_map() const +{ + return as_object().template to_map(); +} + +template +inline basic_value& basic_value::operator=(const basic_value& rhs) { _type = rhs._type; _raw_data = deep_copy(rhs._raw_data); @@ -1161,10 +1176,10 @@ MEOJSON_INLINE basic_value& basic_value::operator=(const bas } template -MEOJSON_INLINE basic_value& basic_value::operator=(basic_value&& rhs) noexcept = default; +inline basic_value& basic_value::operator=(basic_value&& rhs) noexcept = default; template -MEOJSON_INLINE bool basic_value::operator==(const basic_value& rhs) const +inline bool basic_value::operator==(const basic_value& rhs) const { if (_type != rhs._type) return false; @@ -1185,7 +1200,7 @@ MEOJSON_INLINE bool basic_value::operator==(const basic_value -MEOJSON_INLINE const basic_value& basic_value::operator[](size_t pos) const +inline const basic_value& basic_value::operator[](size_t pos) const { // basic_array not support to create by operator[] @@ -1193,7 +1208,7 @@ MEOJSON_INLINE const basic_value& basic_value::operator[](si } template -MEOJSON_INLINE basic_value& basic_value::operator[](size_t pos) +inline basic_value& basic_value::operator[](size_t pos) { // basic_array not support to create by operator[] @@ -1201,7 +1216,7 @@ MEOJSON_INLINE basic_value& basic_value::operator[](size_t p } template -MEOJSON_INLINE basic_value& basic_value::operator[](const string_t& key) +inline basic_value& basic_value::operator[](const string_t& key) { if (empty()) { *this = basic_object(); @@ -1211,7 +1226,7 @@ MEOJSON_INLINE basic_value& basic_value::operator[](const st } template -MEOJSON_INLINE basic_value& basic_value::operator[](string_t&& key) +inline basic_value& basic_value::operator[](string_t&& key) { if (empty()) { *this = basic_object(); @@ -1221,76 +1236,76 @@ MEOJSON_INLINE basic_value& basic_value::operator[](string_t } template -MEOJSON_INLINE basic_value basic_value::operator|(const basic_object& rhs) const& +inline basic_value basic_value::operator|(const basic_object& rhs) const& { return as_object() | rhs; } template -MEOJSON_INLINE basic_value basic_value::operator|(basic_object&& rhs) const& +inline basic_value basic_value::operator|(basic_object&& rhs) const& { return as_object() | std::move(rhs); } template -MEOJSON_INLINE basic_value basic_value::operator|(const basic_object& rhs) && +inline basic_value basic_value::operator|(const basic_object& rhs) && { return std::move(as_object()) | rhs; } template -MEOJSON_INLINE basic_value basic_value::operator|(basic_object&& rhs) && +inline basic_value basic_value::operator|(basic_object&& rhs) && { return std::move(as_object()) | std::move(rhs); } template -MEOJSON_INLINE basic_value& basic_value::operator|=(const basic_object& rhs) +inline basic_value& basic_value::operator|=(const basic_object& rhs) { as_object() |= rhs; return *this; } template -MEOJSON_INLINE basic_value& basic_value::operator|=(basic_object&& rhs) +inline basic_value& basic_value::operator|=(basic_object&& rhs) { as_object() |= std::move(rhs); return *this; } template -MEOJSON_INLINE basic_value basic_value::operator+(const basic_array& rhs) const& +inline basic_value basic_value::operator+(const basic_array& rhs) const& { return as_array() + rhs; } template -MEOJSON_INLINE basic_value basic_value::operator+(basic_array&& rhs) const& +inline basic_value basic_value::operator+(basic_array&& rhs) const& { return as_array() + std::move(rhs); } template -MEOJSON_INLINE basic_value basic_value::operator+(const basic_array& rhs) && +inline basic_value basic_value::operator+(const basic_array& rhs) && { return std::move(as_array()) + rhs; } template -MEOJSON_INLINE basic_value basic_value::operator+(basic_array&& rhs) && +inline basic_value basic_value::operator+(basic_array&& rhs) && { return std::move(as_array()) + std::move(rhs); } template -MEOJSON_INLINE basic_value& basic_value::operator+=(const basic_array& rhs) +inline basic_value& basic_value::operator+=(const basic_array& rhs) { as_array() += rhs; return *this; } template -MEOJSON_INLINE basic_value& basic_value::operator+=(basic_array&& rhs) +inline basic_value& basic_value::operator+=(basic_array&& rhs) { as_array() += std::move(rhs); return *this; @@ -1298,14 +1313,14 @@ MEOJSON_INLINE basic_value& basic_value::operator+=(basic_ar template template -basic_value::basic_value(value_type type, args_t&&... args) +inline basic_value::basic_value(value_type type, args_t&&... args) : _type(type), _raw_data(std::forward(args)...) { static_assert(std::is_constructible_v, "Parameter can't be used to construct a var_t"); } template -MEOJSON_INLINE typename basic_value::var_t basic_value::deep_copy(const var_t& src) +inline typename basic_value::var_t basic_value::deep_copy(const var_t& src) { var_t dst; if (const auto string_ptr = std::get_if(&src)) { @@ -1329,64 +1344,43 @@ MEOJSON_INLINE typename basic_value::var_t basic_value::deep // ****************************** template -MEOJSON_INLINE basic_array::basic_array(const raw_array& arr) : _array_data(arr) -{ - ; -} +inline basic_array::basic_array(std::initializer_list init_list) : _array_data(init_list) +{} template -MEOJSON_INLINE basic_array::basic_array(raw_array&& arr) noexcept : _array_data(std::move(arr)) -{ - ; -} +inline basic_array::basic_array(typename raw_array::size_type size) : _array_data(size) +{} template -MEOJSON_INLINE basic_array::basic_array(std::initializer_list init_list) : _array_data(init_list) -{ - ; -} +inline basic_array::basic_array(const basic_value& val) : basic_array(val.as_array()) +{} template -MEOJSON_INLINE basic_array::basic_array(typename raw_array::size_type size) : _array_data(size) -{ - ; -} - -template -MEOJSON_INLINE basic_array::basic_array(const basic_value& val) - : basic_array(val.as_array()) -{ - ; -} - -template -MEOJSON_INLINE basic_array::basic_array(basic_value&& val) +inline basic_array::basic_array(basic_value&& val) : basic_array(std::move(val.as_array())) -{ - ; -} +{} template -MEOJSON_INLINE void basic_array::clear() noexcept +inline void basic_array::clear() noexcept { _array_data.clear(); } template -MEOJSON_INLINE bool basic_array::erase(size_t pos) +inline bool basic_array::erase(size_t pos) { return erase(_array_data.begin() + pos); } template -MEOJSON_INLINE bool basic_array::erase(iterator iter) +inline bool basic_array::erase(iterator iter) { return _array_data.erase(iter) != _array_data.end(); } template template -MEOJSON_INLINE decltype(auto) basic_array::emplace_back(args_t&&... args) +inline decltype(auto) basic_array::emplace_back(args_t&&... args) { static_assert(std::is_constructible_v, "Parameter can't be used to construct a raw_array::value_type"); @@ -1395,19 +1389,19 @@ MEOJSON_INLINE decltype(auto) basic_array::emplace_back(args_t&&... ar template template -MEOJSON_INLINE decltype(auto) basic_array::push_back(args_t&&... args) +inline decltype(auto) basic_array::push_back(args_t&&... args) { return emplace_back(std::forward(args)...); } template -MEOJSON_INLINE const basic_value& basic_array::at(size_t pos) const +inline const basic_value& basic_array::at(size_t pos) const { return _array_data.at(pos); } template -MEOJSON_INLINE string_t basic_array::to_string() const +inline string_t basic_array::to_string() const { string_t str { '[' }; for (auto iter = _array_data.cbegin(); iter != _array_data.cend();) { @@ -1421,7 +1415,7 @@ MEOJSON_INLINE string_t basic_array::to_string() const } template -MEOJSON_INLINE string_t basic_array::format(size_t indent, size_t indent_times) const +inline string_t basic_array::format(size_t indent, size_t indent_times) const { const string_t tail_indent(indent * indent_times, ' '); const string_t body_indent(indent * (indent_times + 1), ' '); @@ -1438,10 +1432,44 @@ MEOJSON_INLINE string_t basic_array::format(size_t indent, size_t inde return str; } +namespace _to_vector_helper +{ + template + class has_emplace_back + { + template + static auto test(int) -> decltype(std::declval().emplace_back(), std::true_type()); + + template + static std::false_type test(...); + + public: + static constexpr bool value = decltype(test(0))::value; + }; +} + +template +template typename vector_t> +inline vector_t basic_array::to_vector() const +{ + + vector_t result; + if constexpr (_to_vector_helper::has_emplace_back>::value) { + for (const auto& elem : _array_data) { + result.emplace_back(elem.template as()); + } + } + else { + for (const auto& elem : _array_data) { + result.emplace(elem.template as()); + } + } + return result; +} + template template -MEOJSON_INLINE auto basic_array::get_helper(const value_t& default_value, size_t pos, - rest_keys_t&&... rest) const +inline auto basic_array::get_helper(const value_t& default_value, size_t pos, rest_keys_t&&... rest) const { constexpr bool is_json = std::is_same_v, value_t> || std::is_same_v, value_t> || @@ -1462,7 +1490,7 @@ MEOJSON_INLINE auto basic_array::get_helper(const value_t& default_val template template -MEOJSON_INLINE auto basic_array::get_helper(const value_t& default_value, size_t pos) const +inline auto basic_array::get_helper(const value_t& default_value, size_t pos) const { constexpr bool is_json = std::is_same_v, value_t> || std::is_same_v, value_t> || @@ -1499,7 +1527,7 @@ MEOJSON_INLINE auto basic_array::get_helper(const value_t& default_val template template -MEOJSON_INLINE std::optional basic_array::find(size_t pos) const +inline std::optional basic_array::find(size_t pos) const { static_assert(std::is_constructible_v>, "Type can NOT be constructed by basic_value"); @@ -1511,91 +1539,91 @@ MEOJSON_INLINE std::optional basic_array::find(size_t pos) co } template -MEOJSON_INLINE typename basic_array::iterator basic_array::begin() noexcept +inline typename basic_array::iterator basic_array::begin() noexcept { return _array_data.begin(); } template -MEOJSON_INLINE typename basic_array::iterator basic_array::end() noexcept +inline typename basic_array::iterator basic_array::end() noexcept { return _array_data.end(); } template -MEOJSON_INLINE typename basic_array::const_iterator basic_array::begin() const noexcept +inline typename basic_array::const_iterator basic_array::begin() const noexcept { return _array_data.begin(); } template -MEOJSON_INLINE typename basic_array::const_iterator basic_array::end() const noexcept +inline typename basic_array::const_iterator basic_array::end() const noexcept { return _array_data.end(); } template -MEOJSON_INLINE typename basic_array::const_iterator basic_array::cbegin() const noexcept +inline typename basic_array::const_iterator basic_array::cbegin() const noexcept { return _array_data.cbegin(); } template -MEOJSON_INLINE typename basic_array::const_iterator basic_array::cend() const noexcept +inline typename basic_array::const_iterator basic_array::cend() const noexcept { return _array_data.cend(); } template -MEOJSON_INLINE typename basic_array::reverse_iterator basic_array::rbegin() noexcept +inline typename basic_array::reverse_iterator basic_array::rbegin() noexcept { return _array_data.rbegin(); } template -MEOJSON_INLINE typename basic_array::reverse_iterator basic_array::rend() noexcept +inline typename basic_array::reverse_iterator basic_array::rend() noexcept { return _array_data.rend(); } template -MEOJSON_INLINE typename basic_array::const_reverse_iterator basic_array::rbegin() const noexcept +inline typename basic_array::const_reverse_iterator basic_array::rbegin() const noexcept { return _array_data.rbegin(); } template -MEOJSON_INLINE typename basic_array::const_reverse_iterator basic_array::rend() const noexcept +inline typename basic_array::const_reverse_iterator basic_array::rend() const noexcept { return _array_data.rend(); } template -MEOJSON_INLINE typename basic_array::const_reverse_iterator basic_array::crbegin() const noexcept +inline typename basic_array::const_reverse_iterator basic_array::crbegin() const noexcept { return _array_data.crbegin(); } template -MEOJSON_INLINE typename basic_array::const_reverse_iterator basic_array::crend() const noexcept +inline typename basic_array::const_reverse_iterator basic_array::crend() const noexcept { return _array_data.crend(); } template -MEOJSON_INLINE basic_value& basic_array::operator[](size_t pos) +inline basic_value& basic_array::operator[](size_t pos) { return _array_data[pos]; } template -MEOJSON_INLINE const basic_value& basic_array::operator[](size_t pos) const +inline const basic_value& basic_array::operator[](size_t pos) const { return _array_data[pos]; } template -MEOJSON_INLINE basic_array basic_array::operator+(const basic_array& rhs) const& +inline basic_array basic_array::operator+(const basic_array& rhs) const& { basic_array temp = *this; temp._array_data.insert(_array_data.end(), rhs.begin(), rhs.end()); @@ -1603,7 +1631,7 @@ MEOJSON_INLINE basic_array basic_array::operator+(const basi } template -MEOJSON_INLINE basic_array basic_array::operator+(basic_array&& rhs) const& +inline basic_array basic_array::operator+(basic_array&& rhs) const& { basic_array temp = *this; temp._array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()), @@ -1612,35 +1640,35 @@ MEOJSON_INLINE basic_array basic_array::operator+(basic_arra } template -MEOJSON_INLINE basic_array basic_array::operator+(const basic_array& rhs) && +inline basic_array basic_array::operator+(const basic_array& rhs) && { _array_data.insert(_array_data.end(), rhs.begin(), rhs.end()); return std::move(*this); } template -MEOJSON_INLINE basic_array basic_array::operator+(basic_array&& rhs) && +inline basic_array basic_array::operator+(basic_array&& rhs) && { _array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end())); return std::move(*this); } template -MEOJSON_INLINE basic_array& basic_array::operator+=(const basic_array& rhs) +inline basic_array& basic_array::operator+=(const basic_array& rhs) { _array_data.insert(_array_data.end(), rhs.begin(), rhs.end()); return *this; } template -MEOJSON_INLINE basic_array& basic_array::operator+=(basic_array&& rhs) +inline basic_array& basic_array::operator+=(basic_array&& rhs) { _array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end())); return *this; } template -MEOJSON_INLINE bool basic_array::operator==(const basic_array& rhs) const +inline bool basic_array::operator==(const basic_array& rhs) const { return _array_data == rhs._array_data; } @@ -1650,72 +1678,52 @@ MEOJSON_INLINE bool basic_array::operator==(const basic_array -MEOJSON_INLINE basic_object::basic_object(const raw_object& raw_obj) : _object_data(raw_obj) -{ - ; -} - -template -MEOJSON_INLINE basic_object::basic_object(raw_object&& raw_obj) : _object_data(std::move(raw_obj)) -{ - ; -} - -template -MEOJSON_INLINE basic_object::basic_object(std::initializer_list init_list) -{ - for (const auto& [key, val] : init_list) { - emplace(key, val); - } -} +inline basic_object::basic_object(std::initializer_list init_list) + : _object_data(std::make_move_iterator(init_list.begin()), std::make_move_iterator(init_list.end())) +{} template -MEOJSON_INLINE basic_object::basic_object(const basic_value& val) - : basic_object(val.as_object()) -{ - ; -} +inline basic_object::basic_object(const basic_value& val) : basic_object(val.as_object()) +{} template -MEOJSON_INLINE basic_object::basic_object(basic_value&& val) +inline basic_object::basic_object(basic_value&& val) : basic_object(std::move(val.as_object())) -{ - ; -} +{} template -MEOJSON_INLINE bool basic_object::contains(const string_t& key) const +inline bool basic_object::contains(const string_t& key) const { return _object_data.find(key) != _object_data.cend(); } template -MEOJSON_INLINE const basic_value& basic_object::at(const string_t& key) const +inline const basic_value& basic_object::at(const string_t& key) const { return _object_data.at(key); } template -MEOJSON_INLINE void basic_object::clear() noexcept +inline void basic_object::clear() noexcept { _object_data.clear(); } template -MEOJSON_INLINE bool basic_object::erase(const string_t& key) +inline bool basic_object::erase(const string_t& key) { return _object_data.erase(key) > 0 ? true : false; } template -MEOJSON_INLINE bool basic_object::erase(iterator iter) +inline bool basic_object::erase(iterator iter) { return _object_data.erase(iter) != _object_data.end(); } template template -MEOJSON_INLINE decltype(auto) basic_object::emplace(args_t&&... args) +inline decltype(auto) basic_object::emplace(args_t&&... args) { static_assert(std::is_constructible_v, "Parameter can't be used to construct a raw_object::value_type"); @@ -1724,13 +1732,13 @@ MEOJSON_INLINE decltype(auto) basic_object::emplace(args_t&&... args) template template -MEOJSON_INLINE decltype(auto) basic_object::insert(args_t&&... args) +inline decltype(auto) basic_object::insert(args_t&&... args) { return emplace(std::forward(args)...); } template -MEOJSON_INLINE string_t basic_object::to_string() const +inline string_t basic_object::to_string() const { string_t str { '{' }; for (auto iter = _object_data.cbegin(); iter != _object_data.cend();) { @@ -1745,7 +1753,7 @@ MEOJSON_INLINE string_t basic_object::to_string() const } template -MEOJSON_INLINE string_t basic_object::format(size_t indent, size_t indent_times) const +inline string_t basic_object::format(size_t indent, size_t indent_times) const { const string_t tail_indent(indent * indent_times, ' '); const string_t body_indent(indent * (indent_times + 1), ' '); @@ -1764,10 +1772,21 @@ MEOJSON_INLINE string_t basic_object::format(size_t indent, size_t ind return str; } +template +template typename map_t> +inline map_t basic_object::to_map() const +{ + map_t result; + for (const auto& [key, val] : _object_data) { + result.emplace(key, val.template as()); + } + return result; +} + template template -MEOJSON_INLINE auto basic_object::get_helper(const value_t& default_value, const string_t& key, - rest_keys_t&&... rest) const +inline auto basic_object::get_helper(const value_t& default_value, const string_t& key, + rest_keys_t&&... rest) const { constexpr bool is_json = std::is_same_v, value_t> || std::is_same_v, value_t> || @@ -1788,7 +1807,7 @@ MEOJSON_INLINE auto basic_object::get_helper(const value_t& default_va template template -MEOJSON_INLINE auto basic_object::get_helper(const value_t& default_value, const string_t& key) const +inline auto basic_object::get_helper(const value_t& default_value, const string_t& key) const { constexpr bool is_json = std::is_same_v, value_t> || std::is_same_v, value_t> || @@ -1825,7 +1844,7 @@ MEOJSON_INLINE auto basic_object::get_helper(const value_t& default_va template template -MEOJSON_INLINE std::optional basic_object::find(const string_t& key) const +inline std::optional basic_object::find(const string_t& key) const { static_assert(std::is_constructible_v>, "value_t can NOT be constructed by basic_value"); @@ -1838,55 +1857,55 @@ MEOJSON_INLINE std::optional basic_object::find(const string_ } template -MEOJSON_INLINE typename basic_object::iterator basic_object::begin() noexcept +inline typename basic_object::iterator basic_object::begin() noexcept { return _object_data.begin(); } template -MEOJSON_INLINE typename basic_object::iterator basic_object::end() noexcept +inline typename basic_object::iterator basic_object::end() noexcept { return _object_data.end(); } template -MEOJSON_INLINE typename basic_object::const_iterator basic_object::begin() const noexcept +inline typename basic_object::const_iterator basic_object::begin() const noexcept { return _object_data.begin(); } template -MEOJSON_INLINE typename basic_object::const_iterator basic_object::end() const noexcept +inline typename basic_object::const_iterator basic_object::end() const noexcept { return _object_data.end(); } template -MEOJSON_INLINE typename basic_object::const_iterator basic_object::cbegin() const noexcept +inline typename basic_object::const_iterator basic_object::cbegin() const noexcept { return _object_data.cbegin(); } template -MEOJSON_INLINE typename basic_object::const_iterator basic_object::cend() const noexcept +inline typename basic_object::const_iterator basic_object::cend() const noexcept { return _object_data.cend(); } template -MEOJSON_INLINE basic_value& basic_object::operator[](const string_t& key) +inline basic_value& basic_object::operator[](const string_t& key) { return _object_data[key]; } template -MEOJSON_INLINE basic_value& basic_object::operator[](string_t&& key) +inline basic_value& basic_object::operator[](string_t&& key) { return _object_data[std::move(key)]; } template -MEOJSON_INLINE basic_object basic_object::operator|(const basic_object& rhs) const& +inline basic_object basic_object::operator|(const basic_object& rhs) const& { basic_object temp = *this; temp._object_data.insert(rhs.begin(), rhs.end()); @@ -1894,7 +1913,7 @@ MEOJSON_INLINE basic_object basic_object::operator|(const ba } template -MEOJSON_INLINE basic_object basic_object::operator|(basic_object&& rhs) const& +inline basic_object basic_object::operator|(basic_object&& rhs) const& { basic_object temp = *this; // temp._object_data.merge(std::move(rhs._object_data)); @@ -1903,14 +1922,14 @@ MEOJSON_INLINE basic_object basic_object::operator|(basic_ob } template -MEOJSON_INLINE basic_object basic_object::operator|(const basic_object& rhs) && +inline basic_object basic_object::operator|(const basic_object& rhs) && { _object_data.insert(rhs.begin(), rhs.end()); return std::move(*this); } template -MEOJSON_INLINE basic_object basic_object::operator|(basic_object&& rhs) && +inline basic_object basic_object::operator|(basic_object&& rhs) && { //_object_data.merge(std::move(rhs._object_data)); _object_data.insert(std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end())); @@ -1918,21 +1937,21 @@ MEOJSON_INLINE basic_object basic_object::operator|(basic_ob } template -MEOJSON_INLINE basic_object& basic_object::operator|=(const basic_object& rhs) +inline basic_object& basic_object::operator|=(const basic_object& rhs) { _object_data.insert(rhs.begin(), rhs.end()); return *this; } template -MEOJSON_INLINE basic_object& basic_object::operator|=(basic_object&& rhs) +inline basic_object& basic_object::operator|=(basic_object&& rhs) { _object_data.insert(std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end())); return *this; } template -MEOJSON_INLINE bool basic_object::operator==(const basic_object& rhs) const +inline bool basic_object::operator==(const basic_object& rhs) const { return _object_data == rhs._object_data; } @@ -1942,14 +1961,13 @@ MEOJSON_INLINE bool basic_object::operator==(const basic_object -MEOJSON_INLINE std::optional> parser::parse( - const parsing_t& content) +inline std::optional> parser::parse(const parsing_t& content) { return parser(content.cbegin(), content.cend()).parse(); } template -MEOJSON_INLINE std::optional> parser::parse() +inline std::optional> parser::parse() { if (!skip_whitespace()) { return std::nullopt; @@ -1981,7 +1999,7 @@ MEOJSON_INLINE std::optional> parser -MEOJSON_INLINE basic_value parser::parse_value() +inline basic_value parser::parse_value() { switch (*_cur) { case 'n': @@ -2013,7 +2031,7 @@ MEOJSON_INLINE basic_value parser:: } template -MEOJSON_INLINE basic_value parser::parse_null() +inline basic_value parser::parse_null() { for (const auto& ch : null_string()) { if (*_cur == ch) { @@ -2028,7 +2046,7 @@ MEOJSON_INLINE basic_value parser:: } template -MEOJSON_INLINE basic_value parser::parse_boolean() +inline basic_value parser::parse_boolean() { switch (*_cur) { case 't': @@ -2057,7 +2075,7 @@ MEOJSON_INLINE basic_value parser:: } template -MEOJSON_INLINE basic_value parser::parse_number() +inline basic_value parser::parse_number() { const auto first = _cur; if (*_cur == '-') { @@ -2096,7 +2114,7 @@ MEOJSON_INLINE basic_value parser:: } template -MEOJSON_INLINE basic_value parser::parse_string() +inline basic_value parser::parse_string() { auto string_opt = parse_stdstring(); if (!string_opt) { @@ -2106,7 +2124,7 @@ MEOJSON_INLINE basic_value parser:: } template -MEOJSON_INLINE basic_value parser::parse_array() +inline basic_value parser::parse_array() { if (*_cur == '[') { ++_cur; @@ -2157,7 +2175,7 @@ MEOJSON_INLINE basic_value parser:: } template -MEOJSON_INLINE basic_value parser::parse_object() +inline basic_value parser::parse_object() { if (*_cur == '{') { ++_cur; @@ -2221,7 +2239,7 @@ MEOJSON_INLINE basic_value parser:: } template -MEOJSON_INLINE std::optional parser::parse_stdstring() +inline std::optional parser::parse_stdstring() { if (*_cur == '"') { ++_cur; @@ -2297,7 +2315,7 @@ MEOJSON_INLINE std::optional parser } template -MEOJSON_INLINE void parser::skip_string_literal() +inline void parser::skip_string_literal() { if constexpr (sizeof(*_cur) != 1) { return; @@ -2319,7 +2337,7 @@ MEOJSON_INLINE void parser::skip_string_liter } template -MEOJSON_INLINE bool parser::skip_whitespace() noexcept +inline bool parser::skip_whitespace() noexcept { while (_cur != _end) { switch (*_cur) { @@ -2339,7 +2357,7 @@ MEOJSON_INLINE bool parser::skip_whitespace() } template -MEOJSON_INLINE bool parser::skip_digit() +inline bool parser::skip_digit() { // At least one digit if (_cur != _end && std::isdigit(*_cur)) { @@ -2366,14 +2384,20 @@ MEOJSON_INLINE bool parser::skip_digit() // ************************* template -MEOJSON_INLINE auto parse(const parsing_t& content) +auto parse(const parsing_t& content) { using string_t = std::basic_string; return parser::parse(content); } +template +auto parse(char_t* content) +{ + return parse(std::basic_string_view> { content }); +} + template -MEOJSON_INLINE auto parse(istream_t& ifs, bool check_bom) +auto parse(istream_t& ifs, bool check_bom) { using string_t = std::basic_string; @@ -2400,7 +2424,7 @@ MEOJSON_INLINE auto parse(istream_t& ifs, bool check_bom) } template -MEOJSON_INLINE auto open(const path_t& filepath, bool check_bom) +auto open(const path_t& filepath, bool check_bom) { using char_t = typename ifstream_t::char_type; using string_t = std::basic_string; @@ -2449,85 +2473,49 @@ ostream_t& operator<<(ostream_t& out, const basic_object& obj) namespace literals { - MEOJSON_INLINE value operator""_json(const char* str, size_t len) - { - return operator""_jvalue(str, len); - } - MEOJSON_INLINE wvalue operator""_json(const wchar_t* str, size_t len) - { - return operator""_jvalue(str, len); - } - MEOJSON_INLINE u16value operator""_json(const char16_t* str, size_t len) + inline value operator""_json(const char* str, size_t len) { return operator""_jvalue(str, len); } - MEOJSON_INLINE u32value operator""_json(const char32_t* str, size_t len) + inline wvalue operator""_json(const wchar_t* str, size_t len) { return operator""_jvalue(str, len); } - MEOJSON_INLINE value operator""_jvalue(const char* str, size_t len) + inline value operator""_jvalue(const char* str, size_t len) { return parse(std::string_view(str, len)).value_or(value()); } - MEOJSON_INLINE wvalue operator""_jvalue(const wchar_t* str, size_t len) + inline wvalue operator""_jvalue(const wchar_t* str, size_t len) { return parse(std::wstring_view(str, len)).value_or(wvalue()); } - MEOJSON_INLINE u16value operator""_jvalue(const char16_t* str, size_t len) - { - return parse(std::u16string_view(str, len)).value_or(u16value()); - } - MEOJSON_INLINE u32value operator""_jvalue(const char32_t* str, size_t len) - { - return parse(std::u32string_view(str, len)).value_or(u32value()); - } - MEOJSON_INLINE array operator""_jarray(const char* str, size_t len) + inline array operator""_jarray(const char* str, size_t len) { auto val = parse(std::string_view(str, len)).value_or(value()); return val.is_array() ? val.as_array() : array(); } - MEOJSON_INLINE warray operator""_jarray(const wchar_t* str, size_t len) + inline warray operator""_jarray(const wchar_t* str, size_t len) { auto val = parse(std::wstring_view(str, len)).value_or(wvalue()); return val.is_array() ? val.as_array() : warray(); } - MEOJSON_INLINE u16array operator""_jarray(const char16_t* str, size_t len) - { - auto val = parse(std::u16string_view(str, len)).value_or(u16value()); - return val.is_array() ? val.as_array() : u16array(); - } - MEOJSON_INLINE u32array operator""_jarray(const char32_t* str, size_t len) - { - auto val = parse(std::u32string_view(str, len)).value_or(u32value()); - return val.is_array() ? val.as_array() : u32array(); - } - MEOJSON_INLINE object operator""_jobject(const char* str, size_t len) + inline object operator""_jobject(const char* str, size_t len) { auto val = parse(std::string_view(str, len)).value_or(value()); return val.is_object() ? val.as_object() : object(); } - MEOJSON_INLINE wobject operator""_jobject(const wchar_t* str, size_t len) + inline wobject operator""_jobject(const wchar_t* str, size_t len) { auto val = parse(std::wstring_view(str, len)).value_or(wvalue()); return val.is_object() ? val.as_object() : wobject(); } - MEOJSON_INLINE u16object operator""_jobject(const char16_t* str, size_t len) - { - auto val = parse(std::u16string_view(str, len)).value_or(u16value()); - return val.is_object() ? val.as_object() : u16object(); - } - MEOJSON_INLINE u32object operator""_jobject(const char32_t* str, size_t len) - { - auto val = parse(std::u32string_view(str, len)).value_or(u32value()); - return val.is_object() ? val.as_object() : u32object(); - } } // namespace literals template -MEOJSON_INLINE const basic_value invalid_value() +const basic_value invalid_value() { return basic_value(basic_value::value_type::invalid, typename basic_value::var_t()); } @@ -2549,27 +2537,21 @@ namespace _serialization_helper static constexpr bool value = decltype(test(0))::value; }; - template - using void_t = void; - template constexpr bool is_container = false; template - constexpr bool is_container< - T, void_t().begin()), decltype(std::declval().end())>> = - true; + constexpr bool is_container>> = + std::is_same_v>; - // something like a map template - constexpr bool is_associative_container = false; + constexpr bool is_map = false; template - constexpr bool is_associative_container> = is_container; + constexpr bool is_map> = is_container; - // something like a vector template - constexpr bool is_sequence_container = false; + constexpr bool is_collection = false; template - constexpr bool is_sequence_container = is_container && !is_associative_container; + constexpr bool is_collection = is_container && !is_map; template struct string_converter @@ -2577,6 +2559,10 @@ namespace _serialization_helper using char_t = typename string_t::value_type; using ostringstream_t = std::basic_ostringstream, std::allocator>; + template + static constexpr bool is_convertible = + std::is_constructible_v || (loose && has_output_operator::value); + template string_t operator()(input_t&& arg) const { @@ -2596,10 +2582,24 @@ namespace _serialization_helper } } }; -} + + template + void unable_to_serialize() + { + static_assert(!sizeof(T), "Unable to serialize T. " + "You can define the conversion of T to json, or overload operator<< for it. " +#ifdef _MSC_VER + "See T below: " __FUNCSIG__ +#else + //"See T below: " __PRETTY_FUNCTION__ + +#endif + ); + } +} // namespace _serialization_helper template -MEOJSON_INLINE basic_value serialize(any_t&& arg, string_converter_t&& string_converter) +basic_value serialize(any_t&& arg, string_converter_t&& string_converter) { using namespace _serialization_helper; @@ -2612,33 +2612,38 @@ MEOJSON_INLINE basic_value serialize(any_t&& arg, string_converter_t&& else if constexpr (std::is_constructible_v, any_t>) { return basic_object(std::forward(arg)); } - else if constexpr (is_sequence_container>) { + else if constexpr (std::decay_t::template is_convertible) { + return string_converter(std::forward(arg)); + } + else if constexpr (is_collection>) { basic_value result; for (auto&& val : arg) { using value_t = decltype(val); - result.emplace(serialize(std::forward(val), string_converter)); + result.emplace(serialize(std::forward(val), + std::forward(string_converter))); } return result; } - else if constexpr (is_associative_container>) { + else if constexpr (is_map>) { basic_value result; for (auto&& [key, val] : arg) { using key_t = decltype(key); using value_t = decltype(val); result.emplace(string_converter(std::forward(key)), - serialize(std::forward(val), string_converter)); + serialize(std::forward(val), + std::forward(string_converter))); } return result; } else { - return string_converter(std::forward(arg)); + unable_to_serialize(); } } template -MEOJSON_INLINE static constexpr string_t unescape_string(const string_t& str) +static constexpr string_t unescape_string(const string_t& str) { using char_t = typename string_t::value_type; diff --git a/source/cli/meojson/json5.hpp b/source/cli/meojson/json5.hpp index d6ca3f5..d2ceefa 100644 --- a/source/cli/meojson/json5.hpp +++ b/source/cli/meojson/json5.hpp @@ -12,1702 +12,1675 @@ namespace json { - // ************************* - // * declare * - // ************************* +// ************************* +// * declare * +// ************************* - template - class parser5 - { - private: - using StringIterT = typename StringT::const_iterator; - using u8char = uint64_t; - - /* exceptions */ - public: - class exception : public json::exception - { - public: - exception() = default; - exception(const std::string& type, const std::string& msg, - const std::string& detail) - { - std::stringstream ss; - ss << "JSON5: [" << type << "] " << msg << '\n'; - ss << detail << std::endl; - _what = ss.str(); - } - exception(const exception&) = default; - exception& operator=(const exception&) = default; - exception(exception&&) = default; - exception& operator=(exception&&) = default; - - virtual ~exception() noexcept = default; - }; - - class InvalidChar : public exception - { - public: - InvalidChar(u8char ch = 0, const std::string& detail = "") - : exception("Invalid Char", - "Unexpected token \'" + StringFromCharCode(ch) + "\'", - detail) - {} - }; - - class InvalidIdentifier : public exception - { - public: - InvalidIdentifier(const std::string& msg = "", - const std::string& detail = "") - : exception("Invalid Identifier", msg, detail) - {} - }; - - class InvalidEOF : public exception - { - public: - InvalidEOF(const std::string& msg = "", const std::string& detail = "") - : exception("Invalid EOF", msg, detail) - {} - }; +template +class parser5 +{ +private: + using StringIterT = typename StringT::const_iterator; + using u8char = uint64_t; + /* exceptions */ +public: + class exception : public json::exception + { public: - std::string exceptionDetailInfo() + exception() = default; + exception(const std::string& type, const std::string& msg, const std::string& detail) { - size_t start_point = _col; - auto len = _print_len; - auto current_line = _line_begin_cur; std::stringstream ss; - ss << "at line " << _line << ", column " << _col + 1 << '\n'; - - while (read() != '\n' && _cur != _end && (_col - start_point) < 5) - ; - ss << std::string(current_line, _cur) << '\n'; - ss << std::setw(len) << '^' << '\n'; - return ss.str(); + ss << "JSON5: [" << type << "] " << msg << '\n'; + ss << detail << std::endl; + _what = ss.str(); } + exception(const exception&) = default; + exception& operator=(const exception&) = default; + exception(exception&&) = default; + exception& operator=(exception&&) = default; - /* helper class and type */ - private: - class unicode - { - public: - static const std::wregex space_separator; - static const std::wregex id_start; - static const std::wregex id_continue; - - static bool isSpaceSeparator(u8char ch); - static bool isIdStartChar(u8char ch); - static bool isIdContinueChar(u8char ch); - static bool isDigit(u8char ch); - static bool isHexDigit(u8char ch); - }; - - enum class LexState - { - default_ = 0, - comment, - multiLineComment, - multiLineCommentAsterisk, - singleLineComment, - value, - identifierNameStartEscape, - identifierName, - identifierNameEscape, - sign, - zero, - decimalInteger, - decimalPointLeading, - decimalPoint, - decimalFraction, - decimalExponent, - decimalExponentSign, - decimalExponentInteger, - hexadecimal, - hexadecimalInteger, - string, - start, - beforePropertyName, - afterPropertyName, - beforePropertyValue, - afterPropertyValue, - beforeArrayValue, - afterArrayValue, - end - }; - - enum class ParseState - { - start = 21, - beforePropertyName, - afterPropertyName, - beforePropertyValue, - afterPropertyValue, - beforeArrayValue, - afterArrayValue, - end - }; - - enum class TokenType - { - punctuator = 0, - identifier, - null, - boolean, - numeric, - string, - eof, - }; - - struct Token - { - TokenType type; - value _value; - size_t col = 0; - size_t line = 0; - }; + virtual ~exception() noexcept = default; + }; - /* constrators and callers */ + class InvalidChar : public exception + { public: - ~parser5() noexcept = default; - static std::optional parse(const StringT& content, std::string* error = nullptr); - - private: - parser5(const StringIterT& cbegin, - const StringIterT& cend) noexcept - : _cur(cbegin), _end(cend), _line_begin_cur(cbegin) + InvalidChar(u8char ch = 0, const std::string& detail = "") + : exception("Invalid Char", "Unexpected token \'" + StringFromCharCode(ch) + "\'", detail) {} - std::optional parse(); - - private: - /* utf-8 reader */ - static u8char peek(StringIterT& begin, - const StringIterT& end, - size_t* len = nullptr); - static u8char peek(const std::string& str); - typename parser5::u8char read(); - static std::string StringFromCharCode(u8char code); - /* escape and format */ - void literal(const std::string& s); - std::optional escape(); - u8char hexEscape(); - u8char unicodeEscape(); - /* lex, parse, token */ - Token lex(); - Token newToken(TokenType type, value value); - - std::optional lex_default(); - std::optional lex_comment(); - std::optional lex_multiLineComment(); - std::optional lex_multiLineCommentAsterisk(); - std::optional lex_singleLineComment(); - std::optional lex_value(); - std::optional lex_identifierNameStartEscape(); - std::optional lex_identifierName(); - std::optional lex_identifierNameEscape(); - std::optional lex_sign(); - std::optional lex_zero(); - std::optional lex_decimalInteger(); - std::optional lex_decimalPointLeading(); - std::optional lex_decimalPoint(); - std::optional lex_decimalFraction(); - std::optional lex_decimalExponent(); - std::optional lex_decimalExponentSign(); - std::optional lex_decimalExponentInteger(); - std::optional lex_hexadecimal(); - std::optional lex_hexdecimalInteger(); - std::optional lex_string(); - std::optional lex_start(); - std::optional lex_beforePropertyName(); - std::optional lex_afterPropertyName(); - std::optional lex_beforePropertyValue(); - std::optional lex_afterPropertyValue(); - std::optional lex_beforeArrayValue(); - std::optional lex_afterArrayValue(); - std::optional lex_end(); - - std::optional lexStates(LexState state); - - void parse_start(); - void parse_beforePropertyName(); - void parse_afterPropertyName(); - void parse_beforePropertyValue(); - void parse_beforeArrayValue(); - void parse_afterPropertyValue(); - void parse_afterArrayValue(); - void parse_end(); - - void parseStates(ParseState state); - - /* stack operation */ - void push(); - void pop(); - - private: - StringIterT _cur, _end; - StringIterT _line_begin_cur; - size_t _line = 1, _col = 0, _print_len = 0; - ParseState _parse_state = ParseState::start; - std::stack _stack; - std::optional _token; - std::string _key; - std::optional _root; - - LexState _lex_state = LexState::default_; - std::string _buffer; - bool _double_quote = false; - int64_t _sign = 1; - u8char _current_char = 0; }; - // ************************* - // * implementation * - // ************************* - - /* parser5::unicode */ - template - MEOJSON_INLINE const std::wregex parser5::unicode::space_separator = - std::wregex(LR"([\u1680\u2000-\u200A\u202F\u205F\u3000])"); - - template - MEOJSON_INLINE const std::wregex parser5::unicode::id_start = std::wregex( - LR"([\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-)" - LR"(\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-)" - LR"(\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-)" - LR"(\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-)" - LR"(\u05F2\u0620-\u064A\u066E\u066F\u0671-)" - LR"(\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-)" - LR"(\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-)" - LR"(\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-)" - LR"(\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-)" - LR"(\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-)" - LR"(\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-)" - LR"(\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-)" - LR"(\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-)" - LR"(\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-)" - LR"(\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-)" - LR"(\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-)" - LR"(\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-)" - LR"(\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-)" - LR"(\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-)" - LR"(\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-)" - LR"(\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-)" - LR"(\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-)" - LR"(\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-)" - LR"(\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-)" - LR"(\u0E30\u0E32\u0E33\u0E40-)" - LR"(\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-)" - LR"(\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-)" - LR"(\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-)" - LR"(\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-)" - LR"(\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-)" - LR"(\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-)" - LR"(\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-)" - LR"(\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-)" - LR"(\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-)" - LR"(\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-)" - LR"(\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-)" - LR"(\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-)" - LR"(\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-)" - LR"(\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-)" - LR"(\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-)" - LR"(\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-)" - LR"(\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-)" - LR"(\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-)" - LR"(\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-)" - LR"(\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-)" - LR"(\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-)" - LR"(\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-)" - LR"(\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-)" - LR"(\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-)" - LR"(\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-)" - LR"(\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-)" - LR"(\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-)" - LR"(\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-)" - LR"(\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-)" - LR"(\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-)" - LR"(\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-)" - LR"(\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-)" - LR"(\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-)" - LR"(\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-)" - LR"(\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-)" - LR"(\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-)" - LR"(\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-)" - LR"(\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-)" - LR"(\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-)" - LR"(\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-)" - LR"(\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-)" - LR"(\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-)" - LR"(\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-)" - LR"(\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-)" - LR"(\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-)" - LR"(\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-)" - LR"(\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-)" - LR"(\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-)" - LR"(\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-)" - LR"(\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-)" - LR"(\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-)" - LR"(\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-)" - LR"(\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-)" - LR"(\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-)" - LR"(\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-)" - LR"(\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-)" - LR"(\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-)" - LR"(\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-)" - LR"(\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-)" - LR"(\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-)" - LR"(\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-)" - LR"(\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-)" - LR"(\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-)" - LR"(\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|)" - LR"(\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-)" - LR"(\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[)" - LR"(\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-)" - LR"(\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|)" - LR"(\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC])" - LR"(|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-)" - LR"(\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-)" - LR"(\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-)" - LR"(\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-)" - LR"(\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-)" - LR"(\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-)" - LR"(\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-)" - LR"(\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-)" - LR"(\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-)" - LR"(\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-)" - LR"(\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64)" - LR"(\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-)" - LR"(\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-)" - LR"(\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-)" - LR"(\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-)" - LR"(\uDFE0]|\uD87E[\uDC00-\uDE1D])"); - template - MEOJSON_INLINE const std::wregex parser5::unicode::id_continue = std::wregex( - LR"([\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-)" - LR"(\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-)" - LR"(\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-)" - LR"(\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-)" - LR"(\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-)" - LR"(\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-)" - LR"(\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-)" - LR"(\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-)" - LR"(\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-)" - LR"(\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-)" - LR"(\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-)" - LR"(\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-)" - LR"(\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-)" - LR"(\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-)" - LR"(\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-)" - LR"(\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-)" - LR"(\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-)" - LR"(\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-)" - LR"(\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-)" - LR"(\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-)" - LR"(\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-)" - LR"(\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-)" - LR"(\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-)" - LR"(\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-)" - LR"(\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-)" - LR"(\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-)" - LR"(\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-)" - LR"(\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-)" - LR"(\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-)" - LR"(\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-)" - LR"(\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-)" - LR"(\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-)" - LR"(\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-)" - LR"(\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-)" - LR"(\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-)" - LR"(\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-)" - LR"(\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-)" - LR"(\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-)" - LR"(\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-)" - LR"(\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-)" - LR"(\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-)" - LR"(\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-)" - LR"(\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-)" - LR"(\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-)" - LR"(\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-)" - LR"(\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-)" - LR"(\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-)" - LR"(\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-)" - LR"(\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-)" - LR"(\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-)" - LR"(\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-)" - LR"(\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-)" - LR"(\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-)" - LR"(\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-)" - LR"(\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-)" - LR"(\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-)" - LR"(\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-)" - LR"(\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-)" - LR"(\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-)" - LR"(\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-)" - LR"(\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-)" - LR"(\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-)" - LR"(\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-)" - LR"(\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-)" - LR"(\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-)" - LR"(\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-)" - LR"(\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-)" - LR"(\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-)" - LR"(\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-)" - LR"(\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-)" - LR"(\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-)" - LR"(\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-)" - LR"(\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-)" - LR"(\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-)" - LR"(\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-)" - LR"(\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-)" - LR"(\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-)" - LR"(\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-)" - LR"(\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-)" - LR"(\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-)" - LR"(\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-)" - LR"(\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-)" - LR"(\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|)" - LR"(\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-)" - LR"(\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-)" - LR"(\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-)" - LR"(\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-)" - LR"(\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-)" - LR"(\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-)" - LR"(\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-)" - LR"(\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|)" - LR"(\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-)" - LR"(\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-)" - LR"(\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-)" - LR"(\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-)" - LR"(\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-)" - LR"(\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-)" - LR"(\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-)" - LR"(\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-)" - LR"(\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-)" - LR"(\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-)" - LR"(\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|)" - LR"(\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-)" - LR"(\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-)" - LR"(\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|)" - LR"(\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-)" - LR"(\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[)" - LR"(\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-)" - LR"(\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-)" - LR"(\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-)" - LR"(\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-)" - LR"(\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-)" - LR"(\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-)" - LR"(\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-)" - LR"(\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-)" - LR"(\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-)" - LR"(\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-)" - LR"(\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-)" - LR"(\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-)" - LR"(\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-)" - LR"(\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-)" - LR"(\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-)" - LR"(\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-)" - LR"(\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-)" - LR"(\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-)" - LR"(\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64)" - LR"(\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-)" - LR"(\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-)" - LR"(\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-)" - LR"(\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-)" - LR"(\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]|[\u200C\u200D])"); - - template - MEOJSON_INLINE bool parser5::unicode::isSpaceSeparator(u8char ch) + class InvalidIdentifier : public exception { -#ifdef _MSC_VER - std::wstring wstr = { (wchar_t)ch, 0 }; -#else - auto str = StringFromCharCode(ch); - auto len = str.size() + 1; - std::unique_ptr p(new wchar_t[len]); - std::setlocale(LC_CTYPE, ".UTF8"); - std::mbstowcs(p.get(), str.c_str(), len); - std::wstring wstr(p.get()); -#endif - return std::regex_search(wstr, unicode::space_separator); - } + public: + InvalidIdentifier(const std::string& msg = "", const std::string& detail = "") + : exception("Invalid Identifier", msg, detail) + {} + }; - template - MEOJSON_INLINE bool parser5::unicode::isIdStartChar(u8char ch) + class InvalidEOF : public exception { -#ifdef _MSC_VER - std::wstring wstr = { (wchar_t)ch, 0 }; -#else - auto str = StringFromCharCode(ch); - auto len = str.size() + 1; - std::unique_ptr p(new wchar_t[len]); - std::setlocale(LC_CTYPE, ".UTF8"); - std::mbstowcs(p.get(), str.c_str(), len); - std::wstring wstr(p.get()); -#endif - return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '$') || - (ch == '_') || std::regex_search(wstr, unicode::id_start); - } + public: + InvalidEOF(const std::string& msg = "", const std::string& detail = "") : exception("Invalid EOF", msg, detail) + {} + }; - template - MEOJSON_INLINE bool parser5::unicode::isIdContinueChar(u8char ch) +public: + std::string exceptionDetailInfo() { -#ifdef _MSC_VER - std::wstring wstr = { (wchar_t)ch, 0 }; -#else - auto str = StringFromCharCode(ch); - auto len = str.size() + 1; - std::unique_ptr p(new wchar_t[len]); - std::setlocale(LC_CTYPE, ".UTF8"); - std::mbstowcs(p.get(), str.c_str(), len); - std::wstring wstr(p.get()); -#endif - return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || - (ch >= '0' && ch <= '9') || (ch == '$') || (ch == '_') || - std::regex_search(wstr, unicode::id_continue); + size_t start_point = _col; + auto len = _print_len; + auto current_line = _line_begin_cur; + std::stringstream ss; + ss << "at line " << _line << ", column " << _col + 1 << '\n'; + + while (read() != '\n' && _cur != _end && (_col - start_point) < 5) + ; + ss << std::string(current_line, _cur) << '\n'; + ss << std::setw(len) << '^' << '\n'; + return ss.str(); } - template - MEOJSON_INLINE bool parser5::unicode::isDigit(u8char ch) + /* helper class and type */ +private: + class unicode { - auto str = StringFromCharCode(ch); - return std::regex_search(str, std::regex(R"([0-9])")); - } + public: + static const std::wregex space_separator; + static const std::wregex id_start; + static const std::wregex id_continue; + + static bool isSpaceSeparator(u8char ch); + static bool isIdStartChar(u8char ch); + static bool isIdContinueChar(u8char ch); + static bool isDigit(u8char ch); + static bool isHexDigit(u8char ch); + }; - template - MEOJSON_INLINE bool parser5::unicode::isHexDigit(u8char ch) + enum class LexState { - auto str = StringFromCharCode(ch); - return std::regex_search(str, std::regex(R"([0-9A-Fa-f])")); - } + default_ = 0, + comment, + multiLineComment, + multiLineCommentAsterisk, + singleLineComment, + value, + identifierNameStartEscape, + identifierName, + identifierNameEscape, + sign, + zero, + decimalInteger, + decimalPointLeading, + decimalPoint, + decimalFraction, + decimalExponent, + decimalExponentSign, + decimalExponentInteger, + hexadecimal, + hexadecimalInteger, + string, + start, + beforePropertyName, + afterPropertyName, + beforePropertyValue, + afterPropertyValue, + beforeArrayValue, + afterArrayValue, + end + }; - /* constrators and callers */ - template - MEOJSON_INLINE std::optional parse5(const StringT& content, std::string* error = nullptr) + enum class ParseState { - return parser5::parse(content, error); - } + start = 21, + beforePropertyName, + afterPropertyName, + beforePropertyValue, + afterPropertyValue, + beforeArrayValue, + afterArrayValue, + end + }; - /* Wrapper for handling input of C-style strings. */ - template - MEOJSON_INLINE std::optional parse5(CharT* content, std::string* error = nullptr) + enum class TokenType { - return parse5(std::basic_string_view::type>{content}, error); - } + punctuator = 0, + identifier, + null, + boolean, + numeric, + string, + eof, + }; - template - MEOJSON_INLINE std::optional parser5::parse(const StringT& content, std::string* error) + struct Token { - try { - return parser5(content.cbegin(), content.cend()).parse(); - } - catch (json::parser5::exception& ex) { - if (error) { - *error = ex.what(); - } - } - return std::nullopt; - } + TokenType type; + value _value; + size_t col = 0; + size_t line = 0; + }; - template - MEOJSON_INLINE std::optional parser5::parse() - { - do { - _token = lex(); - parseStates(_parse_state); - } while (_token->type != TokenType::eof); + /* constrators and callers */ +public: + ~parser5() noexcept = default; + static std::optional parse(const StringT& content, std::string* error = nullptr); - return _root; - } +private: + parser5(const StringIterT& cbegin, const StringIterT& cend) noexcept + : _cur(cbegin), _end(cend), _line_begin_cur(cbegin) + {} + std::optional parse(); +private: + /* utf-8 reader */ + static u8char peek(StringIterT& begin, const StringIterT& end, size_t* len = nullptr); + static u8char peek(const std::string& str); + typename parser5::u8char read(); + static std::string StringFromCharCode(u8char code); /* escape and format */ - template - MEOJSON_INLINE void parser5::literal(const std::string& s) - { - for (const auto& ch : s) { - char p = static_cast(read()); - if (p != ch) { - throw InvalidChar(_current_char, exceptionDetailInfo()); - } - } - } - - template - MEOJSON_INLINE std::optional::u8char> parser5::escape() - { - auto c = peek(_cur, _end); - switch (c) { - case 'b': - read(); - return '\b'; + void literal(const std::string& s); + std::optional escape(); + u8char hexEscape(); + u8char unicodeEscape(); + /* lex, parse, token */ + Token lex(); + Token newToken(TokenType type, value value); + + std::optional lex_default(); + std::optional lex_comment(); + std::optional lex_multiLineComment(); + std::optional lex_multiLineCommentAsterisk(); + std::optional lex_singleLineComment(); + std::optional lex_value(); + std::optional lex_identifierNameStartEscape(); + std::optional lex_identifierName(); + std::optional lex_identifierNameEscape(); + std::optional lex_sign(); + std::optional lex_zero(); + std::optional lex_decimalInteger(); + std::optional lex_decimalPointLeading(); + std::optional lex_decimalPoint(); + std::optional lex_decimalFraction(); + std::optional lex_decimalExponent(); + std::optional lex_decimalExponentSign(); + std::optional lex_decimalExponentInteger(); + std::optional lex_hexadecimal(); + std::optional lex_hexdecimalInteger(); + std::optional lex_string(); + std::optional lex_start(); + std::optional lex_beforePropertyName(); + std::optional lex_afterPropertyName(); + std::optional lex_beforePropertyValue(); + std::optional lex_afterPropertyValue(); + std::optional lex_beforeArrayValue(); + std::optional lex_afterArrayValue(); + std::optional lex_end(); + + std::optional lexStates(LexState state); + + void parse_start(); + void parse_beforePropertyName(); + void parse_afterPropertyName(); + void parse_beforePropertyValue(); + void parse_beforeArrayValue(); + void parse_afterPropertyValue(); + void parse_afterArrayValue(); + void parse_end(); + + void parseStates(ParseState state); - case 'f': - read(); - return '\f'; + /* stack operation */ + void push(); + void pop(); + +private: + StringIterT _cur, _end; + StringIterT _line_begin_cur; + size_t _line = 1, _col = 0, _print_len = 0; + ParseState _parse_state = ParseState::start; + std::stack _stack; + std::optional _token; + std::string _key; + std::optional _root; + + LexState _lex_state = LexState::default_; + std::string _buffer; + bool _double_quote = false; + int64_t _sign = 1; + u8char _current_char = 0; +}; + +// ************************* +// * implementation * +// ************************* + +/* parser5::unicode */ +template +inline const std::wregex parser5::unicode::space_separator = + std::wregex(LR"([\u1680\u2000-\u200A\u202F\u205F\u3000])"); + +template +inline const std::wregex parser5::unicode::id_start = + std::wregex(LR"([\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-)" + LR"(\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-)" + LR"(\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-)" + LR"(\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-)" + LR"(\u05F2\u0620-\u064A\u066E\u066F\u0671-)" + LR"(\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-)" + LR"(\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-)" + LR"(\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-)" + LR"(\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-)" + LR"(\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-)" + LR"(\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-)" + LR"(\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-)" + LR"(\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-)" + LR"(\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-)" + LR"(\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-)" + LR"(\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-)" + LR"(\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-)" + LR"(\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-)" + LR"(\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-)" + LR"(\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-)" + LR"(\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-)" + LR"(\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-)" + LR"(\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-)" + LR"(\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-)" + LR"(\u0E30\u0E32\u0E33\u0E40-)" + LR"(\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-)" + LR"(\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-)" + LR"(\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-)" + LR"(\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-)" + LR"(\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-)" + LR"(\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-)" + LR"(\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-)" + LR"(\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-)" + LR"(\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-)" + LR"(\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-)" + LR"(\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-)" + LR"(\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-)" + LR"(\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-)" + LR"(\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-)" + LR"(\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-)" + LR"(\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-)" + LR"(\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-)" + LR"(\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-)" + LR"(\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-)" + LR"(\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-)" + LR"(\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-)" + LR"(\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-)" + LR"(\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-)" + LR"(\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-)" + LR"(\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-)" + LR"(\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-)" + LR"(\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-)" + LR"(\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-)" + LR"(\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-)" + LR"(\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-)" + LR"(\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-)" + LR"(\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-)" + LR"(\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-)" + LR"(\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-)" + LR"(\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-)" + LR"(\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-)" + LR"(\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-)" + LR"(\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-)" + LR"(\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-)" + LR"(\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-)" + LR"(\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-)" + LR"(\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-)" + LR"(\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-)" + LR"(\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-)" + LR"(\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-)" + LR"(\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-)" + LR"(\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-)" + LR"(\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-)" + LR"(\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-)" + LR"(\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-)" + LR"(\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-)" + LR"(\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-)" + LR"(\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-)" + LR"(\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-)" + LR"(\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-)" + LR"(\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-)" + LR"(\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-)" + LR"(\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-)" + LR"(\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-)" + LR"(\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-)" + LR"(\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-)" + LR"(\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-)" + LR"(\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-)" + LR"(\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|)" + LR"(\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-)" + LR"(\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[)" + LR"(\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-)" + LR"(\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|)" + LR"(\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC])" + LR"(|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-)" + LR"(\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-)" + LR"(\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-)" + LR"(\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-)" + LR"(\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-)" + LR"(\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-)" + LR"(\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-)" + LR"(\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-)" + LR"(\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-)" + LR"(\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-)" + LR"(\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64)" + LR"(\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-)" + LR"(\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-)" + LR"(\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-)" + LR"(\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-)" + LR"(\uDFE0]|\uD87E[\uDC00-\uDE1D])"); +template +inline const std::wregex parser5::unicode::id_continue = + std::wregex(LR"([\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-)" + LR"(\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-)" + LR"(\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-)" + LR"(\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-)" + LR"(\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-)" + LR"(\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-)" + LR"(\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-)" + LR"(\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-)" + LR"(\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-)" + LR"(\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-)" + LR"(\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-)" + LR"(\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-)" + LR"(\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-)" + LR"(\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-)" + LR"(\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-)" + LR"(\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-)" + LR"(\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-)" + LR"(\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-)" + LR"(\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-)" + LR"(\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-)" + LR"(\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-)" + LR"(\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-)" + LR"(\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-)" + LR"(\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-)" + LR"(\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-)" + LR"(\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-)" + LR"(\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-)" + LR"(\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-)" + LR"(\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-)" + LR"(\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-)" + LR"(\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-)" + LR"(\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-)" + LR"(\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-)" + LR"(\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-)" + LR"(\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-)" + LR"(\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-)" + LR"(\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-)" + LR"(\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-)" + LR"(\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-)" + LR"(\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-)" + LR"(\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-)" + LR"(\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-)" + LR"(\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-)" + LR"(\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-)" + LR"(\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-)" + LR"(\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-)" + LR"(\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-)" + LR"(\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-)" + LR"(\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-)" + LR"(\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-)" + LR"(\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-)" + LR"(\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-)" + LR"(\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-)" + LR"(\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-)" + LR"(\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-)" + LR"(\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-)" + LR"(\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-)" + LR"(\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-)" + LR"(\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-)" + LR"(\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-)" + LR"(\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-)" + LR"(\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-)" + LR"(\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-)" + LR"(\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-)" + LR"(\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-)" + LR"(\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-)" + LR"(\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-)" + LR"(\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-)" + LR"(\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-)" + LR"(\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-)" + LR"(\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-)" + LR"(\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-)" + LR"(\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-)" + LR"(\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-)" + LR"(\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-)" + LR"(\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-)" + LR"(\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-)" + LR"(\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-)" + LR"(\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-)" + LR"(\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-)" + LR"(\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-)" + LR"(\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-)" + LR"(\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|)" + LR"(\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-)" + LR"(\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-)" + LR"(\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-)" + LR"(\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-)" + LR"(\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-)" + LR"(\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-)" + LR"(\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-)" + LR"(\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|)" + LR"(\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-)" + LR"(\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-)" + LR"(\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-)" + LR"(\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-)" + LR"(\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-)" + LR"(\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-)" + LR"(\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-)" + LR"(\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-)" + LR"(\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-)" + LR"(\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-)" + LR"(\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|)" + LR"(\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-)" + LR"(\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-)" + LR"(\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|)" + LR"(\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-)" + LR"(\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[)" + LR"(\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-)" + LR"(\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-)" + LR"(\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-)" + LR"(\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-)" + LR"(\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-)" + LR"(\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-)" + LR"(\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-)" + LR"(\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-)" + LR"(\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-)" + LR"(\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-)" + LR"(\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-)" + LR"(\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-)" + LR"(\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-)" + LR"(\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-)" + LR"(\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-)" + LR"(\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-)" + LR"(\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-)" + LR"(\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-)" + LR"(\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64)" + LR"(\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-)" + LR"(\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-)" + LR"(\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-)" + LR"(\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-)" + LR"(\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]|[\u200C\u200D])"); + +template +inline bool parser5::unicode::isSpaceSeparator(u8char ch) +{ +#ifdef _MSC_VER + std::wstring wstr = { (wchar_t)ch, 0 }; +#else + auto str = StringFromCharCode(ch); + auto len = str.size() + 1; + std::unique_ptr p(new wchar_t[len]); + std::setlocale(LC_CTYPE, ".UTF8"); + std::mbstowcs(p.get(), str.c_str(), len); + std::wstring wstr(p.get()); +#endif + return std::regex_search(wstr, unicode::space_separator); +} - case 'n': - read(); - return '\n'; +template +inline bool parser5::unicode::isIdStartChar(u8char ch) +{ +#ifdef _MSC_VER + std::wstring wstr = { (wchar_t)ch, 0 }; +#else + auto str = StringFromCharCode(ch); + auto len = str.size() + 1; + std::unique_ptr p(new wchar_t[len]); + std::setlocale(LC_CTYPE, ".UTF8"); + std::mbstowcs(p.get(), str.c_str(), len); + std::wstring wstr(p.get()); +#endif + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '$') || (ch == '_') || + std::regex_search(wstr, unicode::id_start); +} - case 'r': - read(); - return '\r'; +template +inline bool parser5::unicode::isIdContinueChar(u8char ch) +{ +#ifdef _MSC_VER + std::wstring wstr = { (wchar_t)ch, 0 }; +#else + auto str = StringFromCharCode(ch); + auto len = str.size() + 1; + std::unique_ptr p(new wchar_t[len]); + std::setlocale(LC_CTYPE, ".UTF8"); + std::mbstowcs(p.get(), str.c_str(), len); + std::wstring wstr(p.get()); +#endif + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '$') || + (ch == '_') || std::regex_search(wstr, unicode::id_continue); +} - case 't': - read(); - return '\t'; +template +inline bool parser5::unicode::isDigit(u8char ch) +{ + auto str = StringFromCharCode(ch); + return std::regex_search(str, std::regex(R"([0-9])")); +} - case 'v': - read(); - return '\v'; +template +inline bool parser5::unicode::isHexDigit(u8char ch) +{ + auto str = StringFromCharCode(ch); + return std::regex_search(str, std::regex(R"([0-9A-Fa-f])")); +} - case '0': - read(); - if (unicode::isDigit(peek(_cur, _end))) { - throw InvalidChar(_current_char, exceptionDetailInfo()); - } +/* constrators and callers */ +template +std::optional parse5(const StringT& content, std::string* error = nullptr) +{ + return parser5::parse(content, error); +} - return '\0'; +/* Wrapper for handling input of C-style strings. */ +template +std::optional parse5(CharT* content, std::string* error = nullptr) +{ + return parse5(std::basic_string_view> { content }, error); +} - case 'x': - read(); - return hexEscape(); +template +inline std::optional parser5::parse(const StringT& content, std::string* error) +{ + try { + return parser5(content.cbegin(), content.cend()).parse(); + } + catch (json::parser5::exception& ex) { + if (error) { + *error = ex.what(); + } + } + return std::nullopt; +} - case 'u': - read(); - return unicodeEscape(); +template +inline std::optional parser5::parse() +{ + do { + _token = lex(); + parseStates(_parse_state); + } while (_token->type != TokenType::eof); - case '\n': - case 0x2028: - case 0x2029: - read(); - return 0; + return _root; +} - case '\r': - read(); - if (peek(_cur, _end) == '\n') { - read(); - } - - return std::nullopt; - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': +/* escape and format */ +template +inline void parser5::literal(const std::string& s) +{ + for (const auto& ch : s) { + char p = static_cast(read()); + if (p != ch) { throw InvalidChar(_current_char, exceptionDetailInfo()); - default: - if (c == 0) { - throw InvalidChar(_current_char, exceptionDetailInfo()); - } } - - return read(); } +} - template - MEOJSON_INLINE typename parser5::u8char parser5::hexEscape() - { - std::string buffer = ""; - auto c = peek(_cur, _end); +template +inline std::optional::u8char> parser5::escape() +{ + auto c = peek(_cur, _end); + switch (c) { + case 'b': + read(); + return '\b'; - if (!unicode::isHexDigit(c)) { - throw InvalidChar(_current_char, exceptionDetailInfo()); - } + case 'f': + read(); + return '\f'; - buffer += static_cast(read()); + case 'n': + read(); + return '\n'; - c = peek(_cur, _end); - if (!unicode::isHexDigit(c)) { + case 'r': + read(); + return '\r'; + + case 't': + read(); + return '\t'; + + case 'v': + read(); + return '\v'; + + case '0': + read(); + if (unicode::isDigit(peek(_cur, _end))) { throw InvalidChar(_current_char, exceptionDetailInfo()); } - buffer += static_cast(read()); + return '\0'; - return std::stoi(buffer, nullptr, 16); - } + case 'x': + read(); + return hexEscape(); - template - MEOJSON_INLINE typename parser5::u8char parser5::unicodeEscape() - { - std::string buffer; - int count = 4; - while (count-- > 0) { - auto c = peek(_cur, _end); - if (!unicode::isHexDigit(c)) { - throw InvalidChar(_current_char, exceptionDetailInfo()); - } - buffer += StringFromCharCode(read()); - } + case 'u': + read(); + return unicodeEscape(); - return std::stoull(buffer, nullptr, 16); - } + case '\n': + case 0x2028: + case 0x2029: + read(); + return 0; - /* utf-8 reader */ - template - MEOJSON_INLINE typename parser5::u8char parser5::peek(StringIterT& begin, - const StringIterT& end, - size_t* plen) - { - if (begin == end) { - if (plen) - *plen = 0; - return 0; - } - uint8_t head = (*begin); - uint64_t ch = head; - size_t len = 1; - while (begin != end && (head & 0b11000000) > 0b10000000) { - head <<= 1; - ++len; - ch <<= 8; - ch += (uint8_t)(*(begin + len - 1)); - } - if (plen) { - *plen = len; + case '\r': + read(); + if (peek(_cur, _end) == '\n') { + read(); } - return ch; - } - template - MEOJSON_INLINE typename parser5::u8char parser5::peek(const std::string& str) - { - auto begin = str.begin(); - return peek(begin, str.cend()); - } - MEOJSON_INLINE constexpr size_t operator"" _sz(unsigned long long size) { return size; } - template - MEOJSON_INLINE typename parser5::u8char parser5::read() - { - size_t len = 0; - _current_char = peek(_cur, _end, &len); - if (_current_char == '\n') { - _line++; - _col = 0; - _print_len = 0; - _line_begin_cur = _cur + 1; - } - else if (_current_char > 0) { - _col++; - } + return std::nullopt; - if (len > 0) { - _print_len += (std::min)(len, 2_sz); - _cur += len; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + throw InvalidChar(_current_char, exceptionDetailInfo()); + default: + if (c == 0) { + throw InvalidChar(_current_char, exceptionDetailInfo()); } - return _current_char; } - template - MEOJSON_INLINE std::string parser5::StringFromCharCode(typename parser5::u8char code) - { - if (code == 0) - return ""; - std::string str; - for (auto i = 0; i < 8; ++i) { - auto ch = (0xff & code); - if (ch) - str.insert(0, 1, static_cast(ch)); - code >>= 8; - } - return str; - } + return read(); +} - /* lex, parse, token */ +template +inline typename parser5::u8char parser5::hexEscape() +{ + std::string buffer = ""; + auto c = peek(_cur, _end); - template - MEOJSON_INLINE typename parser5::Token parser5::newToken(TokenType type, value value) - { - Token token; - token.type = type; - token._value = value; - token.line = _line; - token.col = _col; - return token; + if (!unicode::isHexDigit(c)) { + throw InvalidChar(_current_char, exceptionDetailInfo()); } - template - MEOJSON_INLINE typename parser5::Token parser5::lex() - { - _lex_state = LexState::default_; - _buffer = ""; - _double_quote = false; - _sign = 1; + buffer += static_cast(read()); - std::optional token; + c = peek(_cur, _end); + if (!unicode::isHexDigit(c)) { + throw InvalidChar(_current_char, exceptionDetailInfo()); + } - for (;;) { - _current_char = peek(_cur, _end); + buffer += static_cast(read()); - token = lexStates(_lex_state); - if (token.has_value()) { - return token.value(); - } + return std::stoi(buffer, nullptr, 16); +} + +template +inline typename parser5::u8char parser5::unicodeEscape() +{ + std::string buffer; + int count = 4; + while (count-- > 0) { + auto c = peek(_cur, _end); + if (!unicode::isHexDigit(c)) { + throw InvalidChar(_current_char, exceptionDetailInfo()); } + buffer += StringFromCharCode(read()); } - template - MEOJSON_INLINE std::optional::Token> parser5::lex_default() - { - switch (_current_char) { - case '\t': - case '\v': - case '\f': - case ' ': - case '\n': - case '\r': - case 0x00A0: - case 0xFEFF: - case 0x2028: - case 0x2029: - read(); - return std::nullopt; - case '/': - read(); - _lex_state = LexState::comment; - return std::nullopt; - case 0: - read(); - return newToken(TokenType::eof, value()); - } + return std::stoull(buffer, nullptr, 16); +} - // if (_current_char.size() == 0) { - // read(); - // return newToken("eof"); - // } +/* utf-8 reader */ +template +inline typename parser5::u8char parser5::peek(StringIterT& begin, const StringIterT& end, + size_t* plen) +{ + if (begin == end) { + if (plen) *plen = 0; + return 0; + } + uint8_t head = (*begin); + uint64_t ch = head; + size_t len = 1; + while (begin != end && (head & 0b11000000) > 0b10000000) { + head <<= 1; + ++len; + ch <<= 8; + ch += (uint8_t)(*(begin + len - 1)); + } + if (plen) { + *plen = len; + } + return ch; +} - if (unicode::isSpaceSeparator(_current_char)) { - read(); - return std::nullopt; - } +template +inline typename parser5::u8char parser5::peek(const std::string& str) +{ + auto begin = str.begin(); + return peek(begin, str.cend()); +} +inline constexpr size_t operator"" _sz(unsigned long long size) +{ + return size; +} +template +inline typename parser5::u8char parser5::read() +{ + size_t len = 0; + _current_char = peek(_cur, _end, &len); + if (_current_char == '\n') { + _line++; + _col = 0; + _print_len = 0; + _line_begin_cur = _cur + 1; + } + else if (_current_char > 0) { + _col++; + } - // throw InvalidLexState(); - return lexStates((LexState)_parse_state); + if (len > 0) { + _print_len += (std::min)(len, 2_sz); + _cur += len; } + return _current_char; +} - template - MEOJSON_INLINE std::optional::Token> parser5::lex_comment() - { - switch (_current_char) { - case '*': - read(); - _lex_state = LexState::multiLineComment; - return std::nullopt; +template +inline std::string parser5::StringFromCharCode(typename parser5::u8char code) +{ + if (code == 0) return ""; + std::string str; + for (auto i = 0; i < 8; ++i) { + auto ch = (0xff & code); + if (ch) str.insert(0, 1, static_cast(ch)); + code >>= 8; + } + return str; +} - case '/': - read(); - _lex_state = LexState::singleLineComment; - return std::nullopt; - } +/* lex, parse, token */ - throw InvalidChar(_current_char, exceptionDetailInfo()); - } +template +inline typename parser5::Token parser5::newToken(TokenType type, value value) +{ + Token token; + token.type = type; + token._value = value; + token.line = _line; + token.col = _col; + return token; +} + +template +inline typename parser5::Token parser5::lex() +{ + _lex_state = LexState::default_; + _buffer = ""; + _double_quote = false; + _sign = 1; - template - MEOJSON_INLINE std::optional::Token> parser5::lex_multiLineComment() - { - if (_current_char == '*') { - read(); - _lex_state = LexState::multiLineCommentAsterisk; - return std::nullopt; - } + std::optional token; - if (_current_char == 0) { - throw InvalidChar(_current_char, exceptionDetailInfo()); + for (;;) { + _current_char = peek(_cur, _end); + + token = lexStates(_lex_state); + if (token.has_value()) { + return token.value(); } + } +} +template +inline std::optional::Token> parser5::lex_default() +{ + switch (_current_char) { + case '\t': + case '\v': + case '\f': + case ' ': + case '\n': + case '\r': + case 0x00A0: + case 0xFEFF: + case 0x2028: + case 0x2029: + read(); + return std::nullopt; + case '/': read(); + _lex_state = LexState::comment; return std::nullopt; + case 0: + read(); + return newToken(TokenType::eof, value()); } - template - MEOJSON_INLINE std::optional::Token> parser5::lex_multiLineCommentAsterisk() - { - switch (_current_char) { - case '*': - read(); - return std::nullopt; + // if (_current_char.size() == 0) { + // read(); + // return newToken("eof"); + // } - case '/': - read(); - _lex_state = LexState::default_; - return std::nullopt; //$ + if (unicode::isSpaceSeparator(_current_char)) { + read(); + return std::nullopt; + } - default: - if (_current_char == 0) { - throw InvalidChar(_current_char, exceptionDetailInfo()); - } - } + // throw InvalidLexState(); + return lexStates((LexState)_parse_state); +} +template +inline std::optional::Token> parser5::lex_comment() +{ + switch (_current_char) { + case '*': read(); _lex_state = LexState::multiLineComment; return std::nullopt; + + case '/': + read(); + _lex_state = LexState::singleLineComment; + return std::nullopt; } - template - MEOJSON_INLINE std::optional::Token> parser5::lex_singleLineComment() - { - switch (_current_char) { - case '\n': - case '\r': - case 0x2028: - case 0x2029: - read(); - _lex_state = LexState::default_; - return std::nullopt; - case 0: - read(); - return newToken(TokenType::eof, value()); - } + throw InvalidChar(_current_char, exceptionDetailInfo()); +} + +template +inline std::optional::Token> parser5::lex_multiLineComment() +{ + if (_current_char == '*') { read(); + _lex_state = LexState::multiLineCommentAsterisk; return std::nullopt; } - template - MEOJSON_INLINE std::optional::Token> parser5::lex_value() - { - switch (_current_char) { - case '{': - case '[': - return newToken(TokenType::punctuator, value(StringFromCharCode(read()))); - case 'n': - read(); - literal("ull"); - return newToken(TokenType::null, value()); - case 't': - read(); - literal("rue"); - return newToken(TokenType::boolean, value(true)); - case 'f': - read(); - literal("alse"); - return newToken(TokenType::boolean, value(false)); - case '-': - case '+': - if (read() == '-') { - _sign = -1; - } - _lex_state = LexState::sign; - return std::nullopt; - case '.': - _buffer = StringFromCharCode(read()); - _lex_state = LexState::decimalPointLeading; - return std::nullopt; - - case '0': - _buffer = StringFromCharCode(read()); - _lex_state = LexState::zero; - return std::nullopt; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - _buffer = StringFromCharCode(read()); - _lex_state = LexState::decimalInteger; - return std::nullopt; - case 'I': - read(); - literal("nfinity"); - return newToken(TokenType::numeric, INFINITY); - case 'N': - read(); - literal("aN"); - return newToken(TokenType::numeric, NAN); - case '\"': - case '\'': - _double_quote = (read() == '\"'); - _buffer = ""; - _lex_state = LexState::string; - return std::nullopt; - } + if (_current_char == 0) { throw InvalidChar(_current_char, exceptionDetailInfo()); } - template - MEOJSON_INLINE std::optional::Token> parser5::lex_identifierNameStartEscape() - { - if (_current_char != 'u') { + read(); + return std::nullopt; +} + +template +inline std::optional::Token> parser5::lex_multiLineCommentAsterisk() +{ + switch (_current_char) { + case '*': + read(); + return std::nullopt; + + case '/': + read(); + _lex_state = LexState::default_; + return std::nullopt; //$ + + default: + if (_current_char == 0) { throw InvalidChar(_current_char, exceptionDetailInfo()); } + } + + read(); + _lex_state = LexState::multiLineComment; + return std::nullopt; +} + +template +inline std::optional::Token> parser5::lex_singleLineComment() +{ + switch (_current_char) { + case '\n': + case '\r': + case 0x2028: + case 0x2029: read(); - auto u = unicodeEscape(); - switch (u) { - case '$': - case '_': - break; - default: - if (!unicode::isIdStartChar(u)) { - throw InvalidIdentifier("", exceptionDetailInfo()); - } - break; - } - _buffer += StringFromCharCode(u); - _lex_state = LexState::identifierName; + _lex_state = LexState::default_; return std::nullopt; + case 0: + read(); + return newToken(TokenType::eof, value()); } + read(); + return std::nullopt; +} - template - MEOJSON_INLINE std::optional::Token> parser5::lex_identifierName() - { - switch (_current_char) { - case '$': - case '_': - case 0x200C: - case 0x200D: - _buffer += StringFromCharCode(read()); - return std::nullopt; - case '\\': - read(); - _lex_state = LexState::identifierNameEscape; - return std::nullopt; - } +template +inline std::optional::Token> parser5::lex_value() +{ + switch (_current_char) { + case '{': + case '[': + return newToken(TokenType::punctuator, value(StringFromCharCode(read()))); + case 'n': + read(); + literal("ull"); + return newToken(TokenType::null, value()); + case 't': + read(); + literal("rue"); + return newToken(TokenType::boolean, value(true)); + case 'f': + read(); + literal("alse"); + return newToken(TokenType::boolean, value(false)); + case '-': + case '+': + if (read() == '-') { + _sign = -1; + } + _lex_state = LexState::sign; + return std::nullopt; + case '.': + _buffer = StringFromCharCode(read()); + _lex_state = LexState::decimalPointLeading; + return std::nullopt; - if (unicode::isIdContinueChar(_current_char)) { - _buffer += StringFromCharCode(read()); - return std::nullopt; - } + case '0': + _buffer = StringFromCharCode(read()); + _lex_state = LexState::zero; + return std::nullopt; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + _buffer = StringFromCharCode(read()); + _lex_state = LexState::decimalInteger; + return std::nullopt; + case 'I': + read(); + literal("nfinity"); + return newToken(TokenType::numeric, INFINITY); + case 'N': + read(); + literal("aN"); + return newToken(TokenType::numeric, NAN); + case '\"': + case '\'': + _double_quote = (read() == '\"'); + _buffer = ""; + _lex_state = LexState::string; + return std::nullopt; + } + throw InvalidChar(_current_char, exceptionDetailInfo()); +} - return newToken(TokenType::identifier, _buffer); +template +inline std::optional::Token> parser5::lex_identifierNameStartEscape() +{ + if (_current_char != 'u') { + throw InvalidChar(_current_char, exceptionDetailInfo()); } + read(); + auto u = unicodeEscape(); + switch (u) { + case '$': + case '_': + break; + default: + if (!unicode::isIdStartChar(u)) { + throw InvalidIdentifier("", exceptionDetailInfo()); + } + break; + } + _buffer += StringFromCharCode(u); + _lex_state = LexState::identifierName; + return std::nullopt; +} - template - MEOJSON_INLINE std::optional::Token> parser5::lex_identifierNameEscape() - { - if (_current_char != 'u') { - throw InvalidChar(_current_char, exceptionDetailInfo()); - } +template +inline std::optional::Token> parser5::lex_identifierName() +{ + switch (_current_char) { + case '$': + case '_': + case 0x200C: + case 0x200D: + _buffer += StringFromCharCode(read()); + return std::nullopt; + case '\\': read(); - auto u = unicodeEscape(); - switch (u) { - case '$': - case '_': - case 0x200C: - case 0x200D: - break; - default: - if (!unicode::isIdStartChar(u)) { - throw InvalidIdentifier("", exceptionDetailInfo()); - } - break; - } - _buffer += StringFromCharCode(u); - _lex_state = LexState::identifierName; + _lex_state = LexState::identifierNameEscape; return std::nullopt; } - template - MEOJSON_INLINE std::optional::Token> parser5::lex_sign() - { - switch (_current_char) { - case '.': - _buffer = StringFromCharCode(read()); - _lex_state = LexState::decimalPointLeading; - return std::nullopt; - - case '0': - _buffer = StringFromCharCode(read()); - _lex_state = LexState::zero; - return std::nullopt; - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - _buffer = StringFromCharCode(read()); - _lex_state = LexState::decimalInteger; - return std::nullopt; - - case 'I': - read(); - literal("nfinity"); - return newToken(TokenType::numeric, _sign * INFINITY); + if (unicode::isIdContinueChar(_current_char)) { + _buffer += StringFromCharCode(read()); + return std::nullopt; + } - case 'N': - read(); - literal("aN"); - return newToken(TokenType::numeric, NAN); - } + return newToken(TokenType::identifier, _buffer); +} + +template +inline std::optional::Token> parser5::lex_identifierNameEscape() +{ + if (_current_char != 'u') { throw InvalidChar(_current_char, exceptionDetailInfo()); } + read(); + auto u = unicodeEscape(); + switch (u) { + case '$': + case '_': + case 0x200C: + case 0x200D: + break; + default: + if (!unicode::isIdStartChar(u)) { + throw InvalidIdentifier("", exceptionDetailInfo()); + } + break; + } + _buffer += StringFromCharCode(u); + _lex_state = LexState::identifierName; + return std::nullopt; +} - template - MEOJSON_INLINE std::optional::Token> parser5::lex_zero() - { - switch (_current_char) { - case '.': - _buffer += StringFromCharCode(read()); - _lex_state = LexState::decimalPoint; - return std::nullopt; //$ - - case 'e': - case 'E': - _buffer += StringFromCharCode(read()); - _lex_state = LexState::decimalExponent; - return std::nullopt; //$ - - case 'x': - case 'X': - _buffer += StringFromCharCode(read()); - _lex_state = LexState::hexadecimal; - return std::nullopt; //$ - } - return newToken(TokenType::numeric, _sign * 0); +template +inline std::optional::Token> parser5::lex_sign() +{ + switch (_current_char) { + case '.': + _buffer = StringFromCharCode(read()); + _lex_state = LexState::decimalPointLeading; + return std::nullopt; + + case '0': + _buffer = StringFromCharCode(read()); + _lex_state = LexState::zero; + return std::nullopt; + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + _buffer = StringFromCharCode(read()); + _lex_state = LexState::decimalInteger; + return std::nullopt; + + case 'I': + read(); + literal("nfinity"); + return newToken(TokenType::numeric, _sign * INFINITY); + + case 'N': + read(); + literal("aN"); + return newToken(TokenType::numeric, NAN); } + throw InvalidChar(_current_char, exceptionDetailInfo()); +} - template - MEOJSON_INLINE std::optional::Token> parser5::lex_decimalInteger() - { - switch (_current_char) { - case '.': - _buffer += StringFromCharCode(read()); - _lex_state = LexState::decimalPoint; - return std::nullopt; - case 'e': - case 'E': - _buffer += StringFromCharCode(read()); - _lex_state = LexState::decimalExponent; - return std::nullopt; //$ - } - if (unicode::isDigit(_current_char)) { - _buffer += StringFromCharCode(read()); - return std::nullopt; - } +template +inline std::optional::Token> parser5::lex_zero() +{ + switch (_current_char) { + case '.': + _buffer += StringFromCharCode(read()); + _lex_state = LexState::decimalPoint; + return std::nullopt; //$ + + case 'e': + case 'E': + _buffer += StringFromCharCode(read()); + _lex_state = LexState::decimalExponent; + return std::nullopt; //$ - return newToken(TokenType::numeric, _sign * std::stod(_buffer)); + case 'x': + case 'X': + _buffer += StringFromCharCode(read()); + _lex_state = LexState::hexadecimal; + return std::nullopt; //$ } + return newToken(TokenType::numeric, _sign * 0); +} - template - MEOJSON_INLINE std::optional::Token> parser5::lex_decimalPointLeading() - { - if (unicode::isDigit(_current_char)) { - _buffer += StringFromCharCode(read()); - _lex_state = LexState::decimalFraction; - return std::nullopt; - } - throw InvalidChar(_current_char, exceptionDetailInfo()); +template +inline std::optional::Token> parser5::lex_decimalInteger() +{ + switch (_current_char) { + case '.': + _buffer += StringFromCharCode(read()); + _lex_state = LexState::decimalPoint; + return std::nullopt; + case 'e': + case 'E': + _buffer += StringFromCharCode(read()); + _lex_state = LexState::decimalExponent; + return std::nullopt; //$ + } + if (unicode::isDigit(_current_char)) { + _buffer += StringFromCharCode(read()); + return std::nullopt; } - template - MEOJSON_INLINE std::optional::Token> parser5::lex_decimalPoint() - { - switch (_current_char) { - case 'e': - case 'E': - _buffer += StringFromCharCode(read()); - _lex_state = LexState::decimalExponent; - return std::nullopt; //$ - } - if (unicode::isDigit(_current_char)) { - _buffer += StringFromCharCode(read()); - _lex_state = LexState::decimalFraction; - return std::nullopt; - } + return newToken(TokenType::numeric, _sign * std::stod(_buffer)); +} - return newToken(TokenType::numeric, _sign * std::stod(_buffer)); +template +inline std::optional::Token> parser5::lex_decimalPointLeading() +{ + if (unicode::isDigit(_current_char)) { + _buffer += StringFromCharCode(read()); + _lex_state = LexState::decimalFraction; + return std::nullopt; } + throw InvalidChar(_current_char, exceptionDetailInfo()); +} - template - MEOJSON_INLINE std::optional::Token> parser5::lex_decimalFraction() - { - switch (_current_char) { - case 'e': - case 'E': - _buffer += StringFromCharCode(read()); - _lex_state = LexState::decimalExponent; - return std::nullopt; //$ - } - if (unicode::isDigit(_current_char)) { - _buffer += StringFromCharCode(read()); - return std::nullopt; - } - - return newToken(TokenType::numeric, _sign * std::stod(_buffer)); +template +inline std::optional::Token> parser5::lex_decimalPoint() +{ + switch (_current_char) { + case 'e': + case 'E': + _buffer += StringFromCharCode(read()); + _lex_state = LexState::decimalExponent; + return std::nullopt; //$ + } + if (unicode::isDigit(_current_char)) { + _buffer += StringFromCharCode(read()); + _lex_state = LexState::decimalFraction; + return std::nullopt; } - template - MEOJSON_INLINE std::optional::Token> parser5::lex_decimalExponent() - { - switch (_current_char) { - case '+': - case '-': - _buffer += StringFromCharCode(read()); - _lex_state = LexState::decimalExponentSign; - return std::nullopt; //$ - } + return newToken(TokenType::numeric, _sign * std::stod(_buffer)); +} - if (unicode::isDigit(_current_char)) { - _buffer += StringFromCharCode(read()); - _lex_state = LexState::decimalExponentInteger; - return std::nullopt; - } - throw InvalidChar(_current_char, exceptionDetailInfo()); +template +inline std::optional::Token> parser5::lex_decimalFraction() +{ + switch (_current_char) { + case 'e': + case 'E': + _buffer += StringFromCharCode(read()); + _lex_state = LexState::decimalExponent; + return std::nullopt; //$ } - - template - MEOJSON_INLINE std::optional::Token> parser5::lex_decimalExponentSign() - { - if (unicode::isDigit(_current_char)) { - _buffer += StringFromCharCode(read()); - _lex_state = LexState::decimalExponentInteger; - return std::nullopt; - } - throw InvalidChar(_current_char, exceptionDetailInfo()); + if (unicode::isDigit(_current_char)) { + _buffer += StringFromCharCode(read()); + return std::nullopt; } - template - MEOJSON_INLINE std::optional::Token> parser5::lex_decimalExponentInteger() - { - if (unicode::isDigit(_current_char)) { - _buffer += StringFromCharCode(read()); - return std::nullopt; - } - return newToken(TokenType::numeric, _sign * std::stod(_buffer)); + return newToken(TokenType::numeric, _sign * std::stod(_buffer)); +} + +template +inline std::optional::Token> parser5::lex_decimalExponent() +{ + switch (_current_char) { + case '+': + case '-': + _buffer += StringFromCharCode(read()); + _lex_state = LexState::decimalExponentSign; + return std::nullopt; //$ } - template - MEOJSON_INLINE std::optional::Token> parser5::lex_hexadecimal() - { - if (unicode::isHexDigit(_current_char)) { - _buffer += StringFromCharCode(read()); - _lex_state = LexState::hexadecimalInteger; - return std::nullopt; - } - throw InvalidChar(_current_char, exceptionDetailInfo()); + if (unicode::isDigit(_current_char)) { + _buffer += StringFromCharCode(read()); + _lex_state = LexState::decimalExponentInteger; + return std::nullopt; } + throw InvalidChar(_current_char, exceptionDetailInfo()); +} - template - MEOJSON_INLINE std::optional::Token> parser5::lex_hexdecimalInteger() - { - if (unicode::isHexDigit(_current_char)) { - _buffer += StringFromCharCode(read()); - return std::nullopt; - } - return newToken(TokenType::numeric, _sign * std::stod(_buffer)); +template +inline std::optional::Token> parser5::lex_decimalExponentSign() +{ + if (unicode::isDigit(_current_char)) { + _buffer += StringFromCharCode(read()); + _lex_state = LexState::decimalExponentInteger; + return std::nullopt; } + throw InvalidChar(_current_char, exceptionDetailInfo()); +} - template - MEOJSON_INLINE std::optional::Token> parser5::lex_string() - { - switch (_current_char) { - case '\\': - read(); - _buffer += StringFromCharCode(escape().value_or(0)); - return std::nullopt; - case '\"': - if (_double_quote) { - read(); - return newToken(TokenType::string, _buffer); - } - _buffer += StringFromCharCode(read()); - return std::nullopt; - case '\'': - if (!_double_quote) { - read(); - return newToken(TokenType::string, _buffer); - } - _buffer += StringFromCharCode(read()); - return std::nullopt; - case '\n': - case '\r': - throw InvalidChar(_current_char, exceptionDetailInfo()); - case 0x2028: - case 0x2029: - // throw separatorChar(_current_char); - break; - default: - if (_current_char == 0) { - throw InvalidChar(_current_char, exceptionDetailInfo()); - } - } +template +inline std::optional::Token> parser5::lex_decimalExponentInteger() +{ + if (unicode::isDigit(_current_char)) { _buffer += StringFromCharCode(read()); return std::nullopt; } + return newToken(TokenType::numeric, _sign * std::stod(_buffer)); +} - template - MEOJSON_INLINE std::optional::Token> parser5::lex_start() - { - switch (_current_char) { - case '{': - case '[': - return newToken(TokenType::punctuator, StringFromCharCode(read())); - } +template +inline std::optional::Token> parser5::lex_hexadecimal() +{ + if (unicode::isHexDigit(_current_char)) { + _buffer += StringFromCharCode(read()); + _lex_state = LexState::hexadecimalInteger; + return std::nullopt; + } + throw InvalidChar(_current_char, exceptionDetailInfo()); +} - _lex_state = LexState::value; +template +inline std::optional::Token> parser5::lex_hexdecimalInteger() +{ + if (unicode::isHexDigit(_current_char)) { + _buffer += StringFromCharCode(read()); return std::nullopt; } + return newToken(TokenType::numeric, _sign * std::stod(_buffer)); +} - template - MEOJSON_INLINE std::optional::Token> parser5::lex_beforePropertyName() - { - switch (_current_char) { - case '$': - case '_': - _buffer = StringFromCharCode(read()); - _lex_state = LexState::identifierName; - return std::nullopt; - case '\\': +template +inline std::optional::Token> parser5::lex_string() +{ + switch (_current_char) { + case '\\': + read(); + _buffer += StringFromCharCode(escape().value_or(0)); + return std::nullopt; + case '\"': + if (_double_quote) { read(); - _lex_state = LexState::identifierNameStartEscape; - return std::nullopt; - case '}': - return newToken(TokenType::punctuator, StringFromCharCode(read())); - case '\"': - case '\'': - _double_quote = (read() == '\"'); - _lex_state = LexState::string; - return std::nullopt; + return newToken(TokenType::string, _buffer); } - - if (unicode::isIdStartChar(_current_char)) { - _buffer += StringFromCharCode(read()); - _lex_state = LexState::identifierName; - return std::nullopt; + _buffer += StringFromCharCode(read()); + return std::nullopt; + case '\'': + if (!_double_quote) { + read(); + return newToken(TokenType::string, _buffer); } - + _buffer += StringFromCharCode(read()); + return std::nullopt; + case '\n': + case '\r': throw InvalidChar(_current_char, exceptionDetailInfo()); - } - - template - MEOJSON_INLINE std::optional::Token> parser5::lex_afterPropertyName() - { - if (_current_char == ':') { - return newToken(TokenType::punctuator, StringFromCharCode(read())); + case 0x2028: + case 0x2029: + // throw separatorChar(_current_char); + break; + default: + if (_current_char == 0) { + throw InvalidChar(_current_char, exceptionDetailInfo()); } - throw InvalidChar(_current_char, exceptionDetailInfo()); } + _buffer += StringFromCharCode(read()); + return std::nullopt; +} - template - MEOJSON_INLINE std::optional::Token> parser5::lex_beforePropertyValue() - { - _lex_state = LexState::value; - return std::nullopt; +template +inline std::optional::Token> parser5::lex_start() +{ + switch (_current_char) { + case '{': + case '[': + return newToken(TokenType::punctuator, StringFromCharCode(read())); } - template - MEOJSON_INLINE std::optional::Token> parser5::lex_afterPropertyValue() - { - switch (_current_char) { - case ',': - case '}': - return newToken(TokenType::punctuator, StringFromCharCode(read())); - } - throw InvalidChar(_current_char, exceptionDetailInfo()); + _lex_state = LexState::value; + return std::nullopt; +} + +template +inline std::optional::Token> parser5::lex_beforePropertyName() +{ + switch (_current_char) { + case '$': + case '_': + _buffer = StringFromCharCode(read()); + _lex_state = LexState::identifierName; + return std::nullopt; + case '\\': + read(); + _lex_state = LexState::identifierNameStartEscape; + return std::nullopt; + case '}': + return newToken(TokenType::punctuator, StringFromCharCode(read())); + case '\"': + case '\'': + _double_quote = (read() == '\"'); + _lex_state = LexState::string; + return std::nullopt; } - template - MEOJSON_INLINE std::optional::Token> parser5::lex_beforeArrayValue() - { - if (_current_char == ']') { - return newToken(TokenType::punctuator, StringFromCharCode(read())); - } - _lex_state = LexState::value; + if (unicode::isIdStartChar(_current_char)) { + _buffer += StringFromCharCode(read()); + _lex_state = LexState::identifierName; return std::nullopt; } - template - MEOJSON_INLINE std::optional::Token> parser5::lex_afterArrayValue() - { - switch (_current_char) { - case ',': - case ']': - return newToken(TokenType::punctuator, StringFromCharCode(read())); - } + throw InvalidChar(_current_char, exceptionDetailInfo()); +} - throw InvalidChar(_current_char, exceptionDetailInfo()); +template +inline std::optional::Token> parser5::lex_afterPropertyName() +{ + if (_current_char == ':') { + return newToken(TokenType::punctuator, StringFromCharCode(read())); } + throw InvalidChar(_current_char, exceptionDetailInfo()); +} - template - MEOJSON_INLINE std::optional::Token> parser5::lex_end() - { - throw InvalidChar(_current_char, exceptionDetailInfo()); +template +inline std::optional::Token> parser5::lex_beforePropertyValue() +{ + _lex_state = LexState::value; + return std::nullopt; +} + +template +inline std::optional::Token> parser5::lex_afterPropertyValue() +{ + switch (_current_char) { + case ',': + case '}': + return newToken(TokenType::punctuator, StringFromCharCode(read())); } + throw InvalidChar(_current_char, exceptionDetailInfo()); +} - template - MEOJSON_INLINE std::optional::Token> parser5::lexStates(LexState state) - { - switch (state) { - case LexState::default_: - return lex_default(); - case LexState::comment: - return lex_comment(); - case LexState::multiLineComment: - return lex_multiLineComment(); - case LexState::multiLineCommentAsterisk: - return lex_multiLineCommentAsterisk(); - case LexState::singleLineComment: - return lex_singleLineComment(); - case LexState::value: - return lex_value(); - case LexState::identifierNameStartEscape: - return lex_identifierNameStartEscape(); - case LexState::identifierName: - return lex_identifierName(); - case LexState::identifierNameEscape: - return lex_identifierNameEscape(); - case LexState::sign: - return lex_sign(); - case LexState::zero: - return lex_zero(); - case LexState::decimalInteger: - return lex_decimalInteger(); - case LexState::decimalPointLeading: - return lex_decimalPointLeading(); - case LexState::decimalPoint: - return lex_decimalPoint(); - case LexState::decimalFraction: - return lex_decimalFraction(); - case LexState::decimalExponent: - return lex_decimalExponent(); - case LexState::decimalExponentSign: - return lex_decimalExponentSign(); - case LexState::decimalExponentInteger: - return lex_decimalExponentInteger(); - case LexState::hexadecimal: - return lex_hexadecimal(); - case LexState::hexadecimalInteger: - return lex_hexdecimalInteger(); - case LexState::string: - return lex_string(); - case LexState::start: - return lex_start(); - case LexState::beforePropertyName: - return lex_beforePropertyName(); - case LexState::afterPropertyName: - return lex_afterPropertyName(); - case LexState::beforePropertyValue: - return lex_beforePropertyValue(); - case LexState::afterPropertyValue: - return lex_afterPropertyValue(); - case LexState::beforeArrayValue: - return lex_beforeArrayValue(); - case LexState::afterArrayValue: - return lex_afterArrayValue(); - case LexState::end: - return lex_end(); - } +template +inline std::optional::Token> parser5::lex_beforeArrayValue() +{ + if (_current_char == ']') { + return newToken(TokenType::punctuator, StringFromCharCode(read())); + } + _lex_state = LexState::value; + return std::nullopt; +} - // throw - return std::nullopt; +template +inline std::optional::Token> parser5::lex_afterArrayValue() +{ + switch (_current_char) { + case ',': + case ']': + return newToken(TokenType::punctuator, StringFromCharCode(read())); } - template - MEOJSON_INLINE void parser5::parse_start() - { - if (_token->type == TokenType::eof) { - throw InvalidEOF("", exceptionDetailInfo()); - } + throw InvalidChar(_current_char, exceptionDetailInfo()); +} + +template +inline std::optional::Token> parser5::lex_end() +{ + throw InvalidChar(_current_char, exceptionDetailInfo()); +} - push(); +template +inline std::optional::Token> parser5::lexStates(LexState state) +{ + switch (state) { + case LexState::default_: + return lex_default(); + case LexState::comment: + return lex_comment(); + case LexState::multiLineComment: + return lex_multiLineComment(); + case LexState::multiLineCommentAsterisk: + return lex_multiLineCommentAsterisk(); + case LexState::singleLineComment: + return lex_singleLineComment(); + case LexState::value: + return lex_value(); + case LexState::identifierNameStartEscape: + return lex_identifierNameStartEscape(); + case LexState::identifierName: + return lex_identifierName(); + case LexState::identifierNameEscape: + return lex_identifierNameEscape(); + case LexState::sign: + return lex_sign(); + case LexState::zero: + return lex_zero(); + case LexState::decimalInteger: + return lex_decimalInteger(); + case LexState::decimalPointLeading: + return lex_decimalPointLeading(); + case LexState::decimalPoint: + return lex_decimalPoint(); + case LexState::decimalFraction: + return lex_decimalFraction(); + case LexState::decimalExponent: + return lex_decimalExponent(); + case LexState::decimalExponentSign: + return lex_decimalExponentSign(); + case LexState::decimalExponentInteger: + return lex_decimalExponentInteger(); + case LexState::hexadecimal: + return lex_hexadecimal(); + case LexState::hexadecimalInteger: + return lex_hexdecimalInteger(); + case LexState::string: + return lex_string(); + case LexState::start: + return lex_start(); + case LexState::beforePropertyName: + return lex_beforePropertyName(); + case LexState::afterPropertyName: + return lex_afterPropertyName(); + case LexState::beforePropertyValue: + return lex_beforePropertyValue(); + case LexState::afterPropertyValue: + return lex_afterPropertyValue(); + case LexState::beforeArrayValue: + return lex_beforeArrayValue(); + case LexState::afterArrayValue: + return lex_afterArrayValue(); + case LexState::end: + return lex_end(); } - template - MEOJSON_INLINE void parser5::parse_beforePropertyName() - { - switch (_token->type) { - case TokenType::identifier: - case TokenType::string: - _key = _token->_value.as_string(); - _parse_state = ParseState::afterPropertyName; - break; - case TokenType::punctuator: - pop(); - break; - case TokenType::eof: - throw InvalidEOF("", exceptionDetailInfo()); - break; - default: + // throw + return std::nullopt; +} - break; - } +template +inline void parser5::parse_start() +{ + if (_token->type == TokenType::eof) { + throw InvalidEOF("", exceptionDetailInfo()); } - template - MEOJSON_INLINE void parser5::parse_afterPropertyName() - { - if (_token->type == TokenType::eof) { - throw InvalidEOF("", exceptionDetailInfo()); - } + push(); +} - _parse_state = ParseState::beforePropertyValue; +template +inline void parser5::parse_beforePropertyName() +{ + switch (_token->type) { + case TokenType::identifier: + case TokenType::string: + _key = _token->_value.as_string(); + _parse_state = ParseState::afterPropertyName; + break; + case TokenType::punctuator: + pop(); + break; + case TokenType::eof: + throw InvalidEOF("", exceptionDetailInfo()); + break; + default: + + break; } +} - template - MEOJSON_INLINE void parser5::parse_beforePropertyValue() - { - if (_token->type == TokenType::eof) { - throw InvalidEOF("", exceptionDetailInfo()); - } - push(); +template +inline void parser5::parse_afterPropertyName() +{ + if (_token->type == TokenType::eof) { + throw InvalidEOF("", exceptionDetailInfo()); } - template - MEOJSON_INLINE void parser5::parse_beforeArrayValue() - { - if (_token->type == TokenType::eof) { - throw InvalidEOF("", exceptionDetailInfo()); - } + _parse_state = ParseState::beforePropertyValue; +} - if (_token->type == TokenType::punctuator && - _token->_value.as_string()[0] == ']') { - pop(); - return; - } +template +inline void parser5::parse_beforePropertyValue() +{ + if (_token->type == TokenType::eof) { + throw InvalidEOF("", exceptionDetailInfo()); + } + push(); +} - push(); +template +inline void parser5::parse_beforeArrayValue() +{ + if (_token->type == TokenType::eof) { + throw InvalidEOF("", exceptionDetailInfo()); } - template - MEOJSON_INLINE void parser5::parse_afterPropertyValue() - { - if (_token->type == TokenType::eof) { - throw InvalidEOF("", exceptionDetailInfo()); - } + if (_token->type == TokenType::punctuator && _token->_value.as_string()[0] == ']') { + pop(); + return; + } - switch (_token->_value.as_string()[0]) { - case ',': - _parse_state = ParseState::beforePropertyName; - break; - case '}': - pop(); - break; - } + push(); +} + +template +inline void parser5::parse_afterPropertyValue() +{ + if (_token->type == TokenType::eof) { + throw InvalidEOF("", exceptionDetailInfo()); } - template - MEOJSON_INLINE void parser5::parse_afterArrayValue() - { - if (_token->type == TokenType::eof) { - throw InvalidEOF("", exceptionDetailInfo()); - } - switch (_token->_value.as_string()[0]) { - case ',': - _parse_state = ParseState::beforeArrayValue; - break; - case ']': - pop(); - break; - } + switch (_token->_value.as_string()[0]) { + case ',': + _parse_state = ParseState::beforePropertyName; + break; + case '}': + pop(); + break; } +} - template - MEOJSON_INLINE void parser5::parse_end() {} +template +inline void parser5::parse_afterArrayValue() +{ + if (_token->type == TokenType::eof) { + throw InvalidEOF("", exceptionDetailInfo()); + } + switch (_token->_value.as_string()[0]) { + case ',': + _parse_state = ParseState::beforeArrayValue; + break; + case ']': + pop(); + break; + } +} - template - MEOJSON_INLINE void parser5::parseStates(ParseState state) - { - switch (state) { - case ParseState::start: - parse_start(); - break; - case ParseState::beforePropertyName: - parse_beforePropertyName(); - break; - case ParseState::afterPropertyName: - parse_afterPropertyName(); - break; - case ParseState::beforePropertyValue: - parse_beforePropertyValue(); - break; - case ParseState::beforeArrayValue: - parse_beforeArrayValue(); - break; - case ParseState::afterPropertyValue: - parse_afterPropertyValue(); +template +inline void parser5::parse_end() +{} + +template +inline void parser5::parseStates(ParseState state) +{ + switch (state) { + case ParseState::start: + parse_start(); + break; + case ParseState::beforePropertyName: + parse_beforePropertyName(); + break; + case ParseState::afterPropertyName: + parse_afterPropertyName(); + break; + case ParseState::beforePropertyValue: + parse_beforePropertyValue(); + break; + case ParseState::beforeArrayValue: + parse_beforeArrayValue(); + break; + case ParseState::afterPropertyValue: + parse_afterPropertyValue(); + break; + case ParseState::afterArrayValue: + parse_afterArrayValue(); + break; + default: + break; + } +} +/* stack operation */ +template +inline void parser5::push() +{ + value v; + value* pv = nullptr; // only for access + switch (_token->type) { + case TokenType::punctuator: { + switch (_token->_value.as_string()[0]) { + case '{': + v = object(); break; - case ParseState::afterArrayValue: - parse_afterArrayValue(); + case '[': + v = array(); break; default: break; } + } break; + case TokenType::null: + case TokenType::boolean: + case TokenType::numeric: + case TokenType::string: + std::swap(v, _token->_value); + break; + default: + break; } - /* stack operation */ - template - MEOJSON_INLINE void parser5::push() - { - value v; - value* pv = nullptr; // only for access - switch (_token->type) { - case TokenType::punctuator: { - switch (_token->_value.as_string()[0]) { - case '{': - v = object(); - break; - case '[': - v = array(); - break; - default: - break; - } - } break; - case TokenType::null: - case TokenType::boolean: - case TokenType::numeric: - case TokenType::string: - std::swap(v, _token->_value); - break; - default: - break; - } - if (!_root.has_value()) { - _root = std::move(v); - pv = &_root.value(); + if (!_root.has_value()) { + _root = std::move(v); + pv = &_root.value(); + } + else { + auto parent = _stack.top(); + if (parent->is_array()) { + parent->as_array().emplace_back(std::move(v)); + pv = &parent->as_array()[parent->as_array().size() - 1]; } else { - auto parent = _stack.top(); - if (parent->is_array()) { - parent->as_array().emplace_back(std::move(v)); - pv = &parent->as_array()[parent->as_array().size() - 1]; - } - else { - parent->as_object()[_key] = std::move(v); - pv = &parent->as_object()[_key]; - } + parent->as_object()[_key] = std::move(v); + pv = &parent->as_object()[_key]; } + } - if (pv->is_object() || pv->is_array()) { - _stack.emplace(pv); - if (pv->is_array()) { - _parse_state = ParseState::beforeArrayValue; - } - else { - _parse_state = ParseState::beforePropertyName; - } + if (pv->is_object() || pv->is_array()) { + _stack.emplace(pv); + if (pv->is_array()) { + _parse_state = ParseState::beforeArrayValue; } else { - if (_stack.empty()) { - _parse_state = ParseState::end; - } - else if (_stack.top()->is_array()) { - _parse_state = ParseState::afterArrayValue; - } - else { - _parse_state = ParseState::afterPropertyValue; - } + _parse_state = ParseState::beforePropertyName; } } - - template - MEOJSON_INLINE void parser5::pop() - { - _stack.pop(); - + else { if (_stack.empty()) { _parse_state = ParseState::end; } @@ -1718,4 +1691,21 @@ namespace json _parse_state = ParseState::afterPropertyValue; } } +} + +template +inline void parser5::pop() +{ + _stack.pop(); + + if (_stack.empty()) { + _parse_state = ParseState::end; + } + else if (_stack.top()->is_array()) { + _parse_state = ParseState::afterArrayValue; + } + else { + _parse_state = ParseState::afterPropertyValue; + } +} } // namespace json