0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-10-01 21:28:53 +02:00

ircd: JSON subsystem related.

This commit is contained in:
Jason Volk 2017-03-20 04:25:55 -07:00
parent 42ce334528
commit 3badb2ff90
5 changed files with 373 additions and 240 deletions

View file

@ -39,14 +39,14 @@ struct obj;
enum type
{
OBJECT = 0,
STRING = 1,
NUMBER = 2,
LITERAL = 3,
ARRAY = 4,
STRING = 0,
OBJECT = 1,
ARRAY = 2,
NUMBER = 3,
LITERAL = 4,
};
type type(const string_view &);
enum type type(const string_view &);
enum type type(const string_view &, std::nothrow_t);
} // namespace json
} // namespace ircd

View file

@ -42,11 +42,14 @@ struct arr
const_iterator end() const;
const_iterator begin() const;
const_iterator find(size_t i) const;
size_t count() const;
const_iterator find(size_t i) const;
string_view at(size_t i) const;
string_view operator[](size_t i) const;
template<class T> T at(const size_t &i) const;
string_view at(const size_t &i) const;
string_view operator[](const size_t &i) const;
explicit operator std::string() const;
using string_view::string_view;
@ -81,50 +84,14 @@ struct arr::const_iterator
const_iterator &operator++();
friend bool operator==(const arr::const_iterator &, const arr::const_iterator &);
friend bool operator!=(const arr::const_iterator &, const arr::const_iterator &);
friend bool operator<=(const arr::const_iterator &, const arr::const_iterator &);
friend bool operator>=(const arr::const_iterator &, const arr::const_iterator &);
friend bool operator<(const arr::const_iterator &, const arr::const_iterator &);
friend bool operator>(const arr::const_iterator &, const arr::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 &);
friend bool operator>(const const_iterator &, const const_iterator &);
};
inline bool
operator==(const arr::const_iterator &a, const arr::const_iterator &b)
{
return a.start == b.start;
}
inline bool
operator!=(const arr::const_iterator &a, const arr::const_iterator &b)
{
return a.start != b.start;
}
inline bool
operator<=(const arr::const_iterator &a, const arr::const_iterator &b)
{
return a.start <= b.start;
}
inline bool
operator>=(const arr::const_iterator &a, const arr::const_iterator &b)
{
return a.start >= b.start;
}
inline bool
operator<(const arr::const_iterator &a, const arr::const_iterator &b)
{
return a.start < b.start;
}
inline bool
operator>(const arr::const_iterator &a, const arr::const_iterator &b)
{
return a.start > b.start;
}
} // namespace json
} // namespace ircd
@ -137,19 +104,31 @@ const
}
inline ircd::string_view
ircd::json::arr::operator[](size_t i)
ircd::json::arr::operator[](const size_t &i)
const
{
const auto it(find(i));
return it != end()? *it : string_view{};
}
template<class T>
T
ircd::json::arr::at(const size_t &i)
const try
{
return lex_cast<T>(at(i));
}
catch(const bad_lex_cast &e)
{
throw type_error("indice %zu must cast to type %s", i, typeid(T).name());
}
inline ircd::string_view
ircd::json::arr::at(size_t i)
ircd::json::arr::at(const size_t &i)
const
{
const auto it(find(i));
return likely(it != end())? *it : throw not_found("[%zu]", i);
return likely(it != end())? *it : throw not_found("indice %zu", i);
}
inline ircd::json::arr::const_iterator
@ -167,3 +146,39 @@ const
{
return std::distance(begin(), end());
}
inline bool
ircd::json::operator==(const arr::const_iterator &a, const arr::const_iterator &b)
{
return a.start == b.start;
}
inline bool
ircd::json::operator!=(const arr::const_iterator &a, const arr::const_iterator &b)
{
return a.start != b.start;
}
inline bool
ircd::json::operator<=(const arr::const_iterator &a, const arr::const_iterator &b)
{
return a.start <= b.start;
}
inline bool
ircd::json::operator>=(const arr::const_iterator &a, const arr::const_iterator &b)
{
return a.start >= b.start;
}
inline bool
ircd::json::operator<(const arr::const_iterator &a, const arr::const_iterator &b)
{
return a.start < b.start;
}
inline bool
ircd::json::operator>(const arr::const_iterator &a, const arr::const_iterator &b)
{
return a.start > b.start;
}

View file

@ -46,11 +46,14 @@ struct doc
const_iterator end() const;
const_iterator begin() const;
const_iterator find(const char *const &name) const;
const_iterator find(const string_view &name) const;
size_t count() const;
string_view at(const char *const &name) const;
string_view operator[](const char *const &name) 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;
explicit operator std::string() const;
using string_view::string_view;
@ -66,11 +69,13 @@ struct doc::member
:std::pair<string_view, string_view>{first, second}
{}
friend bool operator==(const doc::member &, const doc::member &);
friend bool operator<=(const doc::member &, const doc::member &);
friend bool operator>=(const doc::member &, const doc::member &);
friend bool operator<(const doc::member &, const doc::member &);
friend bool operator>(const doc::member &, const doc::member &);
friend bool operator==(const member &, const member &);
friend bool operator!=(const member &, const member &);
friend bool operator<=(const member &, const member &);
friend bool operator>=(const member &, const member &);
friend bool operator<(const member &, const member &);
friend bool operator>(const member &, const member &);
friend std::ostream &operator<<(std::ostream &, const doc::member &);
};
@ -87,7 +92,7 @@ struct doc::const_iterator
const char *start;
const char *stop;
mutable member state;
member state;
const_iterator(const char *const &start, const char *const &stop)
:start{start}
@ -100,112 +105,67 @@ struct doc::const_iterator
const_iterator &operator++();
friend bool operator==(const doc::const_iterator &, const doc::const_iterator &);
friend bool operator!=(const doc::const_iterator &, const doc::const_iterator &);
friend bool operator<=(const doc::const_iterator &, const doc::const_iterator &);
friend bool operator>=(const doc::const_iterator &, const doc::const_iterator &);
friend bool operator<(const doc::const_iterator &, const doc::const_iterator &);
friend bool operator>(const doc::const_iterator &, const doc::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 &);
friend bool operator>(const const_iterator &, const const_iterator &);
};
inline bool
operator==(const doc::const_iterator &a, const doc::const_iterator &b)
{
return a.start == b.start;
}
inline bool
operator!=(const doc::const_iterator &a, const doc::const_iterator &b)
{
return a.start != b.start;
}
inline bool
operator<=(const doc::const_iterator &a, const doc::const_iterator &b)
{
return a.start <= b.start;
}
inline bool
operator>=(const doc::const_iterator &a, const doc::const_iterator &b)
{
return a.start >= b.start;
}
inline bool
operator<(const doc::const_iterator &a, const doc::const_iterator &b)
{
return a.start < b.start;
}
inline bool
operator>(const doc::const_iterator &a, const doc::const_iterator &b)
{
return a.start > b.start;
}
inline bool
operator==(const doc::member &a, const doc::member &b)
{
return a.first == b.first;
}
inline bool
operator<=(const doc::member &a, const doc::member &b)
{
return a.first <= b.first;
}
inline bool
operator>=(const doc::member &a, const doc::member &b)
{
return a.first >= b.first;
}
inline bool
operator<(const doc::member &a, const doc::member &b)
{
return a.first < b.first;
}
inline bool
operator>(const doc::member &a, const doc::member &b)
{
return a.first > b.first;
}
} // namespace json
} // namespace ircd
inline bool
ircd::json::doc::contains(const string_view &s)
inline ircd::string_view
ircd::json::doc::operator[](const string_view &name)
const
{
return s.begin() >= this->string_view::begin() &&
s.end() <= this->string_view::end();
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::operator[](const char *const &name)
ircd::json::doc::at(const string_view &name)
const
{
const auto it(find(name));
return it != end()? it->second : string_view{};
}
inline ircd::string_view
ircd::json::doc::at(const char *const &name)
const
{
const auto it(find(name));
const auto p(split(name, '.'));
const auto it(find(p.first));
if(unlikely(it == end()))
throw not_found("name \"%s\"", name);
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 char *const &name)
ircd::json::doc::find(const string_view &name)
const
{
return std::find_if(begin(), end(), [&name]
@ -221,3 +181,83 @@ const
{
return std::distance(begin(), end());
}
inline bool
ircd::json::doc::contains(const string_view &s)
const
{
return s.begin() >= this->string_view::begin() &&
s.end() <= this->string_view::end();
}
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;
}

View file

@ -49,8 +49,6 @@ struct obj
size_t count() const;
size_t size() const;
explicit operator std::string() const;
const_iterator find(const string_view &name) const;
bool has(const string_view &name) const;
@ -61,8 +59,10 @@ struct obj
void erase(const const_iterator &s);
bool erase(const string_view &name);
explicit operator std::string() const;
obj(std::initializer_list<member>);
obj(const doc &d);
obj(const doc &d, const bool &recurse = false);
obj() = default;
obj(obj &&) = default;
obj(const obj &) = delete;
@ -75,33 +75,21 @@ struct obj
struct obj::member
:std::pair<val, val>
{
member(const string_view &k, const string_view &v)
:std::pair<val, val>{k, v}
{}
member(const string_view &k, const obj *const &v)
:std::pair<val, val>{k, *v}
{}
member(const string_view &k, std::initializer_list<member> v)
:std::pair<val, val>{k, val{*new obj(v), true}}
{}
explicit member(const string_view &k)
:std::pair<val, val>{k, string_view{}}
{}
explicit member(const doc::member &dm)
:member{dm.first, dm.second}
{}
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);
member() = default;
friend bool operator<(const member &a, const string_view &b);
friend bool operator==(const member &a, const string_view &b);
friend bool operator<(const member &a, const member &b);
friend bool operator==(const member &a, const member &b);
friend bool operator!=(const member &a, const member &b);
friend bool operator<(const member &a, const member &b);
friend bool operator==(const member &a, const string_view &b);
friend bool operator!=(const member &a, const string_view &b);
friend bool operator<(const member &a, const string_view &b);
friend std::ostream &operator<<(std::ostream &, const member &);
};
struct obj::const_iterator
@ -124,13 +112,14 @@ struct obj::const_iterator
{}
public:
auto operator==(const const_iterator &o) const { return it == o.it; }
auto operator!=(const const_iterator &o) const { return it != o.it; }
value_type *operator->() const { return it.operator->(); }
value_type &operator*() const { return it.operator*(); }
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
@ -143,17 +132,6 @@ const
return at(name);
}
inline const ircd::json::val &
ircd::json::obj::at(const string_view &name)
const
{
const auto it(find(name));
if(unlikely(it == end()))
throw not_found("name \"%s\"", name.data());
return it->second;
}
inline bool
ircd::json::obj::has(const string_view &name)
const
@ -208,6 +186,53 @@ const
return { std::end(idx) };
}
template<class K,
class V>
ircd::json::obj::member::member(const K &k,
V&& v)
:std::pair<val, val>
{
val { k }, val { std::forward<V>(v) }
}
{}
template<class K>
ircd::json::obj::member::member(const K &k,
std::initializer_list<member> v)
:std::pair<val, val>
{
val { k }, val { std::make_unique<obj>(std::move(v)) }
}
{}
inline
ircd::json::obj::member::member(const doc::member &m)
:std::pair<val, val>
{
m.first, val { m.second, type(m.second) }
}
{}
inline
ircd::json::obj::member::member(const string_view &k)
:std::pair<val, val>
{
k, string_view{}
}
{}
inline bool
ircd::json::operator<(const obj::member &a, const obj::member &b)
{
return a.first < b.first;
}
inline bool
ircd::json::operator!=(const obj::member &a, const obj::member &b)
{
return a.first != b.first;
}
inline bool
ircd::json::operator==(const obj::member &a, const obj::member &b)
{
@ -215,9 +240,15 @@ ircd::json::operator==(const obj::member &a, const obj::member &b)
}
inline bool
ircd::json::operator<(const obj::member &a, const obj::member &b)
ircd::json::operator<(const obj::member &a, const string_view &b)
{
return a.first < b.first;
return string_view(a.first.string, a.first.len) < b;
}
inline bool
ircd::json::operator!=(const obj::member &a, const string_view &b)
{
return string_view(a.first.string, a.first.len) == b;
}
inline bool
@ -227,7 +258,19 @@ ircd::json::operator==(const obj::member &a, const string_view &b)
}
inline bool
ircd::json::operator<(const obj::member &a, const string_view &b)
ircd::json::operator<(const obj::const_iterator &a, const obj::const_iterator &b)
{
return string_view(a.first.string, a.first.len) < b;
return a.it < b.it;
}
inline bool
ircd::json::operator!=(const obj::const_iterator &a, const obj::const_iterator &b)
{
return a.it != b.it;
}
inline bool
ircd::json::operator==(const obj::const_iterator &a, const obj::const_iterator &b)
{
return a.it == b.it;
}

View file

@ -29,32 +29,31 @@ struct val
{
union // xxx std::variant
{
uint64_t integer;
int64_t integer;
double floating;
const char *string;
const struct obj *object;
const struct array *array;
};
uint64_t len : 59;
uint64_t len : 58;
enum type type : 3;
uint64_t serial : 1;
uint64_t alloc : 1;
uint64_t floats : 1;
public:
size_t size() const;
operator string_view() const;
explicit operator std::string() const;
val(const uint64_t &integer);
val(const struct obj &object,
const bool &alloc = false);
val(const string_view &sv,
const enum type &type = STRING,
const bool &serial = true);
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() = default;
val(val &&) noexcept;
val(const val &) = delete;
@ -62,46 +61,93 @@ struct val
val &operator=(const val &) = delete;
~val() 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 &);
};
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} } {}
static_assert(sizeof(val) == 16, "");
} // namespace json
} // namespace ircd
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,
const bool &serial)
const enum type &type)
:string{sv.data()}
,len{sv.size()}
,type{type}
,serial{serial}
,serial{true}
,alloc{false}
{
}
,floats{false}
{}
inline
ircd::json::val::val(const uint64_t &integer)
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 &object,
const bool &alloc)
:object{&object}
ircd::json::val::val(const struct obj *const &object)
:object{object}
,len{0}
,type{OBJECT}
,serial{false}
,alloc{alloc}
,alloc{false}
,floats{false}
{}
inline
ircd::json::val::val(std::unique_ptr<obj> object)
:object{object.get()}
,len{0}
,type{OBJECT}
,serial{false}
,alloc{true}
,floats{false}
{
object.release();
}
inline
@ -112,12 +158,12 @@ noexcept
,type{other.type}
,serial{other.serial}
,alloc{other.alloc}
,floats{other.floats}
{
other.alloc = false;
}
inline
ircd::json::val &
inline ircd::json::val &
ircd::json::val::operator=(val &&other)
noexcept
{
@ -128,23 +174,12 @@ noexcept
serial = other.serial;
alloc = other.alloc;
other.alloc = false;
floats = other.floats;
return *this;
}
inline bool
ircd::json::operator<(const val &a, const val &b)
inline enum ircd::json::type
ircd::json::type(const val &a)
{
if(unlikely(a.type != STRING || b.type != STRING))
throw type_error("cannot compare values");
return static_cast<string_view>(a) < static_cast<string_view>(b);
}
inline bool
ircd::json::operator==(const val &a, const val &b)
{
if(unlikely(a.type != STRING || b.type != STRING))
throw type_error("cannot compare values");
return static_cast<string_view>(a) == static_cast<string_view>(b);
return a.type;
}