0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-16 15:00:51 +01:00

ircd::json: Minor reorg / cleanup; improve some thrown errors.

This commit is contained in:
Jason Volk 2019-01-22 10:52:56 -08:00
parent 97181f9eca
commit 0d78a07f55
3 changed files with 93 additions and 82 deletions

View file

@ -43,10 +43,7 @@ namespace ircd::json
enum type type(const string_view &, std::nothrow_t); enum type type(const string_view &, std::nothrow_t);
string_view reflect(const enum type &); string_view reflect(const enum type &);
struct strung;
template<size_t SIZE> struct buffer;
template<class... T> string_view stringify(const mutable_buffer &&mb, T&&... t); template<class... T> string_view stringify(const mutable_buffer &&mb, T&&... t);
template<class... T> size_t print(const mutable_buffer &buf, T&&... t);
} }
#include "util.h" #include "util.h"
@ -70,32 +67,6 @@ namespace ircd
using json::get; 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<size_t SIZE>
struct ircd::json::buffer
:string_view
{
std::array<char, SIZE> b;
template<class... T>
buffer(T&&... t)
:string_view{stringify(b, std::forward<T>(t)...)}
{}
};
/// Convenience template for const rvalue mutable_buffers or basically /// Convenience template for const rvalue mutable_buffers or basically
/// allowing a bracket initialization of a mutable_buffer in the argument /// allowing a bracket initialization of a mutable_buffer in the argument
/// to stringify(). The const rvalue reference is on purpose. The stringify() /// 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}; mutable_buffer mbc{mb};
return stringify(mbc, std::forward<T>(t)...); return stringify(mbc, std::forward<T>(t)...);
} }
/// Convenience template using the syntax print(mutable_buffer, ...)
/// which stringifies with null termination into buffer.
///
template<class... T>
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>(t)...)
};
buf[sv.size()] = '\0';
valid_output(sv, size(sv)); // no size expectation check
return sv.size();
}

View file

@ -13,9 +13,10 @@
namespace ircd::json namespace ircd::json
{ {
struct string;
template<size_t SIZE> struct buffer;
using name_hash_t = size_t; using name_hash_t = size_t;
constexpr name_hash_t name_hash(const string_view name); using members = std::initializer_list<member>;
constexpr name_hash_t operator ""_(const char *const name, const size_t len);
extern const string_view literal_null; extern const string_view literal_null;
extern const string_view literal_true; extern const string_view literal_true;
@ -25,10 +26,12 @@ namespace ircd::json
extern const string_view empty_array; extern const string_view empty_array;
extern const int64_t undefined_number; 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 &); size_t serialized(const string_view &);
string_view stringify(mutable_buffer &, const string_view &); string_view stringify(mutable_buffer &, const string_view &);
template<class... T> size_t print(const mutable_buffer &buf, T&&... t);
using members = std::initializer_list<member>;
// Validate JSON - checks if valid JSON (not canonical). // Validate JSON - checks if valid JSON (not canonical).
bool valid(const string_view &, std::nothrow_t) noexcept; 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); 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<size_t SIZE>
struct ircd::json::buffer
:string_view
{
std::array<char, SIZE> b;
template<class... T>
buffer(T&&... t)
:string_view{stringify(b, std::forward<T>(t)...)}
{}
};
/// Convenience template using the syntax print(mutable_buffer, ...)
/// which stringifies with null termination into buffer.
///
template<class... T>
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>(t)...)
};
buf[sv.size()] = '\0';
valid_output(sv, size(sv)); // no size expectation check
return sv.size();
}
constexpr ircd::json::name_hash_t constexpr ircd::json::name_hash_t
ircd::json::operator ""_(const char *const text, const size_t len) ircd::json::operator ""_(const char *const text, const size_t len)
{ {

View file

@ -199,18 +199,21 @@ struct ircd::json::output
rule<> quote { lit('"') ,"quote" }; rule<> quote { lit('"') ,"quote" };
rule<> escape { lit('\\') ,"escape" }; rule<> escape { lit('\\') ,"escape" };
// literal
rule<string_view> lit_true { karma::string("true") ,"literal true" }; rule<string_view> lit_true { karma::string("true") ,"literal true" };
rule<string_view> lit_false { karma::string("false") ,"literal false" }; rule<string_view> lit_false { karma::string("false") ,"literal false" };
rule<string_view> lit_null { karma::string("null") ,"literal null" }; rule<string_view> lit_null { karma::string("null") ,"literal null" };
rule<string_view> boolean { lit_true | lit_false ,"boolean" }; rule<string_view> boolean { lit_true | lit_false ,"boolean" };
rule<string_view> literal { lit_true | lit_false | lit_null ,"literal" }; rule<string_view> literal { lit_true | lit_false | lit_null ,"literal" };
// number
rule<string_view> number rule<string_view> number
{ {
double_ double_
,"number" ,"number"
}; };
// string
std::map<char, const char *> escapes std::map<char, const char *> escapes
{ {
{ '"', "\\\"" }, { '"', "\\\"" },
@ -413,7 +416,7 @@ ircd::json::input::throws_exceeded()
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// stack.h // json/stack.h
// //
ircd::json::stack::stack(const mutable_buffer &buf, 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) decltype(ircd::json::iov::max_size)
@ -2282,24 +2285,6 @@ ircd::json::sorted(const member *const &begin,
// json/value.h // 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<decltype(ircd::json::undefined_number)>::min()
};
static_assert
(
ircd::json::undefined_number != 0
);
decltype(ircd::json::value::max_string_size) decltype(ircd::json::value::max_string_size)
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<decltype(ircd::json::undefined_number)>::min()
};
static_assert
(
ircd::json::undefined_number != 0
);
std::string std::string
ircd::json::why(const string_view &s) ircd::json::why(const string_view &s)
try try
@ -3273,6 +3276,11 @@ ircd::json::serialized(const string_view &v)
return serialized(value); return serialized(value);
} }
///////////////////////////////////////////////////////////////////////////////
//
// json/json.h
//
enum ircd::json::type enum ircd::json::type
ircd::json::type(const string_view &buf) 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)) if(!qi::phrase_parse(begin(buf), end(buf), parser.type, parser.WS, flag, ret))
throw type_error throw type_error
{ {
"Failed to get type from buffer" "Failed to derive JSON value type from input buffer."
}; };
return ret; return ret;
@ -3319,5 +3327,8 @@ ircd::json::reflect(const enum type &type)
case STRING: return "STRING"; case STRING: return "STRING";
} }
return {}; throw type_error
{
"Unknown type %x", uint(type)
};
} }