0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-30 15:58:20 +02:00

ircd::json: Improve value semantics and various fixes.

This commit is contained in:
Jason Volk 2017-09-12 10:02:27 -07:00
parent 6c9ad5e513
commit f8fc03e57b
5 changed files with 139 additions and 33 deletions

View file

@ -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 &);
};

View file

@ -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,

View file

@ -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

View file

@ -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 = {});

View file

@ -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 &