mirror of
https://github.com/matrix-construct/construct
synced 2024-11-17 07:20:55 +01:00
ircd::json: Simplify grammar / various cleanup.
This commit is contained in:
parent
0a9d7e2ec8
commit
eaca7429b6
12 changed files with 1124 additions and 1439 deletions
|
@ -68,7 +68,7 @@ namespace ircd::json
|
|||
struct array;
|
||||
struct object;
|
||||
struct value;
|
||||
struct index;
|
||||
struct member;
|
||||
struct iov;
|
||||
|
||||
enum type
|
||||
|
@ -81,6 +81,7 @@ namespace ircd::json
|
|||
};
|
||||
enum type type(const string_view &);
|
||||
enum type type(const string_view &, std::nothrow_t);
|
||||
string_view reflect(const enum type &);
|
||||
|
||||
/// Higher order type beyond a string to cleanly delimit multiple keys.
|
||||
using path = std::initializer_list<string_view>;
|
||||
|
@ -94,13 +95,14 @@ namespace ircd::json
|
|||
template<class... T> std::string string(T&&... t);
|
||||
|
||||
size_t serialized(const string_view &);
|
||||
|
||||
using members = std::initializer_list<member>;
|
||||
}
|
||||
|
||||
#include "json/array.h"
|
||||
#include "json/object.h"
|
||||
#include "json/value.h"
|
||||
#include "json/member.h"
|
||||
#include "json/index.h"
|
||||
#include "json/property.h"
|
||||
#include "json/iov.h"
|
||||
#include "json/tuple.h"
|
||||
|
@ -168,7 +170,13 @@ ircd::json::string(T&&... t)
|
|||
std::string ret(size, char{});
|
||||
const auto buf{const_cast<char *>(ret.data())};
|
||||
const auto max{ret.size() + 1};
|
||||
print(buf, max, std::forward<T>(t)...);
|
||||
|
||||
const auto printed
|
||||
{
|
||||
print(buf, max, std::forward<T>(t)...)
|
||||
};
|
||||
|
||||
assert(printed == ret.size());
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,15 +22,22 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_JSON_ARRAY_H
|
||||
|
||||
namespace ircd::json
|
||||
{
|
||||
struct array;
|
||||
|
||||
string_view stringify(mutable_buffer &buf, const string_view *const &begin, const string_view *const &end);
|
||||
string_view stringify(mutable_buffer &buf, const std::string *const &begin, const std::string *const &end);
|
||||
}
|
||||
|
||||
/// Lightweight interface to a JSON array string.
|
||||
///
|
||||
/// This is the rank1 analog to ircd::json::object. It accepts queries with
|
||||
/// numerical indexing. The same parsing approach is used in ircd::json::object
|
||||
/// and that is important to note here: iterating this array by incrementing
|
||||
/// your own numerical index and making calls into this object is NOT efficient.
|
||||
/// Simply put, do not do something like
|
||||
/// `for(int x=0; x<array.count(); x++) array.at(x)` as that will parse the
|
||||
/// array from the beginning on every single iteration. Instead, use the
|
||||
/// This object accepts queries with numerical indexing. The same parsing
|
||||
/// approach is used in ircd::json::object and that is important to note here:
|
||||
/// iterating this array by incrementing your own numerical index and making
|
||||
/// calls into this object is NOT efficient. Simply put, do not do something
|
||||
/// like `for(int x=0; x<array.count(); x++) array.at(x)` as that will parse
|
||||
/// the array from the beginning on every single iteration. Instead, use the
|
||||
/// provided iterator object.
|
||||
///
|
||||
struct ircd::json::array
|
||||
|
@ -59,8 +66,8 @@ struct ircd::json::array
|
|||
|
||||
using string_view::string_view;
|
||||
|
||||
template<class it> static string_view stringify(mutable_buffer &, const it &b, const it &e);
|
||||
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 &);
|
||||
};
|
||||
|
||||
|
@ -69,7 +76,9 @@ struct ircd::json::array::const_iterator
|
|||
using value_type = const string_view;
|
||||
using pointer = value_type *;
|
||||
using reference = value_type &;
|
||||
using difference_type = size_t;
|
||||
using iterator = const_iterator;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -1,185 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Charybdis Development Team
|
||||
* Copyright (C) 2017 Jason Volk <jason@zemos.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice is present in all copies.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_JSON_INDEX_H
|
||||
|
||||
struct ircd::json::index
|
||||
{
|
||||
struct const_iterator;
|
||||
|
||||
using key_type = value;
|
||||
using mapped_type = value;
|
||||
using value_type = const member;
|
||||
using size_type = size_t;
|
||||
using difference_type = size_t;
|
||||
using key_compare = std::less<member>;
|
||||
using index_type = std::vector<member>;
|
||||
|
||||
index_type idx;
|
||||
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
const_iterator cbegin();
|
||||
const_iterator cend();
|
||||
|
||||
bool empty() const;
|
||||
size_t count() const;
|
||||
size_t serialized() const;
|
||||
|
||||
const_iterator find(const string_view &name) const;
|
||||
bool has(const string_view &name) const;
|
||||
|
||||
const value &operator[](const string_view &name) const;
|
||||
const value &at(const string_view &name) const;
|
||||
|
||||
const_iterator erase(const const_iterator &s, const const_iterator &e);
|
||||
void erase(const const_iterator &s);
|
||||
bool erase(const string_view &name);
|
||||
|
||||
operator std::string() const;
|
||||
|
||||
IRCD_OVERLOAD(recursive)
|
||||
|
||||
index(std::initializer_list<member>);
|
||||
index(const object &d);
|
||||
index(recursive_t, const object &d);
|
||||
index() = default;
|
||||
index(index &&) = default;
|
||||
index(const index &) = delete;
|
||||
|
||||
friend index &operator+=(index &, const object &); // integration
|
||||
friend index operator+(const object &, const object &); // integral
|
||||
|
||||
friend size_t serialized(const index &);
|
||||
friend string_view stringify(mutable_buffer &, const index &);
|
||||
friend std::ostream &operator<<(std::ostream &, const index &);
|
||||
};
|
||||
|
||||
struct ircd::json::index::const_iterator
|
||||
{
|
||||
using value_type = const member;
|
||||
using pointer = value_type *;
|
||||
using reference = value_type &;
|
||||
using difference_type = size_t;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
|
||||
protected:
|
||||
friend class index;
|
||||
|
||||
index::index_type::const_iterator it;
|
||||
|
||||
operator const auto &() const { return it; }
|
||||
|
||||
const_iterator(const decltype(it) &it)
|
||||
:it{it}
|
||||
{}
|
||||
|
||||
public:
|
||||
value_type *operator->() const { return it.operator->(); }
|
||||
value_type &operator*() const { return it.operator*(); }
|
||||
|
||||
const_iterator &operator++() { ++it; return *this; }
|
||||
const_iterator &operator--() { --it; return *this; }
|
||||
|
||||
friend bool operator==(const const_iterator &a, const const_iterator &b);
|
||||
friend bool operator!=(const const_iterator &a, const const_iterator &b);
|
||||
friend bool operator<(const const_iterator &a, const const_iterator &b);
|
||||
};
|
||||
|
||||
inline const ircd::json::value &
|
||||
ircd::json::index::operator[](const string_view &name)
|
||||
const
|
||||
{
|
||||
return at(name);
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::index::has(const string_view &name)
|
||||
const
|
||||
{
|
||||
return find(name) != end();
|
||||
}
|
||||
|
||||
inline ircd::json::index::const_iterator
|
||||
ircd::json::index::find(const string_view &name)
|
||||
const
|
||||
{
|
||||
return std::find(std::begin(idx), std::end(idx), name);
|
||||
}
|
||||
|
||||
inline size_t
|
||||
ircd::json::index::count()
|
||||
const
|
||||
{
|
||||
return idx.size();
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::index::empty()
|
||||
const
|
||||
{
|
||||
return idx.empty();
|
||||
}
|
||||
|
||||
inline ircd::json::index::const_iterator
|
||||
ircd::json::index::cbegin()
|
||||
{
|
||||
return { std::begin(idx) };
|
||||
}
|
||||
|
||||
inline ircd::json::index::const_iterator
|
||||
ircd::json::index::cend()
|
||||
{
|
||||
return { std::end(idx) };
|
||||
}
|
||||
|
||||
inline ircd::json::index::const_iterator
|
||||
ircd::json::index::begin()
|
||||
const
|
||||
{
|
||||
return { std::begin(idx) };
|
||||
}
|
||||
|
||||
inline ircd::json::index::const_iterator
|
||||
ircd::json::index::end()
|
||||
const
|
||||
{
|
||||
return { std::end(idx) };
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<(const index::const_iterator &a, const index::const_iterator &b)
|
||||
{
|
||||
return a.it < b.it;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator!=(const index::const_iterator &a, const index::const_iterator &b)
|
||||
{
|
||||
return a.it != b.it;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator==(const index::const_iterator &a, const index::const_iterator &b)
|
||||
{
|
||||
return a.it == b.it;
|
||||
}
|
|
@ -55,16 +55,11 @@ struct ircd::json::iov
|
|||
struct set;
|
||||
struct set_if;
|
||||
|
||||
private:
|
||||
std::forward_list<node> allocated;
|
||||
|
||||
public:
|
||||
bool has(const string_view &key) const;
|
||||
const value &at(const string_view &key) const;
|
||||
|
||||
iov() = default;
|
||||
iov(member);
|
||||
iov(members);
|
||||
|
||||
friend string_view stringify(mutable_buffer &, const iov &);
|
||||
friend std::ostream &operator<<(std::ostream &, const iov &);
|
||||
|
@ -78,6 +73,8 @@ struct ircd::json::iov::push
|
|||
push(iov &iov, args&&... a)
|
||||
:node{iov, std::forward<args>(a)...}
|
||||
{}
|
||||
|
||||
push() = default;
|
||||
};
|
||||
|
||||
struct ircd::json::iov::add
|
||||
|
@ -88,7 +85,7 @@ struct ircd::json::iov::add
|
|||
};
|
||||
|
||||
struct ircd::json::iov::add_if
|
||||
:ircd::json::iov::add
|
||||
:protected ircd::json::iov::node
|
||||
{
|
||||
add_if(iov &, const bool &, member);
|
||||
add_if() = default;
|
||||
|
@ -102,44 +99,8 @@ struct ircd::json::iov::set
|
|||
};
|
||||
|
||||
struct ircd::json::iov::set_if
|
||||
:ircd::json::iov::set
|
||||
:protected ircd::json::iov::node
|
||||
{
|
||||
set_if(iov &, const bool &, member);
|
||||
set_if() = default;
|
||||
};
|
||||
|
||||
inline
|
||||
ircd::json::iov::iov(json::member m)
|
||||
{
|
||||
allocated.emplace_front(*this, std::move(m));
|
||||
}
|
||||
|
||||
inline
|
||||
ircd::json::iov::iov(members m)
|
||||
{
|
||||
for(auto&& member : m)
|
||||
allocated.emplace_front(*this, std::move(member));
|
||||
}
|
||||
|
||||
inline size_t
|
||||
ircd::json::serialized(const iov &iov)
|
||||
{
|
||||
const size_t ret
|
||||
{
|
||||
1U + !iov.empty()
|
||||
};
|
||||
|
||||
return std::accumulate(std::begin(iov), std::end(iov), ret, []
|
||||
(auto ret, const auto &member)
|
||||
{
|
||||
return ret += serialized(member);
|
||||
});
|
||||
}
|
||||
|
||||
inline std::ostream &
|
||||
ircd::json::operator<<(std::ostream &s, const iov &iov)
|
||||
{
|
||||
s << string(iov);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,10 @@ namespace ircd::json
|
|||
string_view stringify(mutable_buffer &, const member *const &begin, const member *const &end);
|
||||
}
|
||||
|
||||
/// A pair of json::value representing an object member.
|
||||
/// A pair of json::value representing state for a member of an object.
|
||||
///
|
||||
/// This is slightly heavier than object::member as that only deals with
|
||||
/// a pair of strings while the value here holds more diverse native state.
|
||||
///
|
||||
/// The key value (member.first) should always be a STRING type. We don't use
|
||||
/// string_view directly in member.first because json::value can take ownership
|
||||
|
@ -42,7 +45,6 @@ struct ircd::json::member
|
|||
:std::pair<value, value>
|
||||
{
|
||||
using std::pair<value, value>::pair;
|
||||
template<class K> member(const K &k, std::initializer_list<member> v);
|
||||
template<class K, class V> member(const K &k, V&& v);
|
||||
explicit member(const string_view &k);
|
||||
explicit member(const object::member &m);
|
||||
|
@ -79,15 +81,6 @@ ircd::json::member::member(const K &k,
|
|||
}
|
||||
{}
|
||||
|
||||
template<class K>
|
||||
ircd::json::member::member(const K &k,
|
||||
std::initializer_list<member> v)
|
||||
:std::pair<value, value>
|
||||
{
|
||||
value { k }, value { std::make_unique<index>(std::move(v)) }
|
||||
}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::member::member(const object::member &m)
|
||||
:std::pair<value, value>
|
||||
|
|
|
@ -31,7 +31,9 @@ namespace ircd::json
|
|||
///
|
||||
/// This makes queries into a string of JSON. This is a read-only device.
|
||||
/// It is merely functionality built on top of a string_view which is just a
|
||||
/// pair of const char* pointers to the borders of the JSON object.
|
||||
/// pair of `const char*` pointers to the borders of the JSON object. The first
|
||||
/// character should be '{' and the last character should be '}' but this is
|
||||
/// not checked on construction.
|
||||
///
|
||||
/// This class computes over strings of JSON by parsing it on-the-fly
|
||||
/// via forward iteration. The const_iterator is fundamental. All other member
|
||||
|
@ -50,12 +52,10 @@ namespace ircd::json
|
|||
/// type if they want a truly pure value string. Our zero-copy string_view utils
|
||||
/// make this to a simple ballet of pointers.
|
||||
///
|
||||
/// Other devices for dealing with strings of JSON are available: if an index
|
||||
/// should be populated (ircd::json::index), or if a certain set of keys
|
||||
/// should be found and extracted with a single pass (ircd::json::extract).
|
||||
///
|
||||
/// Some serialization/write functions are actually provided here, these
|
||||
/// are to *rewrite* JSON into our desired output form.
|
||||
/// Some serialization/write functions are actually provided here. They will
|
||||
/// always *rewrite* JSON through our generator correcting any imperfections
|
||||
/// that may have been allowed by the parsing grammar (if such allowances are
|
||||
/// ever made).
|
||||
///
|
||||
/// Recursive traversal cannot be achieved via a single key string value; so
|
||||
/// any string_view argument for a key will not be recursive. In other words,
|
||||
|
@ -123,12 +123,12 @@ struct ircd::json::object::member
|
|||
:std::pair<string_view, string_view>{first, second}
|
||||
{}
|
||||
|
||||
friend bool operator==(const member &, const member &);
|
||||
friend bool operator!=(const member &, const member &);
|
||||
friend bool operator<=(const member &, const member &);
|
||||
friend bool operator>=(const member &, const member &);
|
||||
friend bool operator<(const member &, const member &);
|
||||
friend bool operator>(const member &, const member &);
|
||||
friend bool operator==(const object::member &, const object::member &);
|
||||
friend bool operator!=(const object::member &, const object::member &);
|
||||
friend bool operator<=(const object::member &, const object::member &);
|
||||
friend bool operator>=(const object::member &, const object::member &);
|
||||
friend bool operator<(const object::member &, const object::member &);
|
||||
friend bool operator>(const object::member &, const object::member &);
|
||||
|
||||
// writes a single member onto stream
|
||||
friend string_view stringify(mutable_buffer &, const object::member &);
|
||||
|
@ -137,10 +137,14 @@ struct ircd::json::object::member
|
|||
|
||||
struct ircd::json::object::const_iterator
|
||||
{
|
||||
using key_type = string_view;
|
||||
using mapped_type = string_view;
|
||||
using value_type = const member;
|
||||
using pointer = value_type *;
|
||||
using reference = value_type &;
|
||||
using size_type = size_t;
|
||||
using difference_type = size_t;
|
||||
using key_compare = std::less<value_type>;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -33,17 +33,19 @@ struct tuple_base
|
|||
|
||||
/// A compile-time construct to describe a JSON object's members and types.
|
||||
///
|
||||
/// Member access by name is O(1) because of recursive constexpr function
|
||||
/// inlining when translating a name to the index number which is then used
|
||||
/// as the template argument to std::get() for the value.
|
||||
///
|
||||
/// Here we represent a JSON object with a named tuple, allowing the programmer
|
||||
/// to create a structure specifying all of the potentially valid members of the
|
||||
/// object. Thus at runtime, the tuple only carries around its values like a
|
||||
/// `struct`. Unlike a `struct`, the tuple is abstractly iterable and we have
|
||||
/// implemented logic operating on all JSON tuples regardless of their makeup
|
||||
/// without any effort from a developer creating a new tuple.
|
||||
/// without any effort from a developer when creating a new tuple.
|
||||
///
|
||||
/// The member structure for the tuple is called `property` because json::member
|
||||
/// is already used to pair together runtime oriented json::values. This system
|
||||
/// only decays into runtime members and values when compile-time logic cannot
|
||||
/// be achieved.
|
||||
/// is already used to pair together runtime oriented json::values.
|
||||
///
|
||||
/// Create and use a tuple to efficiently extract members from a json::object.
|
||||
/// The tuple will populate its own members during a single-pass iteration of
|
||||
|
@ -585,7 +587,6 @@ tuple<T...>::tuple(const json::iov &iov)
|
|||
{
|
||||
switch(type(member.second))
|
||||
{
|
||||
case type::STRING:
|
||||
case type::OBJECT:
|
||||
case type::ARRAY:
|
||||
if(unlikely(!member.second.serial))
|
||||
|
@ -729,7 +730,7 @@ _member_transform(const tuple<T...> &tuple,
|
|||
if(it == end)
|
||||
return false;
|
||||
|
||||
*it = { key, val };
|
||||
*it = member { key, val };
|
||||
++it;
|
||||
return true;
|
||||
});
|
||||
|
|
|
@ -22,21 +22,47 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_JSON_VALUE_H
|
||||
|
||||
namespace ircd::json
|
||||
{
|
||||
struct value;
|
||||
|
||||
using values = std::initializer_list<value>;
|
||||
|
||||
size_t serialized(const value *const &begin, const value *const &end);
|
||||
size_t serialized(const values &);
|
||||
|
||||
string_view stringify(mutable_buffer &, const value *const &begin, const value *const &end);
|
||||
}
|
||||
|
||||
/// A primitive of the ircd::json system representing a value at runtime.
|
||||
///
|
||||
/// This holds state for values apropos a JSON object.
|
||||
///
|
||||
/// Value's data can either be in the form of a JSON string or it can be
|
||||
/// native machine state. The serial flag indicates the former.
|
||||
///
|
||||
/// Value is capable of allocation and ownership of its internal data if
|
||||
/// necessary with move semantics, but copying may be not implemented in
|
||||
/// exceptional cases.
|
||||
/// This holds state for values apropos a JSON object or array. Value's
|
||||
/// data can either be in the form of a JSON string or it can be some native
|
||||
/// machine state. The serial flag indicates the former.
|
||||
///
|
||||
/// Value can can hold any of the JSON types in either of these states.
|
||||
/// This is accomplished with runtime switching and branching but this is
|
||||
/// still lightweight. The structure is just the size of two pointers, the
|
||||
/// same as a string_view.
|
||||
/// still lightweight and without a vtable pointer. The structure is just
|
||||
/// the size of two pointers like a string_view; we commandeer bits of the
|
||||
/// second word to hold type, flags, and length information. Thus we can hold
|
||||
/// large vectors of values at 16 byte alignment and not 24 byte.
|
||||
///
|
||||
/// Value is capable of allocation and ownership of its internal data and copy
|
||||
/// semantics. This is primarily to support recursion and various developer
|
||||
/// conveniences like nested initializer_list's etc. It is better to
|
||||
/// std::move() a value than copy it, but the full copy semantic is supported;
|
||||
/// however, if serial=false then a copy will stringify the data into JSON and
|
||||
/// the destination will be serial=true,alloc=true; thus copying of complex
|
||||
/// native values never occurs.
|
||||
///
|
||||
/// Take careful note of a quirk with `operator string_view()`: when the
|
||||
/// value is a STRING type string_view()'ing the value will never show
|
||||
/// the string with surrounding quotes in view. This is because the value
|
||||
/// accepts both quoted and unquoted strings as input from the developer, then
|
||||
/// always serializes correctly; unquoted strings are more natural to work
|
||||
/// with. This does not apply to other types like OBJECT and array as
|
||||
/// string_view()'ing those when in a serial state will show surrounding '{'
|
||||
/// etc.
|
||||
///
|
||||
struct ircd::json::value
|
||||
{
|
||||
|
@ -45,41 +71,56 @@ struct ircd::json::value
|
|||
int64_t integer;
|
||||
double floating;
|
||||
const char *string;
|
||||
const struct index *object;
|
||||
const struct array *array;
|
||||
const struct value *array;
|
||||
const struct member *object;
|
||||
};
|
||||
|
||||
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 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;
|
||||
bool undefined() const;
|
||||
static const string_view literal_null;
|
||||
static const string_view literal_true;
|
||||
static const string_view literal_false;
|
||||
static const string_view empty_string;
|
||||
static const string_view empty_number;
|
||||
static const string_view empty_object;
|
||||
static const string_view empty_array;
|
||||
|
||||
operator string_view() const;
|
||||
using create_string_closure = std::function<void (const mutable_buffer &)>;
|
||||
void create_string(const size_t &len, const create_string_closure &);
|
||||
|
||||
public:
|
||||
bool null() const; ///< literal null or assets are really null
|
||||
bool empty() const; ///< null() or assets are empty
|
||||
bool undefined() const;
|
||||
bool operator!() const; ///< null() or undefined() or empty() or asset Falsy
|
||||
|
||||
operator string_view() const; ///< NOTE unquote()'s the string value
|
||||
explicit operator double() const;
|
||||
explicit operator int64_t() const;
|
||||
explicit operator std::string() const;
|
||||
explicit operator std::string() const; ///< NOTE full stringify() of value
|
||||
|
||||
template<class T> explicit value(const T &specialized);
|
||||
value(const string_view &sv, const enum type &);
|
||||
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 index *const &); // alloc = false
|
||||
value(std::unique_ptr<index>); // alloc = true
|
||||
value(const struct member *const &, const size_t &len);
|
||||
value(std::unique_ptr<const struct member[]>, const size_t &len); // alloc = true
|
||||
value(const struct value *const &, const size_t &len);
|
||||
value(std::unique_ptr<const struct value[]>, const size_t &len); // alloc = true
|
||||
value(const members &); // alloc = true
|
||||
value(const nullptr_t &);
|
||||
value();
|
||||
value(value &&) noexcept;
|
||||
value(const value &);
|
||||
value &operator=(value &&) noexcept;
|
||||
value &operator=(const value &) = delete;
|
||||
value &operator=(const value &);
|
||||
~value() noexcept;
|
||||
|
||||
friend enum type type(const value &a);
|
||||
friend bool operator==(const value &a, const value &b);
|
||||
friend bool operator!=(const value &a, const value &b);
|
||||
friend bool operator<=(const value &a, const value &b);
|
||||
|
@ -87,6 +128,7 @@ struct ircd::json::value
|
|||
friend bool operator<(const value &a, const value &b);
|
||||
friend bool operator>(const value &a, const value &b);
|
||||
|
||||
friend enum type type(const value &a);
|
||||
friend size_t serialized(const value &);
|
||||
friend string_view stringify(mutable_buffer &, const value &);
|
||||
friend std::ostream &operator<<(std::ostream &, const value &);
|
||||
|
@ -107,10 +149,10 @@ static_assert(sizeof(ircd::json::value) == 16, "");
|
|||
|
||||
inline
|
||||
ircd::json::value::value()
|
||||
:string{""}
|
||||
:string{nullptr}
|
||||
,len{0}
|
||||
,type{STRING}
|
||||
,serial{true}
|
||||
,serial{false}
|
||||
,alloc{false}
|
||||
,floats{false}
|
||||
{}
|
||||
|
@ -121,15 +163,93 @@ ircd::json::value::value(const string_view &sv,
|
|||
:string{sv.data()}
|
||||
,len{sv.size()}
|
||||
,type{type}
|
||||
,serial{true}
|
||||
,serial{type == STRING? surrounds(sv, '"') : true}
|
||||
,alloc{false}
|
||||
,floats{false}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(const index *const &object)
|
||||
ircd::json::value::value(const char *const &s)
|
||||
:string{s}
|
||||
,len{strlen(s)}
|
||||
,type{json::type(s, std::nothrow)}
|
||||
,serial{type == STRING? surrounds(s, '"') : true}
|
||||
,alloc{false}
|
||||
,floats{false}
|
||||
{}
|
||||
|
||||
template<size_t N>
|
||||
ircd::json::value::value(const char (&str)[N])
|
||||
:string{str}
|
||||
,len{strnlen(str, N)}
|
||||
,type{json::type(str, std::nothrow)}
|
||||
,serial{type == STRING? surrounds(str, '"') : true}
|
||||
,alloc{false}
|
||||
,floats{false}
|
||||
{}
|
||||
|
||||
template<> inline
|
||||
ircd::json::value::value(const std::string &str)
|
||||
:value{string_view{str}}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(const string_view &sv)
|
||||
:value{sv, json::type(sv, std::nothrow)}
|
||||
{}
|
||||
|
||||
template<class T>
|
||||
ircd::json::value::value(const T &t)
|
||||
:value{static_cast<string_view>(t)}
|
||||
{
|
||||
static_assert(std::is_base_of<ircd::string_view, T>() ||
|
||||
std::is_convertible<ircd::string_view, T>(), "");
|
||||
}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(const nullptr_t &)
|
||||
:value
|
||||
{
|
||||
literal_null, type::LITERAL
|
||||
}{}
|
||||
|
||||
template<> inline
|
||||
ircd::json::value::value(const bool &boolean)
|
||||
:value
|
||||
{
|
||||
boolean? literal_true : literal_false, type::LITERAL
|
||||
}{}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(const struct value *const &array,
|
||||
const size_t &len)
|
||||
:array{array}
|
||||
,len{len}
|
||||
,type{ARRAY}
|
||||
,serial{false}
|
||||
,alloc{false}
|
||||
,floats{false}
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(std::unique_ptr<const struct value[]> array,
|
||||
const size_t &len)
|
||||
:array{array.get()}
|
||||
,len{len}
|
||||
,type{ARRAY}
|
||||
,serial{false}
|
||||
,alloc{true}
|
||||
,floats{false}
|
||||
{
|
||||
array.release();
|
||||
}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(const struct member *const &object,
|
||||
const size_t &len)
|
||||
:object{object}
|
||||
,len{0}
|
||||
,len{len}
|
||||
,type{OBJECT}
|
||||
,serial{false}
|
||||
,alloc{false}
|
||||
|
@ -137,9 +257,10 @@ ircd::json::value::value(const index *const &object)
|
|||
{}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(std::unique_ptr<index> object)
|
||||
ircd::json::value::value(std::unique_ptr<const struct member[]> object,
|
||||
const size_t &len)
|
||||
:object{object.get()}
|
||||
,len{0}
|
||||
,len{len}
|
||||
,type{OBJECT}
|
||||
,serial{false}
|
||||
,alloc{true}
|
||||
|
@ -183,50 +304,6 @@ ircd::json::value::value(const int16_t &integer)
|
|||
:value{int64_t(integer)}
|
||||
{}
|
||||
|
||||
template<> inline
|
||||
ircd::json::value::value(const bool &boolean)
|
||||
:value
|
||||
{
|
||||
boolean? "true" : "false",
|
||||
type::LITERAL
|
||||
}{}
|
||||
|
||||
template<> inline
|
||||
ircd::json::value::value(const std::string &str)
|
||||
:value{string_view{str}}
|
||||
{}
|
||||
|
||||
template<class T>
|
||||
ircd::json::value::value(const T &t)
|
||||
:value{static_cast<string_view>(t)}
|
||||
{
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
ircd::json::value::value(const char (&str)[N])
|
||||
: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)
|
||||
:string{s}
|
||||
,len{strlen(s)}
|
||||
,type{json::type(s, std::nothrow)}
|
||||
,serial{true}
|
||||
,alloc{false}
|
||||
,floats{false}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(const string_view &sv)
|
||||
:value{sv, json::type(sv, std::nothrow)}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(value &&other)
|
||||
noexcept
|
||||
|
@ -240,33 +317,6 @@ 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
|
||||
|
|
|
@ -36,7 +36,7 @@ struct ircd::m::error
|
|||
template<class... args> error(const http::code &, const string_view &errcode, const char *const &fmt, args&&...);
|
||||
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::members &);
|
||||
error(const http::code &, const json::iov &);
|
||||
error(const http::code &);
|
||||
error(std::string = {});
|
||||
|
@ -83,8 +83,14 @@ ircd::m::error::error(const http::code &c)
|
|||
|
||||
inline
|
||||
ircd::m::error::error(const http::code &c,
|
||||
const json::index &index)
|
||||
:http::error{c, std::string{index}}
|
||||
const json::members &members)
|
||||
:http::error{c, json::string(members)}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::m::error::error(const http::code &c,
|
||||
const json::iov &iov)
|
||||
:http::error{c, json::string(iov)}
|
||||
{}
|
||||
|
||||
inline
|
||||
|
@ -111,15 +117,15 @@ ircd::m::error::error(const http::code &status,
|
|||
{
|
||||
status, [&]() -> std::string
|
||||
{
|
||||
char estr[256]; const auto estr_len
|
||||
char estr[512]; const auto estr_len
|
||||
{
|
||||
fmt::snprintf{estr, sizeof(estr), fmt, std::forward<args>(a)...}
|
||||
};
|
||||
|
||||
return json::index
|
||||
return json::string(json::members
|
||||
{
|
||||
{ "errcode", errcode },
|
||||
{ "error", string_view(estr, estr_len) }
|
||||
};
|
||||
});
|
||||
}()
|
||||
}{}
|
||||
|
|
|
@ -29,17 +29,18 @@ namespace ircd {
|
|||
namespace m {
|
||||
|
||||
struct request
|
||||
:json::index
|
||||
{
|
||||
string_view method;
|
||||
string_view path;
|
||||
string_view query;
|
||||
string_view access_token;
|
||||
std::string _content;
|
||||
json::object content;
|
||||
|
||||
request(const string_view &method,
|
||||
const string_view &path,
|
||||
const string_view &query = {},
|
||||
std::initializer_list<json::member> body = {});
|
||||
json::members body = {});
|
||||
|
||||
request(const string_view &method,
|
||||
const string_view &path,
|
||||
|
@ -54,11 +55,12 @@ inline
|
|||
ircd::m::request::request(const string_view &method,
|
||||
const string_view &path,
|
||||
const string_view &query,
|
||||
std::initializer_list<json::member> body)
|
||||
:json::index{std::move(body)}
|
||||
,method{method}
|
||||
json::members body)
|
||||
:method{method}
|
||||
,path{path}
|
||||
,query{query}
|
||||
,_content{json::string(body)}
|
||||
,content{_content}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -67,9 +69,9 @@ ircd::m::request::request(const string_view &method,
|
|||
const string_view &path,
|
||||
const string_view &query,
|
||||
const json::object &content)
|
||||
:json::index{content}
|
||||
,method{method}
|
||||
:method{method}
|
||||
,path{path}
|
||||
,query{query}
|
||||
,content{content}
|
||||
{
|
||||
}
|
||||
|
|
16
ircd/db.cc
16
ircd/db.cc
|
@ -2416,6 +2416,22 @@ ircd::db::seek(column::const_iterator &it,
|
|||
template bool ircd::db::seek<ircd::db::pos>(column::const_iterator &, const pos &);
|
||||
template bool ircd::db::seek<ircd::string_view>(column::const_iterator &, const string_view &);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// merge.h
|
||||
//
|
||||
|
||||
std::string
|
||||
ircd::db::merge_operator(const string_view &key,
|
||||
const std::pair<string_view, string_view> &delta)
|
||||
{
|
||||
//ircd::json::index index{delta.first};
|
||||
//index += delta.second;
|
||||
//return index;
|
||||
assert(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// writebatch
|
||||
|
|
1928
ircd/json.cc
1928
ircd/json.cc
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue