mirror of
https://github.com/matrix-construct/construct
synced 2025-01-13 08:23:56 +01:00
ircd::json: Improve value semantics and various fixes.
This commit is contained in:
parent
6c9ad5e513
commit
f8fc03e57b
5 changed files with 139 additions and 33 deletions
|
@ -60,6 +60,7 @@ struct ircd::json::array
|
|||
using string_view::string_view;
|
||||
|
||||
friend string_view stringify(mutable_buffer &, const array &);
|
||||
friend string_view stringify(mutable_buffer &, const std::vector<json::object> &);
|
||||
friend std::ostream &operator<<(std::ostream &, const array &);
|
||||
};
|
||||
|
||||
|
|
|
@ -25,16 +25,10 @@
|
|||
namespace ircd::json
|
||||
{
|
||||
struct member;
|
||||
using members = std::initializer_list<member>;
|
||||
|
||||
size_t serialized(const member *const &begin, const member *const &end);
|
||||
size_t serialized(const members &);
|
||||
|
||||
string_view stringify(mutable_buffer &, const member *const *const &begin, const member *const *const &end);
|
||||
string_view stringify(mutable_buffer &, const member *const &begin, const member *const &end);
|
||||
string_view stringify(mutable_buffer &, const members &);
|
||||
|
||||
string_view stringify(mutable_buffer &, const std::vector<json::object> &);
|
||||
}
|
||||
|
||||
/// A pair of json::value representing an object member.
|
||||
|
@ -67,6 +61,14 @@ struct ircd::json::member
|
|||
friend std::ostream &operator<<(std::ostream &, const member &);
|
||||
};
|
||||
|
||||
namespace ircd::json
|
||||
{
|
||||
using members = std::initializer_list<member>;
|
||||
|
||||
size_t serialized(const members &);
|
||||
string_view stringify(mutable_buffer &, const members &);
|
||||
}
|
||||
|
||||
template<class K,
|
||||
class V>
|
||||
ircd::json::member::member(const K &k,
|
||||
|
|
|
@ -49,15 +49,17 @@ struct ircd::json::value
|
|||
const struct array *array;
|
||||
};
|
||||
|
||||
uint64_t len : 58;
|
||||
enum type type : 3;
|
||||
uint64_t serial : 1;
|
||||
uint64_t alloc : 1;
|
||||
uint64_t floats : 1;
|
||||
uint64_t len : 57; ///< length indicator
|
||||
enum type type : 3; ///< json::type indicator
|
||||
uint64_t serial : 1; ///< only string* is used. type indicates JSON
|
||||
uint64_t alloc : 1; ///< indicates the pointer for type is owned
|
||||
uint64_t floats : 1; ///< for NUMBER type, integer or floating
|
||||
|
||||
public:
|
||||
bool null() const;
|
||||
bool empty() const;
|
||||
size_t serialized() const;
|
||||
bool undefined() const;
|
||||
|
||||
operator string_view() const;
|
||||
explicit operator double() const;
|
||||
explicit operator int64_t() const;
|
||||
|
@ -65,14 +67,14 @@ struct ircd::json::value
|
|||
|
||||
template<class T> explicit value(const T &specialized);
|
||||
template<size_t N> value(const char (&)[N]);
|
||||
value(const char *const &s);
|
||||
value(const string_view &sv, const enum type &);
|
||||
value(const string_view &sv);
|
||||
value(const char *const &s);
|
||||
value(const index *const &); // alloc = false
|
||||
value(std::unique_ptr<index>); // alloc = true
|
||||
value();
|
||||
value(value &&) noexcept;
|
||||
value(const value &) = delete;
|
||||
value(const value &);
|
||||
value &operator=(value &&) noexcept;
|
||||
value &operator=(const value &) = delete;
|
||||
~value() noexcept;
|
||||
|
@ -202,12 +204,22 @@ ircd::json::value::value(const T &t)
|
|||
|
||||
template<size_t N>
|
||||
ircd::json::value::value(const char (&str)[N])
|
||||
:value{string_view{str}}
|
||||
:string{str}
|
||||
,len{strnlen(str, N)}
|
||||
,type{json::type(str, std::nothrow)}
|
||||
,serial{true}
|
||||
,alloc{false}
|
||||
,floats{false}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(const char *const &s)
|
||||
:value{string_view{s}}
|
||||
:string{s}
|
||||
,len{strlen(s)}
|
||||
,type{json::type(s, std::nothrow)}
|
||||
,serial{true}
|
||||
,alloc{false}
|
||||
,floats{false}
|
||||
{}
|
||||
|
||||
inline
|
||||
|
@ -228,6 +240,33 @@ noexcept
|
|||
other.alloc = false;
|
||||
}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(const value &other)
|
||||
:integer{other.integer}
|
||||
,len{other.len}
|
||||
,type{other.type}
|
||||
,serial{other.serial}
|
||||
,alloc{other.alloc}
|
||||
,floats{other.floats}
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case NUMBER:
|
||||
break;
|
||||
|
||||
case LITERAL:
|
||||
case STRING:
|
||||
assert(serial);
|
||||
assert(!alloc);
|
||||
break;
|
||||
|
||||
case OBJECT:
|
||||
case ARRAY:
|
||||
assert(serial);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline ircd::json::value &
|
||||
ircd::json::value::operator=(value &&other)
|
||||
noexcept
|
||||
|
|
|
@ -37,6 +37,7 @@ struct ircd::m::error
|
|||
template<class... args> error(const string_view &errcode, const char *const &fmt, args&&...);
|
||||
error(const http::code &, const json::object &object = {});
|
||||
error(const http::code &, const json::index &idx);
|
||||
error(const http::code &, const json::iov &);
|
||||
error(const http::code &);
|
||||
error(std::string = {});
|
||||
|
||||
|
|
97
ircd/json.cc
97
ircd/json.cc
|
@ -963,7 +963,7 @@ const
|
|||
if(serial)
|
||||
return std::string(string_view(*this));
|
||||
else
|
||||
return std::string(*object);
|
||||
return json::string(*object);
|
||||
|
||||
case ARRAY:
|
||||
if(serial)
|
||||
|
@ -991,9 +991,16 @@ const
|
|||
case STRING:
|
||||
return unquote(string_view{string, len});
|
||||
|
||||
case NUMBER:
|
||||
if(serial)
|
||||
return string_view{string, len};
|
||||
else if(floats)
|
||||
return byte_view<string_view>{floating};
|
||||
else
|
||||
return byte_view<string_view>{integer};
|
||||
|
||||
case ARRAY:
|
||||
case OBJECT:
|
||||
case NUMBER:
|
||||
case LITERAL:
|
||||
if(serial)
|
||||
return string_view{string, len};
|
||||
|
@ -1013,6 +1020,7 @@ const
|
|||
return likely(!floats)? integer : floating;
|
||||
|
||||
case STRING:
|
||||
assert(serial);
|
||||
return lex_cast<int64_t>(string_view(*this));
|
||||
|
||||
case ARRAY:
|
||||
|
@ -1033,6 +1041,7 @@ const
|
|||
return likely(floats)? floating : integer;
|
||||
|
||||
case STRING:
|
||||
assert(serial);
|
||||
return lex_cast<double>(string_view(*this));
|
||||
|
||||
case ARRAY:
|
||||
|
@ -1044,6 +1053,36 @@ const
|
|||
throw type_error("value type[%d] is not a float", int(type));
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::json::value::undefined()
|
||||
const
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case NUMBER:
|
||||
return false;
|
||||
|
||||
case STRING:
|
||||
return string == nullptr;
|
||||
|
||||
case OBJECT:
|
||||
return serial? string == nullptr:
|
||||
object? object->empty():
|
||||
true;
|
||||
|
||||
case ARRAY:
|
||||
return serial? string == nullptr:
|
||||
array? array == nullptr:
|
||||
true;
|
||||
|
||||
case LITERAL:
|
||||
return serial? string == nullptr:
|
||||
true;
|
||||
};
|
||||
|
||||
throw type_error("deciding if a type[%u] is undefined is undefined", int(type));
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::json::value::empty()
|
||||
const
|
||||
|
@ -1054,32 +1093,56 @@ const
|
|||
case STRING: return !len;
|
||||
case OBJECT: return serial? !len : object? object->empty() : true;
|
||||
case ARRAY: return serial? !len : array? false : true; //TODO: XXX arr
|
||||
case LITERAL: return !len;
|
||||
case LITERAL: return serial? !len : true;
|
||||
};
|
||||
|
||||
throw type_error("deciding if a type[%u] is empty is undefined", int(type));
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::json::serialized(const value &value)
|
||||
{
|
||||
return value.serialized();
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::json::value::serialized()
|
||||
bool
|
||||
ircd::json::value::null()
|
||||
const
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case NUMBER: return lex_cast(integer).size();
|
||||
case STRING: return 1 + len + 1;
|
||||
case OBJECT: return serial? len : object->serialized();
|
||||
case ARRAY: return serial? len : 2;
|
||||
case LITERAL: return len;
|
||||
case NUMBER:
|
||||
return floats? !(floating > 0.0 || floating < 0.0):
|
||||
bool(integer);
|
||||
|
||||
case STRING:
|
||||
return string == nullptr;
|
||||
|
||||
case OBJECT:
|
||||
return serial? string == nullptr:
|
||||
object? object->empty():
|
||||
true;
|
||||
|
||||
case ARRAY:
|
||||
return serial? string == nullptr:
|
||||
array? array == nullptr:
|
||||
true;
|
||||
|
||||
case LITERAL:
|
||||
return serial? string == nullptr:
|
||||
true;
|
||||
};
|
||||
|
||||
throw type_error("deciding the size of a type[%u] is undefined", int(type));
|
||||
throw type_error("deciding if a type[%u] is null is undefined", int(type));
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::json::serialized(const value &v)
|
||||
{
|
||||
switch(v.type)
|
||||
{
|
||||
case NUMBER: return lex_cast(v.integer).size();
|
||||
case STRING: return 1 + v.len + 1;
|
||||
case OBJECT: return v.serial? v.len : serialized(*v.object);
|
||||
case ARRAY: return v.serial? v.len : 2;
|
||||
case LITERAL: return v.len;
|
||||
};
|
||||
|
||||
throw type_error("deciding the size of a type[%u] is undefined", int(v.type));
|
||||
}
|
||||
|
||||
std::ostream &
|
||||
|
|
Loading…
Reference in a new issue