0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-25 08:12:37 +01:00

ircd::json::stack: Add internal convenience member instance in the object and array class.

This commit is contained in:
Jason Volk 2019-01-08 14:49:04 -08:00
parent af6fcb24f4
commit f9ec33916c
2 changed files with 133 additions and 80 deletions

View file

@ -83,77 +83,6 @@ struct ircd::json::stack
~stack() noexcept;
};
/// stack::object is constructed under the scope of either a stack::member,
/// or a stack::array, or a stack itself. Only stack::member can be
/// constructed directly under its scope.
///
/// For a stack::member parent, the named member is waiting for this value
/// after leaving the stack at ':' after the name, this object will then
/// print '{' and dtor with '}' and then return to the stack::member which
/// will then return to its parent object.
///
/// For a stack::array parent, the stack may have been left at '[' or ','
/// but either way this object will then print '{' and dtor with '}' and
/// then return to the stack::array.
///
/// For a stack itself, this object is considered the "top object" and will
/// open the stack with '{' and accept member instances under its scope
/// until closing the stack with '}' after which the stack is done()
///
struct ircd::json::stack::object
{
stack *s {nullptr}; ///< root stack ref
member *pm {nullptr}; ///< parent member (if value of one)
array *pa {nullptr}; ///< parent array (if value in one)
member *cm {nullptr}; ///< current child member
size_t mc {0}; ///< members witnessed (monotonic)
public:
object(stack &s); ///< Object is top
object(array &pa); ///< Object is value in the array
object(member &pm); ///< Object is value of named member
object(object &&) noexcept;
object(const object &) = delete;
~object() noexcept;
static const object &top(const stack &);
static object &top(stack &);
};
/// stack::array is constructed under the scope of either a stack::member,
/// or a stack::array, or a stack itself. stack::object and stack::array
/// can be constructed directly under its scope, but not stack::member.
///
/// The same behavior as described by stack::object documentation applies
/// here translated to arrays.
///
struct ircd::json::stack::array
{
stack *s {nullptr}; ///< root stack ref
member *pm {nullptr}; ///< parent member (if value of one)
array *pa {nullptr}; ///< parent array (if value in one)
object *co {nullptr}; ///< current child object
array *ca {nullptr}; ///< current child array
size_t vc {0}; ///< values witnessed (monotonic)
void _pre_append();
void _post_append();
public:
template<class... T> void append(const json::tuple<T...> &);
void append(const json::value &);
array(stack &s); ///< Array is top
array(array &pa); ///< Array is value in the array
array(member &pm); ///< Array is value of the named member
array(const array &) = delete;
array(array &&) noexcept;
~array() noexcept;
static const array &top(const stack &);
static array &top(stack &);
};
/// stack::member is an intermediary that is constructed under the scope of
/// a parent stack::object. It takes a name argument. It then requires one
/// object or array be constructed under its scope as its value, or a
@ -184,6 +113,7 @@ struct ircd::json::stack::member
member(stack &s, const string_view &name, const json::value &);
template<class... T> member(object &po, const string_view &name, const json::tuple<T...> &t);
template<class... T> member(stack &s, const string_view &name, const json::tuple<T...> &t);
member() = default;
member(const member &) = delete;
member(member &&) noexcept;
~member() noexcept;
@ -192,6 +122,83 @@ struct ircd::json::stack::member
static member &top(stack &);
};
/// stack::object is constructed under the scope of either a stack::member,
/// or a stack::array, or a stack itself. Only stack::member can be
/// constructed directly under its scope.
///
/// For a stack::member parent, the named member is waiting for this value
/// after leaving the stack at ':' after the name, this object will then
/// print '{' and dtor with '}' and then return to the stack::member which
/// will then return to its parent object.
///
/// For a stack::array parent, the stack may have been left at '[' or ','
/// but either way this object will then print '{' and dtor with '}' and
/// then return to the stack::array.
///
/// For a stack itself, this object is considered the "top object" and will
/// open the stack with '{' and accept member instances under its scope
/// until closing the stack with '}' after which the stack is done()
///
struct ircd::json::stack::object
{
member m; ///< optional internal member
stack *s {nullptr}; ///< root stack ref
member *pm {nullptr}; ///< parent member (if value of one)
array *pa {nullptr}; ///< parent array (if value in one)
member *cm {nullptr}; ///< current child member
size_t mc {0}; ///< members witnessed (monotonic)
public:
object(stack &s); ///< Object is top
object(array &pa); ///< Object is value in the array
object(member &pm); ///< Object is value of named member
object(object &po, const string_view &name);
object(stack &s, const string_view &name);
object(object &&) noexcept;
object(const object &) = delete;
~object() noexcept;
static const object &top(const stack &);
static object &top(stack &);
};
/// stack::array is constructed under the scope of either a stack::member,
/// or a stack::array, or a stack itself. stack::object and stack::array
/// can be constructed directly under its scope, but not stack::member.
///
/// The same behavior as described by stack::object documentation applies
/// here translated to arrays.
///
struct ircd::json::stack::array
{
member m; ///< optional internal member
stack *s {nullptr}; ///< root stack ref
member *pm {nullptr}; ///< parent member (if value of one)
array *pa {nullptr}; ///< parent array (if value in one)
object *co {nullptr}; ///< current child object
array *ca {nullptr}; ///< current child array
size_t vc {0}; ///< values witnessed (monotonic)
void _pre_append();
void _post_append();
public:
template<class... T> void append(const json::tuple<T...> &);
void append(const json::value &);
array(member &pm); ///< Array is value of the named member
array(array &pa); ///< Array is value in the array
array(object &po, const string_view &name);
array(stack &s, const string_view &name);
array(stack &s);
array(const array &) = delete;
array(array &&) noexcept;
~array() noexcept;
static const array &top(const stack &);
static array &top(stack &);
};
/// This device chases the current active path by updating its member pointers.
struct ircd::json::stack::chase
{

View file

@ -612,7 +612,8 @@ ircd::json::stack::object::top(const stack &s)
ircd::json::stack::object::object(object &&other)
noexcept
:s{std::move(other.s)}
:m{std::move(other.m)}
,s{std::move(other.s)}
,pm{std::move(other.pm)}
,pa{std::move(other.pa)}
,cm{std::move(other.cm)}
@ -646,6 +647,28 @@ ircd::json::stack::object::object(stack &s)
s.append("{"_sv);
}
ircd::json::stack::object::object(stack &s,
const string_view &name)
:object{object::top(s), name}
{
}
ircd::json::stack::object::object(object &po,
const string_view &name)
:m{po, name}
,s{po.s}
,pm{&m}
{
assert(s->opened());
s->rethrow_exception();
assert(pm->co == nullptr);
assert(pm->ca == nullptr);
pm->co = this;
s->append("{"_sv);
pm->vc |= true;
}
ircd::json::stack::object::object(member &pm)
:s{pm.s}
,pm{&pm}
@ -760,7 +783,8 @@ ircd::json::stack::array::top(const stack &s)
ircd::json::stack::array::array(array &&other)
noexcept
:s{std::move(other.s)}
:m{std::move(other.m)}
,s{std::move(other.s)}
,pm{std::move(other.pm)}
,pa{std::move(other.pa)}
,co{std::move(other.co)}
@ -796,18 +820,26 @@ ircd::json::stack::array::array(stack &s)
s.append("["_sv);
}
ircd::json::stack::array::array(member &pm)
:s{pm.s}
,pm{&pm}
ircd::json::stack::array::array(stack &s,
const string_view &name)
:array{object::top(s), name}
{
}
ircd::json::stack::array::array(object &po,
const string_view &name)
:m{po, name}
,s{po.s}
,pm{&m}
{
assert(s->opened());
s->rethrow_exception();
assert(pm.co == nullptr);
assert(pm.ca == nullptr);
pm.ca = this;
assert(pm->co == nullptr);
assert(pm->ca == nullptr);
pm->ca = this;
s->append("["_sv);
pm.vc |= true;
pm->vc |= true;
}
ircd::json::stack::array::array(array &pa)
@ -827,6 +859,20 @@ ircd::json::stack::array::array(array &pa)
s->append("["_sv);
}
ircd::json::stack::array::array(member &pm)
:s{pm.s}
,pm{&pm}
{
assert(s->opened());
s->rethrow_exception();
assert(pm.co == nullptr);
assert(pm.ca == nullptr);
pm.ca = this;
s->append("["_sv);
pm.vc |= true;
}
ircd::json::stack::array::~array()
noexcept
{