From 0d78a07f55cd290bcb35190a5dd73ea98546f7ed Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Tue, 22 Jan 2019 10:52:56 -0800 Subject: [PATCH] ircd::json: Minor reorg / cleanup; improve some thrown errors. --- include/ircd/json/json.h | 55 ----------------------------------- include/ircd/json/util.h | 63 +++++++++++++++++++++++++++++++++++++--- ircd/json.cc | 57 +++++++++++++++++++++--------------- 3 files changed, 93 insertions(+), 82 deletions(-) diff --git a/include/ircd/json/json.h b/include/ircd/json/json.h index fa8d62e40..f32477862 100644 --- a/include/ircd/json/json.h +++ b/include/ircd/json/json.h @@ -43,10 +43,7 @@ namespace ircd::json enum type type(const string_view &, std::nothrow_t); string_view reflect(const enum type &); - struct strung; - template struct buffer; template string_view stringify(const mutable_buffer &&mb, T&&... t); - template size_t print(const mutable_buffer &buf, T&&... t); } #include "util.h" @@ -70,32 +67,6 @@ namespace ircd using json::get; } -/// Strong type representing quoted strings in JSON (which may be unquoted -/// automatically when this type is encountered in a tuple etc) -struct ircd::json::string -:string_view -{ - string(const string_view &s) - :string_view{unquote(s)} - {} - - string() = default; -}; - -/// Alternative to `json::strung` which uses a fixed array rather than an -/// allocated string as the target. -template -struct ircd::json::buffer -:string_view -{ - std::array b; - - template - buffer(T&&... t) - :string_view{stringify(b, std::forward(t)...)} - {} -}; - /// Convenience template for const rvalue mutable_buffers or basically /// allowing a bracket initialization of a mutable_buffer in the argument /// to stringify(). The const rvalue reference is on purpose. The stringify() @@ -111,29 +82,3 @@ ircd::json::stringify(const mutable_buffer &&mb, mutable_buffer mbc{mb}; return stringify(mbc, std::forward(t)...); } - -/// Convenience template using the syntax print(mutable_buffer, ...) -/// which stringifies with null termination into buffer. -/// -template -size_t -ircd::json::print(const mutable_buffer &buf, - T&&... t) -{ - if(unlikely(!size(buf))) - return 0; - - mutable_buffer out - { - data(buf), size(buf) - 1 - }; - - const auto sv - { - stringify(out, std::forward(t)...) - }; - - buf[sv.size()] = '\0'; - valid_output(sv, size(sv)); // no size expectation check - return sv.size(); -} diff --git a/include/ircd/json/util.h b/include/ircd/json/util.h index 2da034786..9599ea86e 100644 --- a/include/ircd/json/util.h +++ b/include/ircd/json/util.h @@ -13,9 +13,10 @@ namespace ircd::json { + struct string; + template struct buffer; using name_hash_t = size_t; - constexpr name_hash_t name_hash(const string_view name); - constexpr name_hash_t operator ""_(const char *const name, const size_t len); + using members = std::initializer_list; extern const string_view literal_null; extern const string_view literal_true; @@ -25,10 +26,12 @@ namespace ircd::json extern const string_view empty_array; extern const int64_t undefined_number; + constexpr name_hash_t name_hash(const string_view name); + constexpr name_hash_t operator ""_(const char *const name, const size_t len); + size_t serialized(const string_view &); string_view stringify(mutable_buffer &, const string_view &); - - using members = std::initializer_list; + template size_t print(const mutable_buffer &buf, T&&... t); // Validate JSON - checks if valid JSON (not canonical). bool valid(const string_view &, std::nothrow_t) noexcept; @@ -39,6 +42,58 @@ namespace ircd::json void valid_output(const string_view &, const size_t &expected); } +/// Strong type representing quoted strings in JSON (which may be unquoted +/// automatically when this type is encountered in a tuple etc) +struct ircd::json::string +:string_view +{ + string(const string_view &s) + :string_view{unquote(s)} + {} + + string() = default; +}; + +/// Alternative to `json::strung` which uses a fixed array rather than an +/// allocated string as the target. +template +struct ircd::json::buffer +:string_view +{ + std::array b; + + template + buffer(T&&... t) + :string_view{stringify(b, std::forward(t)...)} + {} +}; + +/// Convenience template using the syntax print(mutable_buffer, ...) +/// which stringifies with null termination into buffer. +/// +template +size_t +ircd::json::print(const mutable_buffer &buf, + T&&... t) +{ + if(unlikely(!size(buf))) + return 0; + + mutable_buffer out + { + data(buf), size(buf) - 1 + }; + + const auto sv + { + stringify(out, std::forward(t)...) + }; + + buf[sv.size()] = '\0'; + valid_output(sv, size(sv)); // no size expectation check + return sv.size(); +} + constexpr ircd::json::name_hash_t ircd::json::operator ""_(const char *const text, const size_t len) { diff --git a/ircd/json.cc b/ircd/json.cc index 7544a0fff..821c5eb6a 100644 --- a/ircd/json.cc +++ b/ircd/json.cc @@ -199,18 +199,21 @@ struct ircd::json::output rule<> quote { lit('"') ,"quote" }; rule<> escape { lit('\\') ,"escape" }; + // literal rule lit_true { karma::string("true") ,"literal true" }; rule lit_false { karma::string("false") ,"literal false" }; rule lit_null { karma::string("null") ,"literal null" }; rule boolean { lit_true | lit_false ,"boolean" }; rule literal { lit_true | lit_false | lit_null ,"literal" }; + // number rule number { double_ ,"number" }; + // string std::map escapes { { '"', "\\\"" }, @@ -413,7 +416,7 @@ ircd::json::input::throws_exceeded() /////////////////////////////////////////////////////////////////////////////// // -// stack.h +// json/stack.h // ircd::json::stack::stack(const mutable_buffer &buf, @@ -1265,7 +1268,7 @@ ircd::json::_prev(chase &c) /////////////////////////////////////////////////////////////////////////////// // -// iov.h +// json/iov.h // decltype(ircd::json::iov::max_size) @@ -2282,24 +2285,6 @@ ircd::json::sorted(const member *const &begin, // json/value.h // -const ircd::string_view ircd::json::literal_null { "null" }; -const ircd::string_view ircd::json::literal_true { "true" }; -const ircd::string_view ircd::json::literal_false { "false" }; -const ircd::string_view ircd::json::empty_string { "\"\"" }; -const ircd::string_view ircd::json::empty_object { "{}" }; -const ircd::string_view ircd::json::empty_array { "[]" }; - -decltype(ircd::json::undefined_number) -ircd::json::undefined_number -{ - std::numeric_limits::min() -}; - -static_assert -( - ircd::json::undefined_number != 0 -); - decltype(ircd::json::value::max_string_size) ircd::json::value::max_string_size { @@ -3173,9 +3158,27 @@ ircd::json::operator==(const value &a, const value &b) /////////////////////////////////////////////////////////////////////////////// // -// json.h +// json/util.h // +const ircd::string_view ircd::json::literal_null { "null" }; +const ircd::string_view ircd::json::literal_true { "true" }; +const ircd::string_view ircd::json::literal_false { "false" }; +const ircd::string_view ircd::json::empty_string { "\"\"" }; +const ircd::string_view ircd::json::empty_object { "{}" }; +const ircd::string_view ircd::json::empty_array { "[]" }; + +decltype(ircd::json::undefined_number) +ircd::json::undefined_number +{ + std::numeric_limits::min() +}; + +static_assert +( + ircd::json::undefined_number != 0 +); + std::string ircd::json::why(const string_view &s) try @@ -3273,6 +3276,11 @@ ircd::json::serialized(const string_view &v) return serialized(value); } +/////////////////////////////////////////////////////////////////////////////// +// +// json/json.h +// + enum ircd::json::type ircd::json::type(const string_view &buf) { @@ -3285,7 +3293,7 @@ ircd::json::type(const string_view &buf) if(!qi::phrase_parse(begin(buf), end(buf), parser.type, parser.WS, flag, ret)) throw type_error { - "Failed to get type from buffer" + "Failed to derive JSON value type from input buffer." }; return ret; @@ -3319,5 +3327,8 @@ ircd::json::reflect(const enum type &type) case STRING: return "STRING"; } - return {}; + throw type_error + { + "Unknown type %x", uint(type) + }; }