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:
parent
97181f9eca
commit
0d78a07f55
3 changed files with 93 additions and 82 deletions
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
57
ircd/json.cc
57
ircd/json.cc
|
@ -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)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue