mirror of
https://github.com/matrix-construct/construct
synced 2025-03-24 02:10:28 +01:00
ircd::json/modules: Rename various types.
This commit is contained in:
parent
2a6527993b
commit
4fd787d9d5
18 changed files with 1030 additions and 1142 deletions
|
@ -31,11 +31,10 @@ IRCD_EXCEPTION(error, print_error);
|
|||
IRCD_EXCEPTION(error, type_error);
|
||||
IRCD_EXCEPTION(error, not_found);
|
||||
|
||||
struct doc;
|
||||
struct arr;
|
||||
|
||||
struct val;
|
||||
struct obj;
|
||||
struct array;
|
||||
struct object;
|
||||
struct value;
|
||||
struct index;
|
||||
|
||||
enum type
|
||||
{
|
||||
|
@ -51,8 +50,8 @@ enum type type(const string_view &, std::nothrow_t);
|
|||
} // namespace json
|
||||
} // namespace ircd
|
||||
|
||||
#include "json/arr.h"
|
||||
#include "json/doc.h"
|
||||
#include "json/val.h"
|
||||
#include "json/obj.h"
|
||||
#include "json/map.h"
|
||||
#include "json/array.h"
|
||||
#include "json/object.h"
|
||||
#include "json/value.h"
|
||||
#include "json/index.h"
|
||||
// #include "json/parse.h"
|
||||
|
|
|
@ -20,12 +20,12 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_JSON_ARR_H
|
||||
#define HAVE_IRCD_JSON_ARRAY_H
|
||||
|
||||
namespace ircd {
|
||||
namespace json {
|
||||
|
||||
struct arr
|
||||
struct array
|
||||
:string_view
|
||||
{
|
||||
struct const_iterator;
|
||||
|
@ -51,12 +51,12 @@ struct arr
|
|||
|
||||
using string_view::string_view;
|
||||
|
||||
friend arr serialize(const arr &, char *&buf, char *const &stop);
|
||||
friend size_t print(char *const &buf, const size_t &max, const arr &);
|
||||
friend std::ostream &operator<<(std::ostream &, const arr &);
|
||||
friend array serialize(const array &, char *&buf, char *const &stop);
|
||||
friend size_t print(char *const &buf, const size_t &max, const array &);
|
||||
friend std::ostream &operator<<(std::ostream &, const array &);
|
||||
};
|
||||
|
||||
struct arr::const_iterator
|
||||
struct array::const_iterator
|
||||
{
|
||||
using value_type = const string_view;
|
||||
using pointer = value_type *;
|
||||
|
@ -65,7 +65,7 @@ struct arr::const_iterator
|
|||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
protected:
|
||||
friend class arr;
|
||||
friend class array;
|
||||
|
||||
const char *start;
|
||||
const char *stop;
|
||||
|
@ -94,7 +94,7 @@ struct arr::const_iterator
|
|||
} // namespace ircd
|
||||
|
||||
inline ircd::string_view
|
||||
ircd::json::arr::operator[](const size_t &i)
|
||||
ircd::json::array::operator[](const size_t &i)
|
||||
const
|
||||
{
|
||||
const auto it(find(i));
|
||||
|
@ -103,7 +103,7 @@ const
|
|||
|
||||
template<class T>
|
||||
T
|
||||
ircd::json::arr::at(const size_t &i)
|
||||
ircd::json::array::at(const size_t &i)
|
||||
const try
|
||||
{
|
||||
return lex_cast<T>(at(i));
|
||||
|
@ -114,15 +114,15 @@ catch(const bad_lex_cast &e)
|
|||
}
|
||||
|
||||
inline ircd::string_view
|
||||
ircd::json::arr::at(const size_t &i)
|
||||
ircd::json::array::at(const size_t &i)
|
||||
const
|
||||
{
|
||||
const auto it(find(i));
|
||||
return likely(it != end())? *it : throw not_found("indice %zu", i);
|
||||
}
|
||||
|
||||
inline ircd::json::arr::const_iterator
|
||||
ircd::json::arr::find(size_t i)
|
||||
inline ircd::json::array::const_iterator
|
||||
ircd::json::array::find(size_t i)
|
||||
const
|
||||
{
|
||||
auto it(begin());
|
||||
|
@ -131,44 +131,44 @@ const
|
|||
}
|
||||
|
||||
inline size_t
|
||||
ircd::json::arr::count()
|
||||
ircd::json::array::count()
|
||||
const
|
||||
{
|
||||
return std::distance(begin(), end());
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator==(const arr::const_iterator &a, const arr::const_iterator &b)
|
||||
ircd::json::operator==(const array::const_iterator &a, const array::const_iterator &b)
|
||||
{
|
||||
return a.start == b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator!=(const arr::const_iterator &a, const arr::const_iterator &b)
|
||||
ircd::json::operator!=(const array::const_iterator &a, const array::const_iterator &b)
|
||||
{
|
||||
return a.start != b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<=(const arr::const_iterator &a, const arr::const_iterator &b)
|
||||
ircd::json::operator<=(const array::const_iterator &a, const array::const_iterator &b)
|
||||
{
|
||||
return a.start <= b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator>=(const arr::const_iterator &a, const arr::const_iterator &b)
|
||||
ircd::json::operator>=(const array::const_iterator &a, const array::const_iterator &b)
|
||||
{
|
||||
return a.start >= b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<(const arr::const_iterator &a, const arr::const_iterator &b)
|
||||
ircd::json::operator<(const array::const_iterator &a, const array::const_iterator &b)
|
||||
{
|
||||
return a.start < b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator>(const arr::const_iterator &a, const arr::const_iterator &b)
|
||||
ircd::json::operator>(const array::const_iterator &a, const array::const_iterator &b)
|
||||
{
|
||||
return a.start > b.start;
|
||||
}
|
|
@ -1,295 +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_DOC_H
|
||||
|
||||
namespace ircd {
|
||||
namespace json {
|
||||
|
||||
struct doc
|
||||
:string_view
|
||||
{
|
||||
struct member;
|
||||
struct 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 iterator = const_iterator;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using key_compare = std::less<member>;
|
||||
|
||||
const_iterator end() const;
|
||||
const_iterator begin() const;
|
||||
|
||||
bool has(const string_view &name) const;
|
||||
const_iterator find(const string_view &name) const;
|
||||
size_t count() const;
|
||||
|
||||
string_view at(const string_view &name) const;
|
||||
template<class T> T at(const string_view &name) const;
|
||||
string_view operator[](const string_view &name) const;
|
||||
template<class T = string_view> T get(const string_view &name, const T &def = T()) const;
|
||||
string_view get(const string_view &name, const string_view &def = {}) const;
|
||||
|
||||
explicit operator std::string() const;
|
||||
|
||||
using string_view::string_view;
|
||||
|
||||
friend doc serialize(const doc &, char *&buf, char *const &stop);
|
||||
friend size_t print(char *const &buf, const size_t &max, const doc &);
|
||||
friend std::ostream &operator<<(std::ostream &, const doc &);
|
||||
};
|
||||
|
||||
struct doc::member
|
||||
:std::pair<string_view, string_view>
|
||||
{
|
||||
member(const string_view &first = {}, const string_view &second = {})
|
||||
: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 std::ostream &operator<<(std::ostream &, const doc::member &);
|
||||
};
|
||||
|
||||
struct doc::const_iterator
|
||||
{
|
||||
using value_type = const member;
|
||||
using pointer = value_type *;
|
||||
using reference = value_type &;
|
||||
using difference_type = size_t;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
protected:
|
||||
friend class doc;
|
||||
|
||||
const char *start;
|
||||
const char *stop;
|
||||
member state;
|
||||
|
||||
const_iterator(const char *const &start, const char *const &stop)
|
||||
:start{start}
|
||||
,stop{stop}
|
||||
{}
|
||||
|
||||
public:
|
||||
value_type *operator->() const { return &state; }
|
||||
value_type &operator*() const { return *operator->(); }
|
||||
|
||||
const_iterator &operator++();
|
||||
|
||||
friend bool operator==(const const_iterator &, const const_iterator &);
|
||||
friend bool operator!=(const const_iterator &, const const_iterator &);
|
||||
friend bool operator<=(const const_iterator &, const const_iterator &);
|
||||
friend bool operator>=(const const_iterator &, const const_iterator &);
|
||||
friend bool operator<(const const_iterator &, const const_iterator &);
|
||||
friend bool operator>(const const_iterator &, const const_iterator &);
|
||||
};
|
||||
|
||||
} // namespace json
|
||||
} // namespace ircd
|
||||
|
||||
inline ircd::string_view
|
||||
ircd::json::doc::get(const string_view &name,
|
||||
const string_view &def)
|
||||
const
|
||||
{
|
||||
const string_view sv(operator[](name));
|
||||
return !sv.empty()? sv : def;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T
|
||||
ircd::json::doc::get(const string_view &name,
|
||||
const T &def)
|
||||
const try
|
||||
{
|
||||
const string_view sv(operator[](name));
|
||||
return !sv.empty()? lex_cast<T>(sv) : def;
|
||||
}
|
||||
catch(const bad_lex_cast &e)
|
||||
{
|
||||
throw type_error("'%s' must cast to type %s", name, typeid(T).name());
|
||||
}
|
||||
|
||||
inline ircd::string_view
|
||||
ircd::json::doc::operator[](const string_view &name)
|
||||
const
|
||||
{
|
||||
const auto p(split(name, '.'));
|
||||
const auto it(find(p.first));
|
||||
if(it == end())
|
||||
return {};
|
||||
|
||||
if(!p.second.empty())
|
||||
{
|
||||
const doc d(it->second);
|
||||
return d[p.second];
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T
|
||||
ircd::json::doc::at(const string_view &name)
|
||||
const try
|
||||
{
|
||||
return lex_cast<T>(at(name));
|
||||
}
|
||||
catch(const bad_lex_cast &e)
|
||||
{
|
||||
throw type_error("'%s' must cast to type %s", name, typeid(T).name());
|
||||
}
|
||||
|
||||
inline ircd::string_view
|
||||
ircd::json::doc::at(const string_view &name)
|
||||
const
|
||||
{
|
||||
const auto p(split(name, '.'));
|
||||
const auto it(find(p.first));
|
||||
if(unlikely(it == end()))
|
||||
throw not_found("'%s'", p.first);
|
||||
|
||||
if(!p.second.empty())
|
||||
{
|
||||
const doc d(it->second);
|
||||
return d.at(p.second);
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
inline ircd::json::doc::const_iterator
|
||||
ircd::json::doc::find(const string_view &name)
|
||||
const
|
||||
{
|
||||
return std::find_if(begin(), end(), [&name]
|
||||
(const auto &member)
|
||||
{
|
||||
return member.first == name;
|
||||
});
|
||||
}
|
||||
|
||||
inline size_t
|
||||
ircd::json::doc::count()
|
||||
const
|
||||
{
|
||||
return std::distance(begin(), end());
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::doc::has(const string_view &name)
|
||||
const
|
||||
{
|
||||
const auto p(split(name, '.'));
|
||||
const auto it(find(p.first));
|
||||
if(it == end())
|
||||
return false;
|
||||
|
||||
if(p.second.empty())
|
||||
return true;
|
||||
|
||||
const doc d(it->second);
|
||||
return d.has(p.second);
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator==(const doc::const_iterator &a, const doc::const_iterator &b)
|
||||
{
|
||||
return a.start == b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator!=(const doc::const_iterator &a, const doc::const_iterator &b)
|
||||
{
|
||||
return a.start != b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<=(const doc::const_iterator &a, const doc::const_iterator &b)
|
||||
{
|
||||
return a.start <= b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator>=(const doc::const_iterator &a, const doc::const_iterator &b)
|
||||
{
|
||||
return a.start >= b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<(const doc::const_iterator &a, const doc::const_iterator &b)
|
||||
{
|
||||
return a.start < b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator>(const doc::const_iterator &a, const doc::const_iterator &b)
|
||||
{
|
||||
return a.start > b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator==(const doc::member &a, const doc::member &b)
|
||||
{
|
||||
return a.first == b.first;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator!=(const doc::member &a, const doc::member &b)
|
||||
{
|
||||
return a.first != b.first;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<=(const doc::member &a, const doc::member &b)
|
||||
{
|
||||
return a.first <= b.first;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator>=(const doc::member &a, const doc::member &b)
|
||||
{
|
||||
return a.first >= b.first;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<(const doc::member &a, const doc::member &b)
|
||||
{
|
||||
return a.first < b.first;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator>(const doc::member &a, const doc::member &b)
|
||||
{
|
||||
return a.first > b.first;
|
||||
}
|
|
@ -20,25 +20,25 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_JSON_OBJ_H
|
||||
#define HAVE_IRCD_JSON_INDEX_H
|
||||
|
||||
namespace ircd {
|
||||
namespace json {
|
||||
|
||||
struct obj
|
||||
struct index
|
||||
{
|
||||
struct member;
|
||||
struct const_iterator;
|
||||
|
||||
using key_type = val;
|
||||
using mapped_type = val;
|
||||
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 = std::vector<member>;
|
||||
using index_type = std::vector<member>;
|
||||
|
||||
index idx;
|
||||
index_type idx;
|
||||
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
@ -52,8 +52,8 @@ struct obj
|
|||
const_iterator find(const string_view &name) const;
|
||||
bool has(const string_view &name) const;
|
||||
|
||||
const val &operator[](const string_view &name) const;
|
||||
const val &at(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);
|
||||
|
@ -63,28 +63,28 @@ struct obj
|
|||
|
||||
IRCD_OVERLOAD(recursive)
|
||||
|
||||
obj(std::initializer_list<member>);
|
||||
obj(const doc &d);
|
||||
obj(recursive_t, const doc &d);
|
||||
obj() = default;
|
||||
obj(obj &&) = default;
|
||||
obj(const obj &) = delete;
|
||||
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 obj &operator+=(obj &, const doc &); // integration
|
||||
friend obj operator+(const doc &, const doc &); // integral
|
||||
friend index &operator+=(index &, const object &); // integration
|
||||
friend index operator+(const object &, const object &); // integral
|
||||
|
||||
friend doc serialize(const obj &, char *&start, char *const &stop);
|
||||
friend size_t print(char *const &buf, const size_t &max, const obj &);
|
||||
friend std::ostream &operator<<(std::ostream &, const obj &);
|
||||
friend object serialize(const index &, char *&start, char *const &stop);
|
||||
friend size_t print(char *const &buf, const size_t &max, const index &);
|
||||
friend std::ostream &operator<<(std::ostream &, const index &);
|
||||
};
|
||||
|
||||
struct obj::member
|
||||
:std::pair<val, val>
|
||||
struct index::member
|
||||
:std::pair<value, value>
|
||||
{
|
||||
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 doc::member &m);
|
||||
explicit member(const object::member &m);
|
||||
member() = default;
|
||||
|
||||
friend bool operator==(const member &a, const member &b);
|
||||
|
@ -98,7 +98,7 @@ struct obj::member
|
|||
friend std::ostream &operator<<(std::ostream &, const member &);
|
||||
};
|
||||
|
||||
struct obj::const_iterator
|
||||
struct index::const_iterator
|
||||
{
|
||||
using value_type = const member;
|
||||
using pointer = value_type *;
|
||||
|
@ -107,9 +107,9 @@ struct obj::const_iterator
|
|||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
|
||||
protected:
|
||||
friend class obj;
|
||||
friend class index;
|
||||
|
||||
obj::index::const_iterator it;
|
||||
index::index_type::const_iterator it;
|
||||
|
||||
operator const auto &() const { return it; }
|
||||
|
||||
|
@ -132,62 +132,62 @@ struct obj::const_iterator
|
|||
} // namespace json
|
||||
} // namespace ircd
|
||||
|
||||
inline const ircd::json::val &
|
||||
ircd::json::obj::operator[](const string_view &name)
|
||||
inline const ircd::json::value &
|
||||
ircd::json::index::operator[](const string_view &name)
|
||||
const
|
||||
{
|
||||
return at(name);
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::obj::has(const string_view &name)
|
||||
ircd::json::index::has(const string_view &name)
|
||||
const
|
||||
{
|
||||
return find(name) != end();
|
||||
}
|
||||
|
||||
inline ircd::json::obj::const_iterator
|
||||
ircd::json::obj::find(const string_view &name)
|
||||
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::obj::count()
|
||||
ircd::json::index::count()
|
||||
const
|
||||
{
|
||||
return idx.size();
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::obj::empty()
|
||||
ircd::json::index::empty()
|
||||
const
|
||||
{
|
||||
return idx.empty();
|
||||
}
|
||||
|
||||
inline ircd::json::obj::const_iterator
|
||||
ircd::json::obj::cbegin()
|
||||
inline ircd::json::index::const_iterator
|
||||
ircd::json::index::cbegin()
|
||||
{
|
||||
return { std::begin(idx) };
|
||||
}
|
||||
|
||||
inline ircd::json::obj::const_iterator
|
||||
ircd::json::obj::cend()
|
||||
inline ircd::json::index::const_iterator
|
||||
ircd::json::index::cend()
|
||||
{
|
||||
return { std::end(idx) };
|
||||
}
|
||||
|
||||
inline ircd::json::obj::const_iterator
|
||||
ircd::json::obj::begin()
|
||||
inline ircd::json::index::const_iterator
|
||||
ircd::json::index::begin()
|
||||
const
|
||||
{
|
||||
return { std::begin(idx) };
|
||||
}
|
||||
|
||||
inline ircd::json::obj::const_iterator
|
||||
ircd::json::obj::end()
|
||||
inline ircd::json::index::const_iterator
|
||||
ircd::json::index::end()
|
||||
const
|
||||
{
|
||||
return { std::end(idx) };
|
||||
|
@ -195,89 +195,89 @@ const
|
|||
|
||||
template<class K,
|
||||
class V>
|
||||
ircd::json::obj::member::member(const K &k,
|
||||
V&& v)
|
||||
:std::pair<val, val>
|
||||
ircd::json::index::member::member(const K &k,
|
||||
V&& v)
|
||||
:std::pair<value, value>
|
||||
{
|
||||
val { k }, val { std::forward<V>(v) }
|
||||
value { k }, value { std::forward<V>(v) }
|
||||
}
|
||||
{}
|
||||
|
||||
template<class K>
|
||||
ircd::json::obj::member::member(const K &k,
|
||||
std::initializer_list<member> v)
|
||||
:std::pair<val, val>
|
||||
ircd::json::index::member::member(const K &k,
|
||||
std::initializer_list<member> v)
|
||||
:std::pair<value, value>
|
||||
{
|
||||
val { k }, val { std::make_unique<obj>(std::move(v)) }
|
||||
value { k }, value { std::make_unique<index>(std::move(v)) }
|
||||
}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::obj::member::member(const doc::member &m)
|
||||
:std::pair<val, val>
|
||||
ircd::json::index::member::member(const object::member &m)
|
||||
:std::pair<value, value>
|
||||
{
|
||||
m.first, val { m.second, type(m.second) }
|
||||
m.first, value { m.second, type(m.second) }
|
||||
}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::obj::member::member(const string_view &k)
|
||||
:std::pair<val, val>
|
||||
ircd::json::index::member::member(const string_view &k)
|
||||
:std::pair<value, value>
|
||||
{
|
||||
k, string_view{}
|
||||
}
|
||||
{}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<(const obj::member &a, const obj::member &b)
|
||||
ircd::json::operator<(const index::member &a, const index::member &b)
|
||||
{
|
||||
return a.first < b.first;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator!=(const obj::member &a, const obj::member &b)
|
||||
ircd::json::operator!=(const index::member &a, const index::member &b)
|
||||
{
|
||||
return a.first != b.first;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator==(const obj::member &a, const obj::member &b)
|
||||
ircd::json::operator==(const index::member &a, const index::member &b)
|
||||
{
|
||||
return a.first == b.first;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<(const obj::member &a, const string_view &b)
|
||||
ircd::json::operator<(const index::member &a, const string_view &b)
|
||||
{
|
||||
return string_view(a.first.string, a.first.len) < b;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator!=(const obj::member &a, const string_view &b)
|
||||
ircd::json::operator!=(const index::member &a, const string_view &b)
|
||||
{
|
||||
return string_view(a.first.string, a.first.len) != b;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator==(const obj::member &a, const string_view &b)
|
||||
ircd::json::operator==(const index::member &a, const string_view &b)
|
||||
{
|
||||
return string_view(a.first.string, a.first.len) == b;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<(const obj::const_iterator &a, const obj::const_iterator &b)
|
||||
ircd::json::operator<(const index::const_iterator &a, const index::const_iterator &b)
|
||||
{
|
||||
return a.it < b.it;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator!=(const obj::const_iterator &a, const obj::const_iterator &b)
|
||||
ircd::json::operator!=(const index::const_iterator &a, const index::const_iterator &b)
|
||||
{
|
||||
return a.it != b.it;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator==(const obj::const_iterator &a, const obj::const_iterator &b)
|
||||
ircd::json::operator==(const index::const_iterator &a, const index::const_iterator &b)
|
||||
{
|
||||
return a.it == b.it;
|
||||
}
|
|
@ -1,170 +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_MAP_H
|
||||
|
||||
namespace ircd {
|
||||
namespace json {
|
||||
|
||||
struct map
|
||||
{
|
||||
struct const_iterator;
|
||||
|
||||
using key_type = string_view;
|
||||
using mapped_type = std::string;
|
||||
using value_type = std::pair<key_type, mapped_type>;
|
||||
using pointer = value_type *;
|
||||
using reference = value_type &;
|
||||
using size_type = size_t;
|
||||
using difference_type = size_t;
|
||||
|
||||
std::map<std::string, std::string, std::less<>> idx;
|
||||
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
const_iterator cbegin();
|
||||
const_iterator cend();
|
||||
|
||||
bool empty() const;
|
||||
size_t size() const;
|
||||
|
||||
const_iterator find(const string_view &name) const;
|
||||
bool has(const string_view &name) const;
|
||||
|
||||
const val &operator[](const string_view &name) const;
|
||||
const val &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);
|
||||
|
||||
map(const doc &d);
|
||||
map() = default;
|
||||
|
||||
friend doc serialize(const map &, char *&start, char *const &stop);
|
||||
friend size_t print(char *const &buf, const size_t &max, const map &);
|
||||
friend std::ostream &operator<<(std::ostream &, const map &);
|
||||
};
|
||||
|
||||
struct map::const_iterator
|
||||
{
|
||||
using value_type = map::value_type;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
|
||||
protected:
|
||||
friend class map;
|
||||
|
||||
decltype(map::idx)::const_iterator it;
|
||||
mutable value_type val;
|
||||
|
||||
operator const auto &() const { return it; }
|
||||
|
||||
const_iterator(const decltype(it) &it)
|
||||
:it{it}
|
||||
{}
|
||||
|
||||
public:
|
||||
value_type *operator->() const { return &val; }
|
||||
value_type &operator*() const { return val; }
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
} // namespace json
|
||||
} // namespace ircd
|
||||
|
||||
inline const ircd::json::val &
|
||||
ircd::json::map::operator[](const string_view &name)
|
||||
const
|
||||
{
|
||||
return at(name);
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::map::has(const string_view &name)
|
||||
const
|
||||
{
|
||||
return find(name) != end();
|
||||
}
|
||||
|
||||
inline ircd::json::map::const_iterator
|
||||
ircd::json::map::find(const string_view &name)
|
||||
const
|
||||
{
|
||||
return std::end(idx);
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::map::empty()
|
||||
const
|
||||
{
|
||||
return idx.empty();
|
||||
}
|
||||
|
||||
inline ircd::json::map::const_iterator
|
||||
ircd::json::map::cbegin()
|
||||
{
|
||||
return { std::begin(idx) };
|
||||
}
|
||||
|
||||
inline ircd::json::map::const_iterator
|
||||
ircd::json::map::cend()
|
||||
{
|
||||
return { std::end(idx) };
|
||||
}
|
||||
|
||||
inline ircd::json::map::const_iterator
|
||||
ircd::json::map::begin()
|
||||
const
|
||||
{
|
||||
return { std::begin(idx) };
|
||||
}
|
||||
|
||||
inline ircd::json::map::const_iterator
|
||||
ircd::json::map::end()
|
||||
const
|
||||
{
|
||||
return { std::end(idx) };
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<(const map::const_iterator &a, const map::const_iterator &b)
|
||||
{
|
||||
return a.it < b.it;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator!=(const map::const_iterator &a, const map::const_iterator &b)
|
||||
{
|
||||
return a.it != b.it;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator==(const map::const_iterator &a, const map::const_iterator &b)
|
||||
{
|
||||
return a.it == b.it;
|
||||
}
|
|
@ -20,357 +20,276 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_JSON_REFLECT_H
|
||||
|
||||
#define IRCD_MEMBERS(_name_, _vals_...) \
|
||||
static constexpr const char *_member_(const size_t i) \
|
||||
{ \
|
||||
constexpr const char *const val[] \
|
||||
{ \
|
||||
_vals_ \
|
||||
}; \
|
||||
\
|
||||
return val[i]; \
|
||||
}
|
||||
#define HAVE_IRCD_JSON_OBJECT_H
|
||||
|
||||
namespace ircd {
|
||||
namespace json {
|
||||
|
||||
struct basic_object
|
||||
{
|
||||
};
|
||||
|
||||
template<class... T>
|
||||
struct object
|
||||
:basic_object
|
||||
,std::tuple<T...>
|
||||
:string_view
|
||||
{
|
||||
using tuple_type = std::tuple<T...>;
|
||||
struct member;
|
||||
struct const_iterator;
|
||||
|
||||
static constexpr size_t size()
|
||||
{
|
||||
return std::tuple_size<tuple_type>();
|
||||
}
|
||||
using key_type = string_view;
|
||||
using mapped_type = string_view;
|
||||
using value_type = const member;
|
||||
using pointer = value_type *;
|
||||
using reference = value_type &;
|
||||
using iterator = const_iterator;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using key_compare = std::less<member>;
|
||||
|
||||
using std::tuple<T...>::tuple;
|
||||
const_iterator end() const;
|
||||
const_iterator begin() const;
|
||||
|
||||
bool has(const string_view &name) const;
|
||||
const_iterator find(const string_view &name) const;
|
||||
size_t count() const;
|
||||
|
||||
string_view at(const string_view &name) const;
|
||||
template<class T> T at(const string_view &name) const;
|
||||
string_view operator[](const string_view &name) const;
|
||||
template<class T = string_view> T get(const string_view &name, const T &def = T()) const;
|
||||
string_view get(const string_view &name, const string_view &def = {}) const;
|
||||
|
||||
explicit operator std::string() const;
|
||||
|
||||
using string_view::string_view;
|
||||
|
||||
friend object serialize(const object &, char *&buf, char *const &stop);
|
||||
friend size_t print(char *const &buf, const size_t &max, const object &);
|
||||
friend std::ostream &operator<<(std::ostream &, const object &);
|
||||
};
|
||||
|
||||
template<class object>
|
||||
using tuple_type = typename object::tuple_type;
|
||||
|
||||
template<class object>
|
||||
using tuple_size = std::tuple_size<tuple_type<object>>;
|
||||
|
||||
template<size_t i,
|
||||
class object>
|
||||
using tuple_element = typename std::tuple_element<i, tuple_type<object>>::type;
|
||||
|
||||
template<class object>
|
||||
constexpr auto &
|
||||
tuple(const object &o)
|
||||
struct object::member
|
||||
:std::pair<string_view, string_view>
|
||||
{
|
||||
return static_cast<const typename object::tuple_type &>(o);
|
||||
}
|
||||
member(const string_view &first = {}, const string_view &second = {})
|
||||
:std::pair<string_view, string_view>{first, second}
|
||||
{}
|
||||
|
||||
template<class object>
|
||||
constexpr auto &
|
||||
tuple(object &o)
|
||||
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 std::ostream &operator<<(std::ostream &, const object::member &);
|
||||
};
|
||||
|
||||
struct object::const_iterator
|
||||
{
|
||||
return static_cast<typename object::tuple_type &>(o);
|
||||
}
|
||||
using value_type = const member;
|
||||
using pointer = value_type *;
|
||||
using reference = value_type &;
|
||||
using difference_type = size_t;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
template<class... T>
|
||||
constexpr auto
|
||||
size(const object<T...> &t)
|
||||
{
|
||||
return t.size();
|
||||
}
|
||||
protected:
|
||||
friend class object;
|
||||
|
||||
template<size_t i,
|
||||
class... T>
|
||||
constexpr auto &
|
||||
get(const object<T...> &t)
|
||||
{
|
||||
return std::get<i>(t);
|
||||
}
|
||||
const char *start;
|
||||
const char *stop;
|
||||
member state;
|
||||
|
||||
template<size_t i,
|
||||
class... T>
|
||||
constexpr auto &
|
||||
get(object<T...> &t)
|
||||
{
|
||||
return std::get<i>(t);
|
||||
}
|
||||
const_iterator(const char *const &start, const char *const &stop)
|
||||
:start{start}
|
||||
,stop{stop}
|
||||
{}
|
||||
|
||||
template<size_t i,
|
||||
class object>
|
||||
constexpr const char *
|
||||
reflect(const object &t)
|
||||
{
|
||||
return t._member_(i);
|
||||
}
|
||||
public:
|
||||
value_type *operator->() const { return &state; }
|
||||
value_type &operator*() const { return *operator->(); }
|
||||
|
||||
template<size_t i,
|
||||
class object,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i == tuple_size<object>::value, void>::type
|
||||
for_each(const object &t,
|
||||
function&& f)
|
||||
{}
|
||||
const_iterator &operator++();
|
||||
|
||||
template<size_t i,
|
||||
class object,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i == tuple_size<object>::value, void>::type
|
||||
for_each(object &t,
|
||||
function&& f)
|
||||
{}
|
||||
|
||||
template<size_t i = 0,
|
||||
class object,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<object>::value, void>::type
|
||||
for_each(const object &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, object>;
|
||||
|
||||
f(reflect<i>(t), static_cast<const type &>(get<i>(t)));
|
||||
for_each<i + 1>(t, std::forward<function>(f));
|
||||
}
|
||||
|
||||
template<size_t i = 0,
|
||||
class object,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<object>::value, void>::type
|
||||
for_each(object &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, object>;
|
||||
|
||||
f(reflect<i>(t), static_cast<type &>(get<i>(t)));
|
||||
for_each<i + 1>(t, std::forward<function>(f));
|
||||
}
|
||||
|
||||
template<class object,
|
||||
class function,
|
||||
ssize_t i>
|
||||
constexpr
|
||||
typename std::enable_if<(i < 0), void>::type
|
||||
rfor_each(const object &t,
|
||||
function&& f)
|
||||
{}
|
||||
|
||||
template<class object,
|
||||
class function,
|
||||
ssize_t i>
|
||||
constexpr
|
||||
typename std::enable_if<(i < 0), void>::type
|
||||
rfor_each(object &t,
|
||||
function&& f)
|
||||
{}
|
||||
|
||||
template<class object,
|
||||
class function,
|
||||
ssize_t i = tuple_size<object>() - 1>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<object>(), void>::type
|
||||
rfor_each(const object &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, object>;
|
||||
|
||||
f(reflect<i>(t), static_cast<const type &>(get<i>(t)));
|
||||
rfor_each<object, function, i - 1>(t, std::forward<function>(f));
|
||||
}
|
||||
|
||||
template<class object,
|
||||
class function,
|
||||
ssize_t i = tuple_size<object>() - 1>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<object>(), void>::type
|
||||
rfor_each(object &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, object>;
|
||||
|
||||
f(reflect<i>(t), static_cast<type &>(get<i>(t)));
|
||||
rfor_each<object, function, i - 1>(t, std::forward<function>(f));
|
||||
}
|
||||
|
||||
template<size_t i,
|
||||
class object,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i == tuple_size<object>::value, bool>::type
|
||||
until(const object &t,
|
||||
function&& f)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<size_t i,
|
||||
class object,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i == tuple_size<object>::value, bool>::type
|
||||
until(object &t,
|
||||
function&& f)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<size_t i = 0,
|
||||
class object,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<object>::value, bool>::type
|
||||
until(const object &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, object>;
|
||||
|
||||
const auto &value(static_cast<const type &>(get<i>(t)));
|
||||
return f(reflect<i>(t), value)?
|
||||
until<i + 1>(t, std::forward<function>(f)):
|
||||
false;
|
||||
}
|
||||
|
||||
template<size_t i = 0,
|
||||
class object,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<object>::value, bool>::type
|
||||
until(object &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, object>;
|
||||
|
||||
auto &value(static_cast<type &>(get<i>(t)));
|
||||
return f(reflect<i>(t), value)?
|
||||
until<i + 1>(t, std::forward<function>(f)):
|
||||
false;
|
||||
}
|
||||
|
||||
template<class object,
|
||||
class function,
|
||||
ssize_t i>
|
||||
constexpr
|
||||
typename std::enable_if<(i < 0), bool>::type
|
||||
runtil(const object &t,
|
||||
function&& f)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class object,
|
||||
class function,
|
||||
ssize_t i>
|
||||
constexpr
|
||||
typename std::enable_if<(i < 0), bool>::type
|
||||
runtil(object &t,
|
||||
function&& f)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class object,
|
||||
class function,
|
||||
ssize_t i = tuple_size<object>() - 1>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<object>::value, bool>::type
|
||||
runtil(const object &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, object>;
|
||||
|
||||
const auto &value(static_cast<const type &>(get<i>(t)));
|
||||
return f(reflect<i>(t), value)?
|
||||
runtil<object, function, i - 1>(t, std::forward<function>(f)):
|
||||
false;
|
||||
}
|
||||
|
||||
template<class object,
|
||||
class function,
|
||||
ssize_t i = tuple_size<object>() - 1>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<object>::value, bool>::type
|
||||
runtil(object &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, object>;
|
||||
|
||||
auto &value(static_cast<type &>(get<i>(t)));
|
||||
return f(reflect<i>(t), value)?
|
||||
runtil<object, function, i - 1>(t, std::forward<function>(f)):
|
||||
false;
|
||||
}
|
||||
|
||||
template<class object>
|
||||
constexpr size_t
|
||||
index(object&& t,
|
||||
const string_view &name)
|
||||
{
|
||||
size_t ret(0);
|
||||
const auto res(until(t, [&ret, &name]
|
||||
(const string_view &key, auto&& member)
|
||||
{
|
||||
if(key == name)
|
||||
return false;
|
||||
|
||||
++ret;
|
||||
return true;
|
||||
}));
|
||||
|
||||
return !res? ret : throw std::out_of_range("Object has no member with that name");
|
||||
}
|
||||
|
||||
template<class object,
|
||||
class function>
|
||||
constexpr bool
|
||||
at(object&& t,
|
||||
const string_view &name,
|
||||
function&& f)
|
||||
{
|
||||
return until(t, [&name, &f]
|
||||
(const string_view &key, auto&& member)
|
||||
{
|
||||
if(key != name)
|
||||
return true;
|
||||
|
||||
f(member);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
template<class object>
|
||||
constexpr void
|
||||
keys(object&& t,
|
||||
const std::function<void (string_view)> &f)
|
||||
{
|
||||
for_each(t, [&f]
|
||||
(const char *const key, auto&& member)
|
||||
{
|
||||
f(key);
|
||||
});
|
||||
}
|
||||
|
||||
template<class object,
|
||||
class function>
|
||||
constexpr void
|
||||
values(object&& t,
|
||||
function&& f)
|
||||
{
|
||||
for_each(t, [&f]
|
||||
(const char *const key, auto&& member)
|
||||
{
|
||||
f(member);
|
||||
});
|
||||
}
|
||||
friend bool operator==(const const_iterator &, const const_iterator &);
|
||||
friend bool operator!=(const const_iterator &, const const_iterator &);
|
||||
friend bool operator<=(const const_iterator &, const const_iterator &);
|
||||
friend bool operator>=(const const_iterator &, const const_iterator &);
|
||||
friend bool operator<(const const_iterator &, const const_iterator &);
|
||||
friend bool operator>(const const_iterator &, const const_iterator &);
|
||||
};
|
||||
|
||||
} // namespace json
|
||||
} // namespace ircd
|
||||
|
||||
inline ircd::string_view
|
||||
ircd::json::object::get(const string_view &name,
|
||||
const string_view &def)
|
||||
const
|
||||
{
|
||||
const string_view sv(operator[](name));
|
||||
return !sv.empty()? sv : def;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T
|
||||
ircd::json::object::get(const string_view &name,
|
||||
const T &def)
|
||||
const try
|
||||
{
|
||||
const string_view sv(operator[](name));
|
||||
return !sv.empty()? lex_cast<T>(sv) : def;
|
||||
}
|
||||
catch(const bad_lex_cast &e)
|
||||
{
|
||||
throw type_error("'%s' must cast to type %s", name, typeid(T).name());
|
||||
}
|
||||
|
||||
inline ircd::string_view
|
||||
ircd::json::object::operator[](const string_view &name)
|
||||
const
|
||||
{
|
||||
const auto p(split(name, '.'));
|
||||
const auto it(find(p.first));
|
||||
if(it == end())
|
||||
return {};
|
||||
|
||||
if(!p.second.empty())
|
||||
{
|
||||
const object d(it->second);
|
||||
return d[p.second];
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T
|
||||
ircd::json::object::at(const string_view &name)
|
||||
const try
|
||||
{
|
||||
return lex_cast<T>(at(name));
|
||||
}
|
||||
catch(const bad_lex_cast &e)
|
||||
{
|
||||
throw type_error("'%s' must cast to type %s", name, typeid(T).name());
|
||||
}
|
||||
|
||||
inline ircd::string_view
|
||||
ircd::json::object::at(const string_view &name)
|
||||
const
|
||||
{
|
||||
const auto p(split(name, '.'));
|
||||
const auto it(find(p.first));
|
||||
if(unlikely(it == end()))
|
||||
throw not_found("'%s'", p.first);
|
||||
|
||||
if(!p.second.empty())
|
||||
{
|
||||
const object d(it->second);
|
||||
return d.at(p.second);
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
inline ircd::json::object::const_iterator
|
||||
ircd::json::object::find(const string_view &name)
|
||||
const
|
||||
{
|
||||
return std::find_if(begin(), end(), [&name]
|
||||
(const auto &member)
|
||||
{
|
||||
return member.first == name;
|
||||
});
|
||||
}
|
||||
|
||||
inline size_t
|
||||
ircd::json::object::count()
|
||||
const
|
||||
{
|
||||
return std::distance(begin(), end());
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::object::has(const string_view &name)
|
||||
const
|
||||
{
|
||||
const auto p(split(name, '.'));
|
||||
const auto it(find(p.first));
|
||||
if(it == end())
|
||||
return false;
|
||||
|
||||
if(p.second.empty())
|
||||
return true;
|
||||
|
||||
const object d(it->second);
|
||||
return d.has(p.second);
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator==(const object::const_iterator &a, const object::const_iterator &b)
|
||||
{
|
||||
return a.start == b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator!=(const object::const_iterator &a, const object::const_iterator &b)
|
||||
{
|
||||
return a.start != b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<=(const object::const_iterator &a, const object::const_iterator &b)
|
||||
{
|
||||
return a.start <= b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator>=(const object::const_iterator &a, const object::const_iterator &b)
|
||||
{
|
||||
return a.start >= b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<(const object::const_iterator &a, const object::const_iterator &b)
|
||||
{
|
||||
return a.start < b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator>(const object::const_iterator &a, const object::const_iterator &b)
|
||||
{
|
||||
return a.start > b.start;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator==(const object::member &a, const object::member &b)
|
||||
{
|
||||
return a.first == b.first;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator!=(const object::member &a, const object::member &b)
|
||||
{
|
||||
return a.first != b.first;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<=(const object::member &a, const object::member &b)
|
||||
{
|
||||
return a.first <= b.first;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator>=(const object::member &a, const object::member &b)
|
||||
{
|
||||
return a.first >= b.first;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator<(const object::member &a, const object::member &b)
|
||||
{
|
||||
return a.first < b.first;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::json::operator>(const object::member &a, const object::member &b)
|
||||
{
|
||||
return a.first > b.first;
|
||||
}
|
||||
|
|
402
include/ircd/json/parse.h
Normal file
402
include/ircd/json/parse.h
Normal file
|
@ -0,0 +1,402 @@
|
|||
/*
|
||||
* 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_PARSE_H
|
||||
|
||||
#define IRCD_MEMBERS(_vals_...) \
|
||||
static constexpr const char *_member_(const size_t i) \
|
||||
{ \
|
||||
constexpr const char *const val[] \
|
||||
{ \
|
||||
_vals_ \
|
||||
}; \
|
||||
\
|
||||
return val[i]; \
|
||||
}
|
||||
|
||||
namespace ircd {
|
||||
namespace json {
|
||||
|
||||
struct basic_parse
|
||||
{
|
||||
};
|
||||
|
||||
template<class... T>
|
||||
struct parse
|
||||
:basic_parse
|
||||
,std::tuple<T...>
|
||||
{
|
||||
using tuple_type = std::tuple<T...>;
|
||||
|
||||
static constexpr size_t size()
|
||||
{
|
||||
return std::tuple_size<tuple_type>();
|
||||
}
|
||||
|
||||
template<class R> parse(R &r, const json::object &obj);
|
||||
};
|
||||
|
||||
template<class... T>
|
||||
template<class R>
|
||||
parse<T...>::parse(R &r,
|
||||
const json::object &object)
|
||||
{
|
||||
std::for_each(std::begin(object), std::end(object), [this, &r]
|
||||
(auto &&member)
|
||||
{
|
||||
at(r, member.first, [&member]
|
||||
(auto&& target)
|
||||
{
|
||||
using target_type = decltype(target);
|
||||
using cast_type = typename std::remove_reference<target_type>::type; try
|
||||
{
|
||||
target = lex_cast<cast_type>(member.second);
|
||||
}
|
||||
catch(const bad_lex_cast &e)
|
||||
{
|
||||
throw parse_error("member \"%s\" must convert to '%s'",
|
||||
member.first,
|
||||
typeid(target_type).name());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
template<class parse>
|
||||
using tuple_type = typename parse::tuple_type;
|
||||
|
||||
template<class parse>
|
||||
using tuple_size = std::tuple_size<tuple_type<parse>>;
|
||||
|
||||
template<size_t i,
|
||||
class parse>
|
||||
using tuple_element = typename std::tuple_element<i, tuple_type<parse>>::type;
|
||||
|
||||
template<class parse>
|
||||
constexpr auto &
|
||||
tuple(const parse &o)
|
||||
{
|
||||
return static_cast<const typename parse::tuple_type &>(o);
|
||||
}
|
||||
|
||||
template<class parse>
|
||||
constexpr auto &
|
||||
tuple(parse &o)
|
||||
{
|
||||
return static_cast<typename parse::tuple_type &>(o);
|
||||
}
|
||||
|
||||
template<class... T>
|
||||
constexpr auto
|
||||
size(const parse<T...> &t)
|
||||
{
|
||||
return t.size();
|
||||
}
|
||||
|
||||
template<size_t i,
|
||||
class... T>
|
||||
constexpr auto &
|
||||
get(const parse<T...> &t)
|
||||
{
|
||||
return std::get<i>(t);
|
||||
}
|
||||
|
||||
template<size_t i,
|
||||
class... T>
|
||||
constexpr auto &
|
||||
get(parse<T...> &t)
|
||||
{
|
||||
return std::get<i>(t);
|
||||
}
|
||||
|
||||
template<size_t i,
|
||||
class parse>
|
||||
constexpr const char *
|
||||
reflect(const parse &t)
|
||||
{
|
||||
return t._member_(i);
|
||||
}
|
||||
|
||||
template<size_t i,
|
||||
class parse,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i == tuple_size<parse>::value, void>::type
|
||||
for_each(const parse &t,
|
||||
function&& f)
|
||||
{}
|
||||
|
||||
template<size_t i,
|
||||
class parse,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i == tuple_size<parse>::value, void>::type
|
||||
for_each(parse &t,
|
||||
function&& f)
|
||||
{}
|
||||
|
||||
template<size_t i = 0,
|
||||
class parse,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<parse>::value, void>::type
|
||||
for_each(const parse &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, parse>;
|
||||
|
||||
f(reflect<i>(t), static_cast<const type &>(get<i>(t)));
|
||||
for_each<i + 1>(t, std::forward<function>(f));
|
||||
}
|
||||
|
||||
template<size_t i = 0,
|
||||
class parse,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<parse>::value, void>::type
|
||||
for_each(parse &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, parse>;
|
||||
|
||||
f(reflect<i>(t), static_cast<type &>(get<i>(t)));
|
||||
for_each<i + 1>(t, std::forward<function>(f));
|
||||
}
|
||||
|
||||
template<class parse,
|
||||
class function,
|
||||
ssize_t i>
|
||||
constexpr
|
||||
typename std::enable_if<(i < 0), void>::type
|
||||
rfor_each(const parse &t,
|
||||
function&& f)
|
||||
{}
|
||||
|
||||
template<class parse,
|
||||
class function,
|
||||
ssize_t i>
|
||||
constexpr
|
||||
typename std::enable_if<(i < 0), void>::type
|
||||
rfor_each(parse &t,
|
||||
function&& f)
|
||||
{}
|
||||
|
||||
template<class parse,
|
||||
class function,
|
||||
ssize_t i = tuple_size<parse>() - 1>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<parse>(), void>::type
|
||||
rfor_each(const parse &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, parse>;
|
||||
|
||||
f(reflect<i>(t), static_cast<const type &>(get<i>(t)));
|
||||
rfor_each<parse, function, i - 1>(t, std::forward<function>(f));
|
||||
}
|
||||
|
||||
template<class parse,
|
||||
class function,
|
||||
ssize_t i = tuple_size<parse>() - 1>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<parse>(), void>::type
|
||||
rfor_each(parse &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, parse>;
|
||||
|
||||
f(reflect<i>(t), static_cast<type &>(get<i>(t)));
|
||||
rfor_each<parse, function, i - 1>(t, std::forward<function>(f));
|
||||
}
|
||||
|
||||
template<size_t i,
|
||||
class parse,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i == tuple_size<parse>::value, bool>::type
|
||||
until(const parse &t,
|
||||
function&& f)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<size_t i,
|
||||
class parse,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i == tuple_size<parse>::value, bool>::type
|
||||
until(parse &t,
|
||||
function&& f)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<size_t i = 0,
|
||||
class parse,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<parse>::value, bool>::type
|
||||
until(const parse &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, parse>;
|
||||
|
||||
const auto &value(static_cast<const type &>(get<i>(t)));
|
||||
return f(reflect<i>(t), value)?
|
||||
until<i + 1>(t, std::forward<function>(f)):
|
||||
false;
|
||||
}
|
||||
|
||||
template<size_t i = 0,
|
||||
class parse,
|
||||
class function>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<parse>::value, bool>::type
|
||||
until(parse &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, parse>;
|
||||
|
||||
auto &value(static_cast<type &>(get<i>(t)));
|
||||
return f(reflect<i>(t), value)?
|
||||
until<i + 1>(t, std::forward<function>(f)):
|
||||
false;
|
||||
}
|
||||
|
||||
template<class parse,
|
||||
class function,
|
||||
ssize_t i>
|
||||
constexpr
|
||||
typename std::enable_if<(i < 0), bool>::type
|
||||
runtil(const parse &t,
|
||||
function&& f)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class parse,
|
||||
class function,
|
||||
ssize_t i>
|
||||
constexpr
|
||||
typename std::enable_if<(i < 0), bool>::type
|
||||
runtil(parse &t,
|
||||
function&& f)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class parse,
|
||||
class function,
|
||||
ssize_t i = tuple_size<parse>() - 1>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<parse>::value, bool>::type
|
||||
runtil(const parse &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, parse>;
|
||||
|
||||
const auto &value(static_cast<const type &>(get<i>(t)));
|
||||
return f(reflect<i>(t), value)?
|
||||
runtil<parse, function, i - 1>(t, std::forward<function>(f)):
|
||||
false;
|
||||
}
|
||||
|
||||
template<class parse,
|
||||
class function,
|
||||
ssize_t i = tuple_size<parse>() - 1>
|
||||
constexpr
|
||||
typename std::enable_if<i < tuple_size<parse>::value, bool>::type
|
||||
runtil(parse &t,
|
||||
function&& f)
|
||||
{
|
||||
using type = tuple_element<i, parse>;
|
||||
|
||||
auto &value(static_cast<type &>(get<i>(t)));
|
||||
return f(reflect<i>(t), value)?
|
||||
runtil<parse, function, i - 1>(t, std::forward<function>(f)):
|
||||
false;
|
||||
}
|
||||
|
||||
template<class parse>
|
||||
constexpr size_t
|
||||
indexof(parse&& t,
|
||||
const string_view &name)
|
||||
{
|
||||
size_t ret(0);
|
||||
const auto res(until(t, [&ret, &name]
|
||||
(const string_view &key, auto&& member)
|
||||
{
|
||||
if(key == name)
|
||||
return false;
|
||||
|
||||
++ret;
|
||||
return true;
|
||||
}));
|
||||
|
||||
return !res? ret : throw std::out_of_range("parse has no member with that name");
|
||||
}
|
||||
|
||||
template<class parse,
|
||||
class function>
|
||||
constexpr bool
|
||||
at(parse&& t,
|
||||
const string_view &name,
|
||||
function&& f)
|
||||
{
|
||||
return until(t, [&name, &f]
|
||||
(const string_view &key, auto&& member)
|
||||
{
|
||||
if(key != name)
|
||||
return true;
|
||||
|
||||
f(member);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
template<class parse>
|
||||
constexpr void
|
||||
keys(parse&& t,
|
||||
const std::function<void (string_view)> &f)
|
||||
{
|
||||
for_each(t, [&f]
|
||||
(const char *const key, auto&& member)
|
||||
{
|
||||
f(key);
|
||||
});
|
||||
}
|
||||
|
||||
template<class parse,
|
||||
class function>
|
||||
constexpr void
|
||||
values(parse&& t,
|
||||
function&& f)
|
||||
{
|
||||
for_each(t, [&f]
|
||||
(const char *const key, auto&& member)
|
||||
{
|
||||
f(member);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace json
|
||||
} // namespace ircd
|
|
@ -20,19 +20,19 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_JSON_VAL_H
|
||||
#define HAVE_IRCD_JSON_VALUE_H
|
||||
|
||||
namespace ircd {
|
||||
namespace json {
|
||||
|
||||
struct val
|
||||
struct value
|
||||
{
|
||||
union // xxx std::variant
|
||||
{
|
||||
int64_t integer;
|
||||
double floating;
|
||||
const char *string;
|
||||
const struct obj *object;
|
||||
const struct index *object;
|
||||
const struct array *array;
|
||||
};
|
||||
|
||||
|
@ -48,43 +48,43 @@ struct val
|
|||
operator string_view() const;
|
||||
explicit operator std::string() const;
|
||||
|
||||
template<class T> explicit val(const T &specialized);
|
||||
template<size_t N> val(const char (&)[N]);
|
||||
val(const string_view &sv, const enum type &);
|
||||
val(const string_view &sv);
|
||||
val(const char *const &s);
|
||||
val(const struct obj *const &); // alloc = false
|
||||
val(std::unique_ptr<obj>); // alloc = true
|
||||
val();
|
||||
val(val &&) noexcept;
|
||||
val(const val &) = delete;
|
||||
val &operator=(val &&) noexcept;
|
||||
val &operator=(const val &) = delete;
|
||||
~val() noexcept;
|
||||
template<class T> explicit value(const T &specialized);
|
||||
template<size_t N> value(const char (&)[N]);
|
||||
value(const string_view &sv, const enum type &);
|
||||
value(const string_view &sv);
|
||||
value(const char *const &s);
|
||||
value(const struct index *const &); // alloc = false
|
||||
value(std::unique_ptr<struct index>); // alloc = true
|
||||
value();
|
||||
value(value &&) noexcept;
|
||||
value(const value &) = delete;
|
||||
value &operator=(value &&) noexcept;
|
||||
value &operator=(const value &) = delete;
|
||||
~value() noexcept;
|
||||
|
||||
friend enum type type(const val &a);
|
||||
friend bool operator==(const val &a, const val &b);
|
||||
friend bool operator!=(const val &a, const val &b);
|
||||
friend bool operator<=(const val &a, const val &b);
|
||||
friend bool operator>=(const val &a, const val &b);
|
||||
friend bool operator<(const val &a, const val &b);
|
||||
friend bool operator>(const val &a, const val &b);
|
||||
friend std::ostream &operator<<(std::ostream &, const val &);
|
||||
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);
|
||||
friend std::ostream &operator<<(std::ostream &, const value &);
|
||||
};
|
||||
template<> val::val(const double &floating);
|
||||
template<> val::val(const int64_t &integer);
|
||||
template<> inline val::val(const float &floating): val { double(floating) } {}
|
||||
template<> inline val::val(const int32_t &integer): val { int64_t(integer) } {}
|
||||
template<> inline val::val(const int16_t &integer): val { int64_t(integer) } {}
|
||||
template<> inline val::val(const std::string &str): val { string_view{str} } {}
|
||||
template<> value::value(const double &floating);
|
||||
template<> value::value(const int64_t &integer);
|
||||
template<> value::value(const float &floating);
|
||||
template<> value::value(const int32_t &integer);
|
||||
template<> value::value(const int16_t &integer);
|
||||
template<> value::value(const std::string &str);
|
||||
|
||||
static_assert(sizeof(val) == 16, "");
|
||||
static_assert(sizeof(value) == 16, "");
|
||||
|
||||
} // namespace json
|
||||
} // namespace ircd
|
||||
|
||||
inline
|
||||
ircd::json::val::val()
|
||||
ircd::json::value::value()
|
||||
:string{""}
|
||||
,len{0}
|
||||
,type{STRING}
|
||||
|
@ -93,24 +93,9 @@ ircd::json::val::val()
|
|||
,floats{false}
|
||||
{}
|
||||
|
||||
template<size_t N>
|
||||
ircd::json::val::val(const char (&str)[N])
|
||||
:val{string_view{str}}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::val::val(const char *const &s)
|
||||
:val{string_view{s}}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::val::val(const string_view &sv)
|
||||
:val{sv, json::type(sv, std::nothrow)}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::val::val(const string_view &sv,
|
||||
const enum type &type)
|
||||
ircd::json::value::value(const string_view &sv,
|
||||
const enum type &type)
|
||||
:string{sv.data()}
|
||||
,len{sv.size()}
|
||||
,type{type}
|
||||
|
@ -119,28 +104,8 @@ ircd::json::val::val(const string_view &sv,
|
|||
,floats{false}
|
||||
{}
|
||||
|
||||
template<> inline
|
||||
ircd::json::val::val(const int64_t &integer)
|
||||
:integer{integer}
|
||||
,len{0}
|
||||
,type{NUMBER}
|
||||
,serial{false}
|
||||
,alloc{false}
|
||||
,floats{false}
|
||||
{}
|
||||
|
||||
template<> inline
|
||||
ircd::json::val::val(const double &floating)
|
||||
:floating{floating}
|
||||
,len{0}
|
||||
,type{NUMBER}
|
||||
,serial{false}
|
||||
,alloc{false}
|
||||
,floats{true}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::val::val(const struct obj *const &object)
|
||||
ircd::json::value::value(const struct index *const &object)
|
||||
:object{object}
|
||||
,len{0}
|
||||
,type{OBJECT}
|
||||
|
@ -150,7 +115,7 @@ ircd::json::val::val(const struct obj *const &object)
|
|||
{}
|
||||
|
||||
inline
|
||||
ircd::json::val::val(std::unique_ptr<obj> object)
|
||||
ircd::json::value::value(std::unique_ptr<struct index> object)
|
||||
:object{object.get()}
|
||||
,len{0}
|
||||
,type{OBJECT}
|
||||
|
@ -161,8 +126,63 @@ ircd::json::val::val(std::unique_ptr<obj> object)
|
|||
object.release();
|
||||
}
|
||||
|
||||
template<> inline
|
||||
ircd::json::value::value(const int64_t &integer)
|
||||
:integer{integer}
|
||||
,len{0}
|
||||
,type{NUMBER}
|
||||
,serial{false}
|
||||
,alloc{false}
|
||||
,floats{false}
|
||||
{}
|
||||
|
||||
template<> inline
|
||||
ircd::json::value::value(const double &floating)
|
||||
:floating{floating}
|
||||
,len{0}
|
||||
,type{NUMBER}
|
||||
,serial{false}
|
||||
,alloc{false}
|
||||
,floats{true}
|
||||
{}
|
||||
|
||||
template<> inline
|
||||
ircd::json::value::value(const float &floating)
|
||||
:value{double(floating)}
|
||||
{}
|
||||
|
||||
template<> inline
|
||||
ircd::json::value::value(const int32_t &integer)
|
||||
:value{int64_t(integer)}
|
||||
{}
|
||||
|
||||
template<> inline
|
||||
ircd::json::value::value(const int16_t &integer)
|
||||
:value{int64_t(integer)}
|
||||
{}
|
||||
|
||||
template<> inline
|
||||
ircd::json::value::value(const std::string &str)
|
||||
:value{string_view{str}}
|
||||
{}
|
||||
|
||||
template<size_t N>
|
||||
ircd::json::value::value(const char (&str)[N])
|
||||
:value{string_view{str}}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::val::val(val &&other)
|
||||
ircd::json::value::value(const char *const &s)
|
||||
:value{string_view{s}}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(const string_view &sv)
|
||||
:value{sv, json::type(sv, std::nothrow)}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(value &&other)
|
||||
noexcept
|
||||
:integer{other.integer}
|
||||
,len{other.len}
|
||||
|
@ -174,11 +194,11 @@ noexcept
|
|||
other.alloc = false;
|
||||
}
|
||||
|
||||
inline ircd::json::val &
|
||||
ircd::json::val::operator=(val &&other)
|
||||
inline ircd::json::value &
|
||||
ircd::json::value::operator=(value &&other)
|
||||
noexcept
|
||||
{
|
||||
this->~val();
|
||||
this->~value();
|
||||
integer = other.integer;
|
||||
len = other.len;
|
||||
type = other.type;
|
||||
|
@ -190,7 +210,7 @@ noexcept
|
|||
}
|
||||
|
||||
inline enum ircd::json::type
|
||||
ircd::json::type(const val &a)
|
||||
ircd::json::type(const value &a)
|
||||
{
|
||||
return a.type;
|
||||
}
|
347
ircd/json.cc
347
ircd/json.cc
|
@ -25,9 +25,9 @@
|
|||
|
||||
BOOST_FUSION_ADAPT_STRUCT
|
||||
(
|
||||
ircd::json::doc::member,
|
||||
( decltype(ircd::json::doc::member::first), first )
|
||||
( decltype(ircd::json::doc::member::second), second )
|
||||
ircd::json::object::member,
|
||||
( decltype(ircd::json::object::member::first), first )
|
||||
( decltype(ircd::json::object::member::second), second )
|
||||
)
|
||||
|
||||
namespace ircd {
|
||||
|
@ -81,7 +81,7 @@ struct input
|
|||
rule<> ws { *(WS) ,"whitespace monoid" };
|
||||
rule<> wsp { +(WS) ,"whitespace semigroup" };
|
||||
|
||||
// structural
|
||||
// structural
|
||||
rule<> object_begin { lit('{') ,"object begin" };
|
||||
rule<> object_end { lit('}') ,"object end" };
|
||||
rule<> array_begin { lit('[') ,"array begin" };
|
||||
|
@ -121,7 +121,7 @@ struct input
|
|||
,"value"
|
||||
};
|
||||
|
||||
rule<doc::member> member
|
||||
rule<object::member> member
|
||||
{
|
||||
name >> ws >> name_sep >> ws >> value
|
||||
,"member"
|
||||
|
@ -164,7 +164,7 @@ struct output
|
|||
rule<> ws { *(WS) ,"whitespace monoid" };
|
||||
rule<> wsp { +(WS) ,"whitespace semigroup" };
|
||||
|
||||
// structural
|
||||
// structural
|
||||
rule<> object_begin { lit('{') ,"object begin" };
|
||||
rule<> object_end { lit('}') ,"object end" };
|
||||
rule<> array_begin { lit('[') ,"array begin" };
|
||||
|
@ -176,25 +176,38 @@ struct output
|
|||
rule<string_view> lit_true { karma::string("true") ,"literal true" };
|
||||
rule<string_view> lit_false { karma::string("false") ,"literal false" };
|
||||
rule<string_view> lit_null { karma::string("null") ,"literal null" };
|
||||
|
||||
rule<string_view> boolean { lit_true | lit_false ,"boolean" };
|
||||
rule<string_view> literal { lit_true | lit_false | lit_null ,"literal" };
|
||||
|
||||
rule<string_view> chars { *(~char_('"')) ,"characters" };
|
||||
rule<string_view> string { quote << chars << quote ,"string" };
|
||||
|
||||
rule<string_view> number { double_ ,"number" };
|
||||
|
||||
rule<string_view> name { quote << +(~char_('"')) << quote ,"name" };
|
||||
rule<string_view> value { rule<string_view>{} /* subclass implemented */ ,"value" };
|
||||
rule<const doc::member &> member { name << name_sep << value ,"member" };
|
||||
|
||||
rule<const string_view &> elem { value ,"element" };
|
||||
rule<const json::arr &> elems { -(value % value_sep) ,"elements" };
|
||||
rule<const json::arr &> array { array_begin << elems << array_end ,"array" };
|
||||
rule<const json::array &> elems { -(value % value_sep) ,"elements" };
|
||||
rule<const json::array &> array
|
||||
{
|
||||
array_begin << elems << array_end
|
||||
,"array"
|
||||
};
|
||||
|
||||
rule<const json::doc &> members { -(member % value_sep) ,"members" };
|
||||
rule<const json::doc &> document { object_begin << members << object_end ,"document" };
|
||||
rule<const json::object::member &> member
|
||||
{
|
||||
name << name_sep << value
|
||||
,"member"
|
||||
};
|
||||
|
||||
rule<const json::object &> members
|
||||
{
|
||||
-(member % value_sep)
|
||||
,"members"
|
||||
};
|
||||
|
||||
rule<const json::object &> object
|
||||
{
|
||||
object_begin << members << object_end
|
||||
,"object"
|
||||
};
|
||||
|
||||
output()
|
||||
:output::base_type{rule<>{}}
|
||||
|
@ -235,17 +248,17 @@ struct ostreamer
|
|||
}
|
||||
const ostreamer;
|
||||
|
||||
size_t print(char *const &buf, const size_t &max, const arr &);
|
||||
size_t print(char *const &buf, const size_t &max, const doc &);
|
||||
size_t print(char *const &buf, const size_t &max, const obj &);
|
||||
arr serialize(const arr &, char *&start, char *const &stop);
|
||||
doc serialize(const doc &, char *&start, char *const &stop);
|
||||
doc serialize(const obj &, char *&start, char *const &stop);
|
||||
size_t print(char *const &buf, const size_t &max, const array &);
|
||||
size_t print(char *const &buf, const size_t &max, const object &);
|
||||
size_t print(char *const &buf, const size_t &max, const index &);
|
||||
array serialize(const array &, char *&start, char *const &stop);
|
||||
object serialize(const object &, char *&start, char *const &stop);
|
||||
object serialize(const index &, char *&start, char *const &stop);
|
||||
|
||||
std::ostream &operator<<(std::ostream &, const arr &);
|
||||
std::ostream &operator<<(std::ostream &, const doc::member &);
|
||||
std::ostream &operator<<(std::ostream &, const doc &);
|
||||
std::ostream &operator<<(std::ostream &, const obj &);
|
||||
std::ostream &operator<<(std::ostream &, const array &);
|
||||
std::ostream &operator<<(std::ostream &, const object::member &);
|
||||
std::ostream &operator<<(std::ostream &, const object &);
|
||||
std::ostream &operator<<(std::ostream &, const index &);
|
||||
|
||||
} // namespace json
|
||||
} // namespace ircd
|
||||
|
@ -266,7 +279,7 @@ failed_to_stream_object()
|
|||
throw print_error("The JSON generator failed to stream object");
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace <anonymous>
|
||||
} // namespace json
|
||||
} // namespace ircd
|
||||
|
||||
|
@ -277,9 +290,9 @@ std::string
|
|||
merge_operator(const string_view &key,
|
||||
const std::pair<string_view, string_view> &delta)
|
||||
{
|
||||
ircd::json::obj obj{delta.first};
|
||||
obj += delta.second;
|
||||
return obj;
|
||||
ircd::json::index index{delta.first};
|
||||
index += delta.second;
|
||||
return index;
|
||||
}
|
||||
|
||||
} // namespace db
|
||||
|
@ -292,14 +305,14 @@ ircd::json::printer::printer()
|
|||
const auto recurse_array([&]
|
||||
{
|
||||
char *out(const_cast<char *>(a.data()));
|
||||
const arr r(serialize(json::arr(a), out, out + a.size()));
|
||||
const auto r(serialize(json::array(a), out, out + a.size()));
|
||||
a.resize(size_t(out - r.data()));
|
||||
});
|
||||
|
||||
const auto recurse_document([&]
|
||||
const auto recurse_object([&]
|
||||
{
|
||||
char *out(const_cast<char *>(a.data()));
|
||||
const doc d(serialize(json::doc(a), out, out + a.size()));
|
||||
const auto d(serialize(json::object(a), out, out + a.size()));
|
||||
a.resize(size_t(out - d.data()));
|
||||
});
|
||||
|
||||
|
@ -311,7 +324,7 @@ ircd::json::printer::printer()
|
|||
|
||||
if(likely(!a.empty())) switch(a.front())
|
||||
{
|
||||
case '{': recurse_document(); break;
|
||||
case '{': recurse_object(); break;
|
||||
case '[': recurse_array(); break;
|
||||
case '"': break;
|
||||
case '0': break;
|
||||
|
@ -374,7 +387,7 @@ const
|
|||
size_t
|
||||
ircd::json::print(char *const &buf,
|
||||
const size_t &max,
|
||||
const obj &obj)
|
||||
const index &obj)
|
||||
{
|
||||
if(unlikely(!max))
|
||||
return 0;
|
||||
|
@ -385,65 +398,65 @@ ircd::json::print(char *const &buf,
|
|||
return out - buf;
|
||||
}
|
||||
|
||||
ircd::json::doc
|
||||
ircd::json::serialize(const obj &obj,
|
||||
ircd::json::object
|
||||
ircd::json::serialize(const index &obj,
|
||||
char *&out,
|
||||
char *const &stop)
|
||||
{
|
||||
const auto print_string([&stop, &out](const val &val)
|
||||
const auto print_string([&stop, &out](const value &value)
|
||||
{
|
||||
printer(out, stop, printer.string, string_view{val});
|
||||
printer(out, stop, printer.string, string_view{value});
|
||||
});
|
||||
|
||||
const auto print_literal([&stop, &out](const val &val)
|
||||
const auto print_literal([&stop, &out](const value &value)
|
||||
{
|
||||
printer(out, stop, karma::string, string_view{val});
|
||||
printer(out, stop, karma::string, string_view{value});
|
||||
});
|
||||
|
||||
const auto print_object([&stop, &out](const val &val)
|
||||
const auto print_object([&stop, &out](const value &value)
|
||||
{
|
||||
if(val.serial)
|
||||
if(value.serial)
|
||||
{
|
||||
printer(out, stop, printer.document, string_view{val});
|
||||
printer(out, stop, printer.object, string_view{value});
|
||||
return;
|
||||
}
|
||||
|
||||
assert(val.object);
|
||||
serialize(*val.object, out, stop);
|
||||
assert(value.object);
|
||||
serialize(*value.object, out, stop);
|
||||
});
|
||||
|
||||
const auto print_array([&stop, &out](const val &val)
|
||||
const auto print_array([&stop, &out](const value &value)
|
||||
{
|
||||
if(val.serial)
|
||||
if(value.serial)
|
||||
{
|
||||
printer(out, stop, printer.array, string_view{val});
|
||||
printer(out, stop, printer.array, string_view{value});
|
||||
return;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
//assert(val.object);
|
||||
//serialize(*val.object, out, stop);
|
||||
//assert(value.object);
|
||||
//serialize(*value.object, out, stop);
|
||||
});
|
||||
|
||||
const auto print_number([&stop, &out](const val &val)
|
||||
const auto print_number([&stop, &out](const value &value)
|
||||
{
|
||||
if(val.serial)
|
||||
if(value.serial)
|
||||
{
|
||||
if(val.floats)
|
||||
printer(out, stop, double_, string_view{val});
|
||||
if(value.floats)
|
||||
printer(out, stop, double_, string_view{value});
|
||||
else
|
||||
printer(out, stop, long_, string_view{val});
|
||||
printer(out, stop, long_, string_view{value});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(val.floats)
|
||||
printer(out, stop, double_, val.floating);
|
||||
if(value.floats)
|
||||
printer(out, stop, double_, value.floating);
|
||||
else
|
||||
printer(out, stop, long_, val.integer);
|
||||
printer(out, stop, long_, value.integer);
|
||||
});
|
||||
|
||||
const auto print_member([&](const obj::member &member)
|
||||
const auto print_member([&](const index::member &member)
|
||||
{
|
||||
printer(out, stop, printer.name << printer.name_sep, member.first);
|
||||
|
||||
|
@ -482,14 +495,14 @@ ircd::json::ostreamer::ostreamer()
|
|||
const auto recurse_array([&]
|
||||
{
|
||||
char *out(const_cast<char *>(a.data()));
|
||||
const arr r(serialize(json::arr(a), out, out + a.size()));
|
||||
const auto r(serialize(json::array(a), out, out + a.size()));
|
||||
a.resize(size_t(out - r.data()));
|
||||
});
|
||||
|
||||
const auto recurse_document([&]
|
||||
const auto recurse_object([&]
|
||||
{
|
||||
char *out(const_cast<char *>(a.data()));
|
||||
const doc d(serialize(json::doc(a), out, out + a.size()));
|
||||
const auto d(serialize(json::object(a), out, out + a.size()));
|
||||
a.resize(size_t(out - d.data()));
|
||||
});
|
||||
|
||||
|
@ -501,7 +514,7 @@ ircd::json::ostreamer::ostreamer()
|
|||
|
||||
if(likely(!a.empty())) switch(a.front())
|
||||
{
|
||||
case '{': recurse_document(); break;
|
||||
case '{': recurse_object(); break;
|
||||
case '[': recurse_array(); break;
|
||||
case '"': break;
|
||||
case '0': break;
|
||||
|
@ -530,64 +543,64 @@ ircd::json::ostreamer::ostreamer()
|
|||
}
|
||||
|
||||
std::ostream &
|
||||
ircd::json::operator<<(std::ostream &s, const obj &obj)
|
||||
ircd::json::operator<<(std::ostream &s, const index &obj)
|
||||
{
|
||||
karma::ostream_iterator<char> osi(s);
|
||||
|
||||
const auto stream_string([&osi](const val &val)
|
||||
const auto stream_string([&osi](const value &value)
|
||||
{
|
||||
karma::generate(osi, ostreamer.string, string_view{val});
|
||||
karma::generate(osi, ostreamer.string, string_view{value});
|
||||
});
|
||||
|
||||
const auto stream_literal([&osi](const val &val)
|
||||
const auto stream_literal([&osi](const value &value)
|
||||
{
|
||||
karma::generate(osi, karma::string, string_view{val});
|
||||
karma::generate(osi, karma::string, string_view{value});
|
||||
});
|
||||
|
||||
const auto stream_object([&osi, &s](const val &val)
|
||||
const auto stream_object([&osi, &s](const value &value)
|
||||
{
|
||||
if(val.serial)
|
||||
if(value.serial)
|
||||
{
|
||||
karma::generate(osi, ostreamer.document, string_view{val});
|
||||
karma::generate(osi, ostreamer.object, string_view{value});
|
||||
return;
|
||||
}
|
||||
|
||||
assert(val.object);
|
||||
s << *val.object;
|
||||
assert(value.object);
|
||||
s << *value.object;
|
||||
});
|
||||
|
||||
const auto stream_array([&osi](const val &val)
|
||||
const auto stream_array([&osi](const value &value)
|
||||
{
|
||||
if(val.serial)
|
||||
if(value.serial)
|
||||
{
|
||||
karma::generate(osi, ostreamer.array, string_view{val});
|
||||
karma::generate(osi, ostreamer.array, string_view{value});
|
||||
return;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
//assert(val.object);
|
||||
//s << *val.object;
|
||||
//assert(value.object);
|
||||
//s << *value.object;
|
||||
});
|
||||
|
||||
const auto stream_number([&osi](const val &val)
|
||||
const auto stream_number([&osi](const value &value)
|
||||
{
|
||||
if(val.serial)
|
||||
if(value.serial)
|
||||
{
|
||||
if(val.floats)
|
||||
karma::generate(osi, double_, string_view{val});
|
||||
if(value.floats)
|
||||
karma::generate(osi, double_, string_view{value});
|
||||
else
|
||||
karma::generate(osi, long_, string_view{val});
|
||||
karma::generate(osi, long_, string_view{value});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(val.floats)
|
||||
karma::generate(osi, double_, val.floating);
|
||||
if(value.floats)
|
||||
karma::generate(osi, double_, value.floating);
|
||||
else
|
||||
karma::generate(osi, long_, val.integer);
|
||||
karma::generate(osi, long_, value.integer);
|
||||
});
|
||||
|
||||
const auto stream_member([&](const obj::member &member)
|
||||
const auto stream_member([&](const index::member &member)
|
||||
{
|
||||
karma::generate(osi, ostreamer.name << ostreamer.name_sep, string_view(member.first));
|
||||
|
||||
|
@ -618,16 +631,16 @@ ircd::json::operator<<(std::ostream &s, const obj &obj)
|
|||
return s;
|
||||
}
|
||||
|
||||
ircd::json::obj
|
||||
ircd::json::operator+(const doc &left, const doc &right)
|
||||
ircd::json::index
|
||||
ircd::json::operator+(const object &left, const object &right)
|
||||
{
|
||||
obj ret(left);
|
||||
index ret(left);
|
||||
ret += right;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ircd::json::obj &
|
||||
ircd::json::operator+=(obj &left, const doc &right)
|
||||
ircd::json::index &
|
||||
ircd::json::operator+=(index &left, const object &right)
|
||||
{
|
||||
for(const auto &b : right)
|
||||
{
|
||||
|
@ -646,7 +659,7 @@ ircd::json::operator+=(obj &left, const doc &right)
|
|||
if(deletion) // prevents adding the empty indicator as the new key!
|
||||
continue;
|
||||
|
||||
left.idx.emplace_back(obj::member{b});
|
||||
left.idx.emplace_back(index::member{b});
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -656,20 +669,20 @@ ircd::json::operator+=(obj &left, const doc &right)
|
|||
continue;
|
||||
}
|
||||
|
||||
auto &a(const_cast<obj::member &>(*it));
|
||||
auto &a(const_cast<index::member &>(*it));
|
||||
switch(type(a.second))
|
||||
{
|
||||
default:
|
||||
{
|
||||
a = obj::member{b};
|
||||
a = index::member{b};
|
||||
continue;
|
||||
}
|
||||
|
||||
// merge recursively
|
||||
case OBJECT:
|
||||
{
|
||||
auto merged(std::make_unique<obj>(json::doc{a.second}));
|
||||
*merged += json::doc{b.second};
|
||||
auto merged(std::make_unique<index>(json::object{a.second}));
|
||||
*merged += json::object{b.second};
|
||||
if(merged->empty())
|
||||
{
|
||||
// Child merge was empty value. Now we can also remove this empty parent.
|
||||
|
@ -677,7 +690,7 @@ ircd::json::operator+=(obj &left, const doc &right)
|
|||
continue;
|
||||
}
|
||||
|
||||
a = obj::member{string_view{a.first}, std::move(merged)};
|
||||
a = index::member{string_view{a.first}, std::move(merged)};
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -686,35 +699,35 @@ ircd::json::operator+=(obj &left, const doc &right)
|
|||
return left;
|
||||
}
|
||||
|
||||
ircd::json::obj::obj(recursive_t recursive,
|
||||
const doc &doc)
|
||||
:idx{doc.count()}
|
||||
ircd::json::index::index(recursive_t recursive,
|
||||
const object &object)
|
||||
:idx{object.count()}
|
||||
{
|
||||
std::transform(std::begin(doc), std::end(doc), std::begin(idx), [&]
|
||||
(const doc::member &m) -> obj::member
|
||||
std::transform(std::begin(object), std::end(object), std::begin(idx), [&]
|
||||
(const object::member &m) -> index::member
|
||||
{
|
||||
switch(type(m.second))
|
||||
{
|
||||
case OBJECT:
|
||||
return obj::member{m.first, std::make_unique<obj>(recursive, m.second)};
|
||||
return index::member{m.first, std::make_unique<index>(recursive, m.second)};
|
||||
|
||||
default:
|
||||
return obj::member{m};
|
||||
return index::member{m};
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
ircd::json::obj::obj(const doc &doc)
|
||||
:idx{doc.count()}
|
||||
ircd::json::index::index(const object &object)
|
||||
:idx{object.count()}
|
||||
{
|
||||
std::transform(std::begin(doc), std::end(doc), std::begin(idx), []
|
||||
(const doc::member &m) -> obj::member
|
||||
std::transform(std::begin(object), std::end(object), std::begin(idx), []
|
||||
(const object::member &m) -> index::member
|
||||
{
|
||||
return obj::member{m};
|
||||
return index::member{m};
|
||||
});
|
||||
}
|
||||
|
||||
ircd::json::obj::obj(std::initializer_list<member> builder)
|
||||
ircd::json::index::index(std::initializer_list<member> builder)
|
||||
:idx{builder.size()}
|
||||
{
|
||||
std::transform(std::begin(builder), std::end(builder), std::begin(idx), []
|
||||
|
@ -732,7 +745,7 @@ ircd::json::obj::obj(std::initializer_list<member> builder)
|
|||
}
|
||||
|
||||
bool
|
||||
ircd::json::obj::erase(const string_view &name)
|
||||
ircd::json::index::erase(const string_view &name)
|
||||
{
|
||||
const auto it(find(name));
|
||||
if(it == end())
|
||||
|
@ -743,20 +756,20 @@ ircd::json::obj::erase(const string_view &name)
|
|||
}
|
||||
|
||||
void
|
||||
ircd::json::obj::erase(const const_iterator &it)
|
||||
ircd::json::index::erase(const const_iterator &it)
|
||||
{
|
||||
idx.erase(it);
|
||||
}
|
||||
|
||||
ircd::json::obj::const_iterator
|
||||
ircd::json::obj::erase(const const_iterator &start,
|
||||
const const_iterator &stop)
|
||||
ircd::json::index::const_iterator
|
||||
ircd::json::index::erase(const const_iterator &start,
|
||||
const const_iterator &stop)
|
||||
{
|
||||
return { idx.erase(start, stop) };
|
||||
}
|
||||
|
||||
const ircd::json::val &
|
||||
ircd::json::obj::at(const string_view &path)
|
||||
const ircd::json::value &
|
||||
ircd::json::index::at(const string_view &path)
|
||||
const
|
||||
{
|
||||
const auto elem(split(path, '.'));
|
||||
|
@ -797,7 +810,7 @@ const
|
|||
}
|
||||
|
||||
size_t
|
||||
ircd::json::obj::size()
|
||||
ircd::json::index::size()
|
||||
const
|
||||
{
|
||||
const size_t ret(1 + idx.empty());
|
||||
|
@ -808,7 +821,7 @@ const
|
|||
});
|
||||
}
|
||||
|
||||
ircd::json::obj::operator std::string()
|
||||
ircd::json::index::operator std::string()
|
||||
const
|
||||
{
|
||||
std::string ret(size(), char());
|
||||
|
@ -816,7 +829,7 @@ const
|
|||
return ret;
|
||||
}
|
||||
|
||||
ircd::json::val::~val()
|
||||
ircd::json::value::~value()
|
||||
noexcept
|
||||
{
|
||||
switch(type)
|
||||
|
@ -828,7 +841,7 @@ noexcept
|
|||
}
|
||||
}
|
||||
|
||||
ircd::json::val::operator std::string()
|
||||
ircd::json::value::operator std::string()
|
||||
const
|
||||
{
|
||||
switch(type)
|
||||
|
@ -858,10 +871,10 @@ const
|
|||
return std::string(lex_cast(integer));
|
||||
}
|
||||
|
||||
throw type_error("cannot stringify type[%d]", int(type));
|
||||
throw type_error("cannot index type[%d]", int(type));
|
||||
}
|
||||
|
||||
ircd::json::val::operator string_view()
|
||||
ircd::json::value::operator string_view()
|
||||
const
|
||||
{
|
||||
switch(type)
|
||||
|
@ -883,7 +896,7 @@ const
|
|||
}
|
||||
|
||||
bool
|
||||
ircd::json::val::empty()
|
||||
ircd::json::value::empty()
|
||||
const
|
||||
{
|
||||
switch(type)
|
||||
|
@ -899,7 +912,7 @@ const
|
|||
}
|
||||
|
||||
size_t
|
||||
ircd::json::val::size()
|
||||
ircd::json::value::size()
|
||||
const
|
||||
{
|
||||
switch(type)
|
||||
|
@ -915,7 +928,7 @@ const
|
|||
}
|
||||
|
||||
std::ostream &
|
||||
ircd::json::operator<<(std::ostream &s, const val &v)
|
||||
ircd::json::operator<<(std::ostream &s, const value &v)
|
||||
{
|
||||
switch(v.type)
|
||||
{
|
||||
|
@ -952,7 +965,7 @@ ircd::json::operator<<(std::ostream &s, const val &v)
|
|||
}
|
||||
|
||||
bool
|
||||
ircd::json::operator>(const val &a, const val &b)
|
||||
ircd::json::operator>(const value &a, const value &b)
|
||||
{
|
||||
if(unlikely(type(a) != STRING || type(b) != STRING))
|
||||
throw type_error("cannot compare values");
|
||||
|
@ -961,7 +974,7 @@ ircd::json::operator>(const val &a, const val &b)
|
|||
}
|
||||
|
||||
bool
|
||||
ircd::json::operator<(const val &a, const val &b)
|
||||
ircd::json::operator<(const value &a, const value &b)
|
||||
{
|
||||
if(unlikely(type(a) != STRING || type(b) != STRING))
|
||||
throw type_error("cannot compare values");
|
||||
|
@ -970,7 +983,7 @@ ircd::json::operator<(const val &a, const val &b)
|
|||
}
|
||||
|
||||
bool
|
||||
ircd::json::operator>=(const val &a, const val &b)
|
||||
ircd::json::operator>=(const value &a, const value &b)
|
||||
{
|
||||
if(unlikely(type(a) != STRING || type(b) != STRING))
|
||||
throw type_error("cannot compare values");
|
||||
|
@ -979,7 +992,7 @@ ircd::json::operator>=(const val &a, const val &b)
|
|||
}
|
||||
|
||||
bool
|
||||
ircd::json::operator<=(const val &a, const val &b)
|
||||
ircd::json::operator<=(const value &a, const value &b)
|
||||
{
|
||||
if(unlikely(type(a) != STRING || type(b) != STRING))
|
||||
throw type_error("cannot compare values");
|
||||
|
@ -988,7 +1001,7 @@ ircd::json::operator<=(const val &a, const val &b)
|
|||
}
|
||||
|
||||
bool
|
||||
ircd::json::operator!=(const val &a, const val &b)
|
||||
ircd::json::operator!=(const value &a, const value &b)
|
||||
{
|
||||
if(unlikely(type(a) != STRING || type(b) != STRING))
|
||||
throw type_error("cannot compare values");
|
||||
|
@ -997,7 +1010,7 @@ ircd::json::operator!=(const val &a, const val &b)
|
|||
}
|
||||
|
||||
bool
|
||||
ircd::json::operator==(const val &a, const val &b)
|
||||
ircd::json::operator==(const value &a, const value &b)
|
||||
{
|
||||
if(unlikely(type(a) != STRING || type(b) != STRING))
|
||||
throw type_error("cannot compare values");
|
||||
|
@ -1008,52 +1021,52 @@ ircd::json::operator==(const val &a, const val &b)
|
|||
size_t
|
||||
ircd::json::print(char *const &buf,
|
||||
const size_t &max,
|
||||
const doc &doc)
|
||||
const object &object)
|
||||
{
|
||||
if(unlikely(!max))
|
||||
return 0;
|
||||
|
||||
char *out(buf);
|
||||
serialize(doc, out, out + (max - 1));
|
||||
serialize(object, out, out + (max - 1));
|
||||
*out = '\0';
|
||||
return std::distance(buf, out);
|
||||
}
|
||||
|
||||
ircd::json::doc
|
||||
ircd::json::serialize(const doc &doc,
|
||||
ircd::json::object
|
||||
ircd::json::serialize(const object &object,
|
||||
char *&out,
|
||||
char *const &stop)
|
||||
{
|
||||
static const auto throws([]
|
||||
{
|
||||
throw print_error("The JSON generator failed to print document");
|
||||
throw print_error("The JSON generator failed to print object");
|
||||
});
|
||||
|
||||
char *const start(out);
|
||||
karma::generate(out, maxwidth(stop - start)[printer.document] | eps[throws], doc);
|
||||
karma::generate(out, maxwidth(stop - start)[printer.object] | eps[throws], object);
|
||||
return string_view{start, out};
|
||||
}
|
||||
|
||||
std::ostream &
|
||||
ircd::json::operator<<(std::ostream &s, const doc &doc)
|
||||
ircd::json::operator<<(std::ostream &s, const object &object)
|
||||
{
|
||||
const auto &os(ostreamer);
|
||||
static const auto throws([]
|
||||
{
|
||||
throw print_error("The JSON generator failed to output document to stream");
|
||||
throw print_error("The JSON generator failed to output object to stream");
|
||||
});
|
||||
|
||||
karma::ostream_iterator<char> osi(s);
|
||||
karma::generate(osi, os.document | eps[throws], doc);
|
||||
karma::generate(osi, os.object | eps[throws], object);
|
||||
return s;
|
||||
}
|
||||
|
||||
std::ostream &
|
||||
ircd::json::operator<<(std::ostream &s, const doc::member &member)
|
||||
ircd::json::operator<<(std::ostream &s, const object::member &member)
|
||||
{
|
||||
static const auto throws([]
|
||||
{
|
||||
throw print_error("The JSON generator failed to output document member to stream");
|
||||
throw print_error("The JSON generator failed to output object member to stream");
|
||||
});
|
||||
|
||||
karma::ostream_iterator<char> osi(s);
|
||||
|
@ -1061,15 +1074,15 @@ ircd::json::operator<<(std::ostream &s, const doc::member &member)
|
|||
return s;
|
||||
}
|
||||
|
||||
ircd::json::doc::const_iterator &
|
||||
ircd::json::doc::const_iterator::operator++()
|
||||
ircd::json::object::const_iterator &
|
||||
ircd::json::object::const_iterator::operator++()
|
||||
{
|
||||
static const qi::rule<const char *, json::doc::member> member
|
||||
static const qi::rule<const char *, json::object::member> member
|
||||
{
|
||||
parser.name >> parser.ws >> parser.name_sep >> parser.ws >> raw[parser.value]
|
||||
};
|
||||
|
||||
static const qi::rule<const char *, json::doc::member> parse_next
|
||||
static const qi::rule<const char *, json::object::member> parse_next
|
||||
{
|
||||
parser.object_end | (parser.value_sep >> parser.ws >> member)
|
||||
};
|
||||
|
@ -1082,7 +1095,7 @@ ircd::json::doc::const_iterator::operator++()
|
|||
return *this;
|
||||
}
|
||||
|
||||
ircd::json::doc::operator std::string()
|
||||
ircd::json::object::operator std::string()
|
||||
const
|
||||
{
|
||||
//TODO: tmp
|
||||
|
@ -1091,16 +1104,16 @@ const
|
|||
return ret.str();
|
||||
}
|
||||
|
||||
ircd::json::doc::const_iterator
|
||||
ircd::json::doc::begin()
|
||||
ircd::json::object::const_iterator
|
||||
ircd::json::object::begin()
|
||||
const
|
||||
{
|
||||
static const qi::rule<const char *, json::doc::member> member
|
||||
static const qi::rule<const char *, json::object::member> member
|
||||
{
|
||||
parser.name >> parser.ws >> parser.name_sep >> parser.ws >> raw[parser.value]
|
||||
};
|
||||
|
||||
static const qi::rule<const char *, json::doc::member> parse_begin
|
||||
static const qi::rule<const char *, json::object::member> parse_begin
|
||||
{
|
||||
parser.object_begin >> parser.ws >> (parser.object_end | member)
|
||||
};
|
||||
|
@ -1112,8 +1125,8 @@ const
|
|||
return ret;
|
||||
}
|
||||
|
||||
ircd::json::doc::const_iterator
|
||||
ircd::json::doc::end()
|
||||
ircd::json::object::const_iterator
|
||||
ircd::json::object::end()
|
||||
const
|
||||
{
|
||||
return { string_view::end(), string_view::end() };
|
||||
|
@ -1122,7 +1135,7 @@ const
|
|||
size_t
|
||||
ircd::json::print(char *const &buf,
|
||||
const size_t &max,
|
||||
const arr &arr)
|
||||
const array &arr)
|
||||
{
|
||||
if(unlikely(!max))
|
||||
return 0;
|
||||
|
@ -1133,8 +1146,8 @@ ircd::json::print(char *const &buf,
|
|||
return std::distance(buf, out);
|
||||
}
|
||||
|
||||
ircd::json::arr
|
||||
ircd::json::serialize(const arr &a,
|
||||
ircd::json::array
|
||||
ircd::json::serialize(const array &a,
|
||||
char *&out,
|
||||
char *const &stop)
|
||||
{
|
||||
|
@ -1159,7 +1172,7 @@ ircd::json::serialize(const arr &a,
|
|||
}
|
||||
|
||||
std::ostream &
|
||||
ircd::json::operator<<(std::ostream &s, const arr &a)
|
||||
ircd::json::operator<<(std::ostream &s, const array &a)
|
||||
{
|
||||
const auto &os(ostreamer);
|
||||
static const auto throws([]
|
||||
|
@ -1182,8 +1195,8 @@ ircd::json::operator<<(std::ostream &s, const arr &a)
|
|||
return s;
|
||||
}
|
||||
|
||||
ircd::json::arr::const_iterator &
|
||||
ircd::json::arr::const_iterator::operator++()
|
||||
ircd::json::array::const_iterator &
|
||||
ircd::json::array::const_iterator::operator++()
|
||||
{
|
||||
static const qi::rule<const char *, string_view> parse_next
|
||||
{
|
||||
|
@ -1197,7 +1210,7 @@ ircd::json::arr::const_iterator::operator++()
|
|||
return *this;
|
||||
}
|
||||
|
||||
ircd::json::arr::operator std::string()
|
||||
ircd::json::array::operator std::string()
|
||||
const
|
||||
{
|
||||
//TODO: tmp
|
||||
|
@ -1206,8 +1219,8 @@ const
|
|||
return ret.str();
|
||||
}
|
||||
|
||||
ircd::json::arr::const_iterator
|
||||
ircd::json::arr::begin()
|
||||
ircd::json::array::const_iterator
|
||||
ircd::json::array::begin()
|
||||
const
|
||||
{
|
||||
static const qi::rule<const char *, string_view> parse_begin
|
||||
|
@ -1222,8 +1235,8 @@ const
|
|||
return ret;
|
||||
}
|
||||
|
||||
ircd::json::arr::const_iterator
|
||||
ircd::json::arr::end()
|
||||
ircd::json::array::const_iterator
|
||||
ircd::json::array::end()
|
||||
const
|
||||
{
|
||||
return { string_view::end(), string_view::end() };
|
||||
|
|
|
@ -120,7 +120,7 @@ try
|
|||
/*
|
||||
account(db::MERGE, "jzk", std::string
|
||||
{
|
||||
json::obj
|
||||
json::index
|
||||
{{
|
||||
"password",
|
||||
{
|
||||
|
|
|
@ -55,7 +55,7 @@ try
|
|||
|
||||
return resource::response
|
||||
{
|
||||
client, http::CREATED, json::obj
|
||||
client, http::CREATED, json::index
|
||||
{
|
||||
{ "room_id", room_id }
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ logout(client &client, const resource::request &request)
|
|||
resource::tokens.erase(it);
|
||||
return resource::response
|
||||
{
|
||||
client, json::obj
|
||||
client, json::index
|
||||
{
|
||||
{ }
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ get_publicrooms(client &client, const resource::request &request)
|
|||
|
||||
return resource::response
|
||||
{
|
||||
client, json::obj
|
||||
client, json::index
|
||||
{
|
||||
{ }
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ try
|
|||
{
|
||||
return resource::response
|
||||
{
|
||||
client, json::obj
|
||||
client, json::index
|
||||
{
|
||||
{ }
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ handle_post(client &client,
|
|||
|
||||
return resource::response
|
||||
{
|
||||
client, http::CREATED, json::obj
|
||||
client, http::CREATED, json::index
|
||||
{
|
||||
{ "access_token", access_token },
|
||||
{ "home_server", home_server },
|
||||
|
@ -146,7 +146,7 @@ handle_post(client &client,
|
|||
// Send response to user
|
||||
return resource::response
|
||||
{
|
||||
client, http::CREATED, json::obj
|
||||
client, http::CREATED, json::index
|
||||
{
|
||||
{ "access_token", access_token },
|
||||
{ "home_server", home_server },
|
||||
|
|
|
@ -56,7 +56,7 @@ try
|
|||
|
||||
return resource::response
|
||||
{
|
||||
client, json::obj
|
||||
client, json::index
|
||||
{
|
||||
{ }
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ try
|
|||
|
||||
return resource::response
|
||||
{
|
||||
client, http::CREATED, json::obj
|
||||
client, http::CREATED, json::index
|
||||
{
|
||||
{ "filter_id", "abc321" }
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ resource::method getter
|
|||
(client &client, resource::request &request)
|
||||
-> resource::response
|
||||
{
|
||||
static const json::doc object
|
||||
static const json::object object
|
||||
{
|
||||
R"({"versions":["r2.0.0"]})"
|
||||
};
|
||||
|
|
|
@ -38,7 +38,7 @@ get_turnserver(client &client, const resource::request &request)
|
|||
{
|
||||
return resource::response
|
||||
{
|
||||
client, json::obj
|
||||
client, json::index
|
||||
{
|
||||
{ },
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue