0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-17 15:30:52 +01:00

ircd::json: Simplify grammar / various cleanup.

This commit is contained in:
Jason Volk 2017-09-14 11:30:06 -07:00
parent 0a9d7e2ec8
commit eaca7429b6
12 changed files with 1124 additions and 1439 deletions

View file

@ -68,7 +68,7 @@ namespace ircd::json
struct array; struct array;
struct object; struct object;
struct value; struct value;
struct index; struct member;
struct iov; struct iov;
enum type enum type
@ -81,6 +81,7 @@ namespace ircd::json
}; };
enum type type(const string_view &); enum type type(const string_view &);
enum type type(const string_view &, std::nothrow_t); 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. /// Higher order type beyond a string to cleanly delimit multiple keys.
using path = std::initializer_list<string_view>; using path = std::initializer_list<string_view>;
@ -94,13 +95,14 @@ namespace ircd::json
template<class... T> std::string string(T&&... t); template<class... T> std::string string(T&&... t);
size_t serialized(const string_view &); size_t serialized(const string_view &);
using members = std::initializer_list<member>;
} }
#include "json/array.h" #include "json/array.h"
#include "json/object.h" #include "json/object.h"
#include "json/value.h" #include "json/value.h"
#include "json/member.h" #include "json/member.h"
#include "json/index.h"
#include "json/property.h" #include "json/property.h"
#include "json/iov.h" #include "json/iov.h"
#include "json/tuple.h" #include "json/tuple.h"
@ -168,7 +170,13 @@ ircd::json::string(T&&... t)
std::string ret(size, char{}); std::string ret(size, char{});
const auto buf{const_cast<char *>(ret.data())}; const auto buf{const_cast<char *>(ret.data())};
const auto max{ret.size() + 1}; 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; return ret;
} }

View file

@ -22,15 +22,22 @@
#pragma once #pragma once
#define HAVE_IRCD_JSON_ARRAY_H #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. /// Lightweight interface to a JSON array string.
/// ///
/// This is the rank1 analog to ircd::json::object. It accepts queries with /// This object accepts queries with numerical indexing. The same parsing
/// numerical indexing. The same parsing approach is used in ircd::json::object /// approach is used in ircd::json::object and that is important to note here:
/// and that is important to note here: iterating this array by incrementing /// iterating this array by incrementing your own numerical index and making
/// your own numerical index and making calls into this object is NOT efficient. /// calls into this object is NOT efficient. Simply put, do not do something
/// Simply put, do not do something like /// like `for(int x=0; x<array.count(); x++) array.at(x)` as that will parse
/// `for(int x=0; x<array.count(); x++) array.at(x)` as that will parse the /// the array from the beginning on every single iteration. Instead, use the
/// array from the beginning on every single iteration. Instead, use the
/// provided iterator object. /// provided iterator object.
/// ///
struct ircd::json::array struct ircd::json::array
@ -59,8 +66,8 @@ struct ircd::json::array
using string_view::string_view; 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 array &);
friend string_view stringify(mutable_buffer &, const std::vector<json::object> &);
friend std::ostream &operator<<(std::ostream &, const array &); 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 value_type = const string_view;
using pointer = value_type *; using pointer = value_type *;
using reference = 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; using iterator_category = std::forward_iterator_tag;
protected: protected:

View file

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

View file

@ -55,16 +55,11 @@ struct ircd::json::iov
struct set; struct set;
struct set_if; struct set_if;
private:
std::forward_list<node> allocated;
public: public:
bool has(const string_view &key) const; bool has(const string_view &key) const;
const value &at(const string_view &key) const; const value &at(const string_view &key) const;
iov() = default; iov() = default;
iov(member);
iov(members);
friend string_view stringify(mutable_buffer &, const iov &); friend string_view stringify(mutable_buffer &, const iov &);
friend std::ostream &operator<<(std::ostream &, const iov &); friend std::ostream &operator<<(std::ostream &, const iov &);
@ -78,6 +73,8 @@ struct ircd::json::iov::push
push(iov &iov, args&&... a) push(iov &iov, args&&... a)
:node{iov, std::forward<args>(a)...} :node{iov, std::forward<args>(a)...}
{} {}
push() = default;
}; };
struct ircd::json::iov::add struct ircd::json::iov::add
@ -88,7 +85,7 @@ struct ircd::json::iov::add
}; };
struct ircd::json::iov::add_if struct ircd::json::iov::add_if
:ircd::json::iov::add :protected ircd::json::iov::node
{ {
add_if(iov &, const bool &, member); add_if(iov &, const bool &, member);
add_if() = default; add_if() = default;
@ -102,44 +99,8 @@ struct ircd::json::iov::set
}; };
struct ircd::json::iov::set_if struct ircd::json::iov::set_if
:ircd::json::iov::set :protected ircd::json::iov::node
{ {
set_if(iov &, const bool &, member); set_if(iov &, const bool &, member);
set_if() = default; 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;
}

View file

@ -31,7 +31,10 @@ namespace ircd::json
string_view stringify(mutable_buffer &, const member *const &begin, const member *const &end); 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 /// 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 /// string_view directly in member.first because json::value can take ownership
@ -42,7 +45,6 @@ struct ircd::json::member
:std::pair<value, value> :std::pair<value, value>
{ {
using std::pair<value, value>::pair; 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); template<class K, class V> member(const K &k, V&& v);
explicit member(const string_view &k); explicit member(const string_view &k);
explicit member(const object::member &m); 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 inline
ircd::json::member::member(const object::member &m) ircd::json::member::member(const object::member &m)
:std::pair<value, value> :std::pair<value, value>

View file

@ -31,7 +31,9 @@ namespace ircd::json
/// ///
/// This makes queries into a string of JSON. This is a read-only device. /// 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 /// 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 /// This class computes over strings of JSON by parsing it on-the-fly
/// via forward iteration. The const_iterator is fundamental. All other member /// 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 /// type if they want a truly pure value string. Our zero-copy string_view utils
/// make this to a simple ballet of pointers. /// make this to a simple ballet of pointers.
/// ///
/// Other devices for dealing with strings of JSON are available: if an index /// Some serialization/write functions are actually provided here. They will
/// should be populated (ircd::json::index), or if a certain set of keys /// always *rewrite* JSON through our generator correcting any imperfections
/// should be found and extracted with a single pass (ircd::json::extract). /// that may have been allowed by the parsing grammar (if such allowances are
/// /// ever made).
/// Some serialization/write functions are actually provided here, these
/// are to *rewrite* JSON into our desired output form.
/// ///
/// Recursive traversal cannot be achieved via a single key string value; so /// 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, /// 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} :std::pair<string_view, string_view>{first, second}
{} {}
friend bool operator==(const member &, const member &); friend bool operator==(const object::member &, const object::member &);
friend bool operator!=(const member &, const member &); friend bool operator!=(const object::member &, const object::member &);
friend bool operator<=(const member &, const member &); friend bool operator<=(const object::member &, const object::member &);
friend bool operator>=(const member &, const member &); friend bool operator>=(const object::member &, const object::member &);
friend bool operator<(const member &, const member &); friend bool operator<(const object::member &, const object::member &);
friend bool operator>(const member &, const member &); friend bool operator>(const object::member &, const object::member &);
// writes a single member onto stream // writes a single member onto stream
friend string_view stringify(mutable_buffer &, const object::member &); friend string_view stringify(mutable_buffer &, const object::member &);
@ -137,10 +137,14 @@ struct ircd::json::object::member
struct ircd::json::object::const_iterator struct ircd::json::object::const_iterator
{ {
using key_type = string_view;
using mapped_type = string_view;
using value_type = const member; using value_type = const member;
using pointer = value_type *; using pointer = value_type *;
using reference = value_type &; using reference = value_type &;
using size_type = size_t;
using difference_type = size_t; using difference_type = size_t;
using key_compare = std::less<value_type>;
using iterator_category = std::forward_iterator_tag; using iterator_category = std::forward_iterator_tag;
protected: protected:

View file

@ -33,17 +33,19 @@ struct tuple_base
/// A compile-time construct to describe a JSON object's members and types. /// 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 /// 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 /// 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 /// 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 /// `struct`. Unlike a `struct`, the tuple is abstractly iterable and we have
/// implemented logic operating on all JSON tuples regardless of their makeup /// 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 /// The member structure for the tuple is called `property` because json::member
/// is already used to pair together runtime oriented json::values. This system /// is already used to pair together runtime oriented json::values.
/// only decays into runtime members and values when compile-time logic cannot
/// be achieved.
/// ///
/// Create and use a tuple to efficiently extract members from a json::object. /// 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 /// 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)) switch(type(member.second))
{ {
case type::STRING:
case type::OBJECT: case type::OBJECT:
case type::ARRAY: case type::ARRAY:
if(unlikely(!member.second.serial)) if(unlikely(!member.second.serial))
@ -729,7 +730,7 @@ _member_transform(const tuple<T...> &tuple,
if(it == end) if(it == end)
return false; return false;
*it = { key, val }; *it = member { key, val };
++it; ++it;
return true; return true;
}); });

View file

@ -22,21 +22,47 @@
#pragma once #pragma once
#define HAVE_IRCD_JSON_VALUE_H #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. /// A primitive of the ircd::json system representing a value at runtime.
/// ///
/// This holds state for values apropos a JSON object. /// 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
/// Value's data can either be in the form of a JSON string or it can be /// machine state. The serial flag indicates the former.
/// 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.
/// ///
/// Value can can hold any of the JSON types in either of these states. /// 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 /// This is accomplished with runtime switching and branching but this is
/// still lightweight. The structure is just the size of two pointers, the /// still lightweight and without a vtable pointer. The structure is just
/// same as a string_view. /// 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 struct ircd::json::value
{ {
@ -45,41 +71,56 @@ struct ircd::json::value
int64_t integer; int64_t integer;
double floating; double floating;
const char *string; const char *string;
const struct index *object; const struct value *array;
const struct array *array; const struct member *object;
}; };
uint64_t len : 57; ///< length indicator uint64_t len : 57; ///< length indicator
enum type type : 3; ///< json::type 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 alloc : 1; ///< indicates the pointer for type is owned
uint64_t floats : 1; ///< for NUMBER type, integer or floating uint64_t floats : 1; ///< for NUMBER type, integer or floating
public: static const string_view literal_null;
bool null() const; static const string_view literal_true;
bool empty() const; static const string_view literal_false;
bool undefined() const; 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 double() const;
explicit operator int64_t() 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); template<class T> explicit value(const T &specialized);
value(const string_view &sv, const enum type &);
template<size_t N> value(const char (&)[N]); template<size_t N> value(const char (&)[N]);
value(const char *const &s); value(const char *const &s);
value(const string_view &sv, const enum type &);
value(const string_view &sv); value(const string_view &sv);
value(const index *const &); // alloc = false value(const struct member *const &, const size_t &len);
value(std::unique_ptr<index>); // alloc = true 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(value &&) noexcept; value(value &&) noexcept;
value(const value &); value(const value &);
value &operator=(value &&) noexcept; value &operator=(value &&) noexcept;
value &operator=(const value &) = delete; value &operator=(const value &);
~value() noexcept; ~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); 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 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 size_t serialized(const value &);
friend string_view stringify(mutable_buffer &, const value &); friend string_view stringify(mutable_buffer &, const value &);
friend std::ostream &operator<<(std::ostream &, const value &); friend std::ostream &operator<<(std::ostream &, const value &);
@ -107,10 +149,10 @@ static_assert(sizeof(ircd::json::value) == 16, "");
inline inline
ircd::json::value::value() ircd::json::value::value()
:string{""} :string{nullptr}
,len{0} ,len{0}
,type{STRING} ,type{STRING}
,serial{true} ,serial{false}
,alloc{false} ,alloc{false}
,floats{false} ,floats{false}
{} {}
@ -121,15 +163,93 @@ ircd::json::value::value(const string_view &sv,
:string{sv.data()} :string{sv.data()}
,len{sv.size()} ,len{sv.size()}
,type{type} ,type{type}
,serial{true} ,serial{type == STRING? surrounds(sv, '"') : true}
,alloc{false} ,alloc{false}
,floats{false} ,floats{false}
{} {}
inline 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} :object{object}
,len{0} ,len{len}
,type{OBJECT} ,type{OBJECT}
,serial{false} ,serial{false}
,alloc{false} ,alloc{false}
@ -137,9 +257,10 @@ ircd::json::value::value(const index *const &object)
{} {}
inline 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()} :object{object.get()}
,len{0} ,len{len}
,type{OBJECT} ,type{OBJECT}
,serial{false} ,serial{false}
,alloc{true} ,alloc{true}
@ -183,50 +304,6 @@ ircd::json::value::value(const int16_t &integer)
:value{int64_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 inline
ircd::json::value::value(value &&other) ircd::json::value::value(value &&other)
noexcept noexcept
@ -240,33 +317,6 @@ noexcept
other.alloc = false; 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 & inline ircd::json::value &
ircd::json::value::operator=(value &&other) ircd::json::value::operator=(value &&other)
noexcept noexcept

View file

@ -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 http::code &, const string_view &errcode, const char *const &fmt, args&&...);
template<class... args> error(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::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 &, const json::iov &);
error(const http::code &); error(const http::code &);
error(std::string = {}); error(std::string = {});
@ -83,8 +83,14 @@ ircd::m::error::error(const http::code &c)
inline inline
ircd::m::error::error(const http::code &c, ircd::m::error::error(const http::code &c,
const json::index &index) const json::members &members)
:http::error{c, std::string{index}} :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 inline
@ -111,15 +117,15 @@ ircd::m::error::error(const http::code &status,
{ {
status, [&]() -> std::string 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)...} fmt::snprintf{estr, sizeof(estr), fmt, std::forward<args>(a)...}
}; };
return json::index return json::string(json::members
{ {
{ "errcode", errcode }, { "errcode", errcode },
{ "error", string_view(estr, estr_len) } { "error", string_view(estr, estr_len) }
}; });
}() }()
}{} }{}

View file

@ -29,17 +29,18 @@ namespace ircd {
namespace m { namespace m {
struct request struct request
:json::index
{ {
string_view method; string_view method;
string_view path; string_view path;
string_view query; string_view query;
string_view access_token; string_view access_token;
std::string _content;
json::object content;
request(const string_view &method, request(const string_view &method,
const string_view &path, const string_view &path,
const string_view &query = {}, const string_view &query = {},
std::initializer_list<json::member> body = {}); json::members body = {});
request(const string_view &method, request(const string_view &method,
const string_view &path, const string_view &path,
@ -54,11 +55,12 @@ inline
ircd::m::request::request(const string_view &method, ircd::m::request::request(const string_view &method,
const string_view &path, const string_view &path,
const string_view &query, const string_view &query,
std::initializer_list<json::member> body) json::members body)
:json::index{std::move(body)} :method{method}
,method{method}
,path{path} ,path{path}
,query{query} ,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 &path,
const string_view &query, const string_view &query,
const json::object &content) const json::object &content)
:json::index{content} :method{method}
,method{method}
,path{path} ,path{path}
,query{query} ,query{query}
,content{content}
{ {
} }

View file

@ -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::db::pos>(column::const_iterator &, const pos &);
template bool ircd::db::seek<ircd::string_view>(column::const_iterator &, const string_view &); 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 // writebatch

File diff suppressed because it is too large Load diff