mirror of
https://github.com/matrix-construct/construct
synced 2024-12-27 07:54:05 +01:00
ircd::json: Improve stringification interface et al.
This commit is contained in:
parent
77ba8696d9
commit
147a49a86c
11 changed files with 375 additions and 305 deletions
|
@ -83,6 +83,11 @@ namespace ircd::json
|
||||||
|
|
||||||
using path = std::initializer_list<string_view>;
|
using path = std::initializer_list<string_view>;
|
||||||
std::ostream &operator<<(std::ostream &, const path &);
|
std::ostream &operator<<(std::ostream &, const path &);
|
||||||
|
|
||||||
|
size_t serialized(const string_view &);
|
||||||
|
template<class... T> string_view stringify(const mutable_buffer &&mb, T&&... t);
|
||||||
|
template<class... T> size_t print(char *const &buf, const size_t &max, T&&... t);
|
||||||
|
template<class... T> std::string string(T&&... t);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "json/array.h"
|
#include "json/array.h"
|
||||||
|
@ -99,6 +104,55 @@ namespace ircd
|
||||||
using json::operator<<;
|
using json::operator<<;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Convenience template for const rvalue mutable_buffers or basically
|
||||||
|
// allowing a bracket initialization of a mutable_buffer in the argument
|
||||||
|
// to stringify()
|
||||||
|
//
|
||||||
|
template<class... T>
|
||||||
|
ircd::string_view
|
||||||
|
ircd::json::stringify(const mutable_buffer &&mb,
|
||||||
|
T&&... t)
|
||||||
|
{
|
||||||
|
mutable_buffer mbc(mb);
|
||||||
|
return stringify(mbc, std::forward<T>(t)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Convenience template using the syntax print(buf, sizeof(buf), ...)
|
||||||
|
// which stringifies with null termination into buffer.
|
||||||
|
//
|
||||||
|
template<class... T>
|
||||||
|
size_t
|
||||||
|
ircd::json::print(char *const &buf,
|
||||||
|
const size_t &max,
|
||||||
|
T&&... t)
|
||||||
|
{
|
||||||
|
if(!max)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mutable_buffer mb{buf, max - 1};
|
||||||
|
const auto sv(stringify(mb, std::forward<T>(t)...));
|
||||||
|
assert(sv.size() < max);
|
||||||
|
buf[sv.size()] = '\0';
|
||||||
|
return sv.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Convenience template using the syntax string(...) which returns
|
||||||
|
// an std::string of the printed JSON
|
||||||
|
//
|
||||||
|
template<class... T>
|
||||||
|
std::string
|
||||||
|
ircd::json::string(T&&... t)
|
||||||
|
{
|
||||||
|
std::string ret;
|
||||||
|
ret.resize(serialized(std::forward<T>(t)...), char{});
|
||||||
|
const auto buf{const_cast<char *>(ret.data())};
|
||||||
|
print(buf, ret.size() + 1, std::forward<T>(t)...);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
inline std::ostream &
|
inline std::ostream &
|
||||||
ircd::json::operator<<(std::ostream &s, const path &p)
|
ircd::json::operator<<(std::ostream &s, const path &p)
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,8 +57,7 @@ struct ircd::json::array
|
||||||
|
|
||||||
using string_view::string_view;
|
using string_view::string_view;
|
||||||
|
|
||||||
friend array serialize(const array &, char *&buf, char *const &stop);
|
friend string_view stringify(mutable_buffer &, const array &);
|
||||||
friend size_t print(char *const &buf, const size_t &max, const array &);
|
|
||||||
friend std::ostream &operator<<(std::ostream &, const array &);
|
friend std::ostream &operator<<(std::ostream &, const array &);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -47,26 +47,24 @@ struct ircd::json::builder
|
||||||
builder(const builder *const &parent, const members *const &);
|
builder(const builder *const &parent, const members *const &);
|
||||||
builder(const builder *const &parent, member);
|
builder(const builder *const &parent, member);
|
||||||
|
|
||||||
friend string_view stringify(char *const &buf, const size_t &max, const builder &);
|
friend string_view stringify(mutable_buffer &, const builder &);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline ircd::string_view
|
inline ircd::string_view
|
||||||
ircd::json::stringify(char *const &buf,
|
ircd::json::stringify(mutable_buffer &head,
|
||||||
const size_t &max,
|
|
||||||
const builder &builder)
|
const builder &builder)
|
||||||
{
|
{
|
||||||
size_t i(0);
|
const auto num{builder.count()};
|
||||||
const auto num(builder.count());
|
|
||||||
const member *m[num];
|
const member *m[num];
|
||||||
|
|
||||||
|
size_t i(0);
|
||||||
builder.for_each([&i, &m]
|
builder.for_each([&i, &m]
|
||||||
(const auto &member)
|
(const auto &member)
|
||||||
{
|
{
|
||||||
m[i++] = &member;
|
m[i++] = &member;
|
||||||
});
|
});
|
||||||
|
|
||||||
char *p(buf);
|
return stringify(head, m, m + num);
|
||||||
char *const e(buf + max);
|
|
||||||
return serialize(m, m + num, p, e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
|
|
|
@ -44,7 +44,7 @@ struct ircd::json::index
|
||||||
|
|
||||||
bool empty() const;
|
bool empty() const;
|
||||||
size_t count() const;
|
size_t count() const;
|
||||||
size_t size() const;
|
size_t serialized() const;
|
||||||
|
|
||||||
const_iterator find(const string_view &name) const;
|
const_iterator find(const string_view &name) const;
|
||||||
bool has(const string_view &name) const;
|
bool has(const string_view &name) const;
|
||||||
|
@ -70,8 +70,8 @@ struct ircd::json::index
|
||||||
friend index &operator+=(index &, const object &); // integration
|
friend index &operator+=(index &, const object &); // integration
|
||||||
friend index operator+(const object &, const object &); // integral
|
friend index operator+(const object &, const object &); // integral
|
||||||
|
|
||||||
friend object serialize(const index &, char *&start, char *const &stop);
|
friend size_t serialized(const index &);
|
||||||
friend size_t print(char *const &buf, const size_t &max, const index &);
|
friend string_view stringify(mutable_buffer &, const index &);
|
||||||
friend std::ostream &operator<<(std::ostream &, const index &);
|
friend std::ostream &operator<<(std::ostream &, const index &);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -34,20 +34,16 @@
|
||||||
namespace ircd::json
|
namespace ircd::json
|
||||||
{
|
{
|
||||||
struct member;
|
struct member;
|
||||||
|
|
||||||
size_t size(const member *const &begin, const member *const &end);
|
|
||||||
object serialize(const member *const *const &begin, const member *const *const &end, char *&start, char *const &stop);
|
|
||||||
object serialize(const member *const &begin, const member *const &end, char *&start, char *const &stop);
|
|
||||||
size_t print(char *const &buf, const size_t &max, const member *const &begin, const member *const &end);
|
|
||||||
std::string string(const member *const &begin, const member *const &end);
|
|
||||||
|
|
||||||
using members = std::initializer_list<member>;
|
using members = std::initializer_list<member>;
|
||||||
object serialize(const members &, char *&start, char *const &stop);
|
|
||||||
size_t print(char *const &buf, const size_t &max, const members &);
|
|
||||||
std::string string(const members &);
|
|
||||||
|
|
||||||
array serialize(const std::vector<json::object> &, char *&start, char *const &stop);
|
size_t serialized(const member *const &begin, const member *const &end);
|
||||||
string_view stringify(char *const &buf, const size_t &max, const members &);
|
size_t serialized(const members &);
|
||||||
|
|
||||||
|
string_view stringify(mutable_buffer &, const member *const *const &begin, const member *const *const &end);
|
||||||
|
string_view stringify(mutable_buffer &, const member *const &begin, const member *const &end);
|
||||||
|
string_view stringify(mutable_buffer &, const members &);
|
||||||
|
|
||||||
|
string_view stringify(mutable_buffer &, const std::vector<json::object> &);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ircd::json::member
|
struct ircd::json::member
|
||||||
|
@ -67,6 +63,8 @@ struct ircd::json::member
|
||||||
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 bool operator<(const member &a, const string_view &b);
|
||||||
|
|
||||||
|
friend size_t serialized(const member &);
|
||||||
|
friend string_view stringify(mutable_buffer &, const member &);
|
||||||
friend std::ostream &operator<<(std::ostream &, const member &);
|
friend std::ostream &operator<<(std::ostream &, const member &);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -111,9 +111,8 @@ struct ircd::json::object
|
||||||
explicit operator std::string() const;
|
explicit operator std::string() const;
|
||||||
|
|
||||||
// rewrite onto streams or buffers etc
|
// rewrite onto streams or buffers etc
|
||||||
|
friend string_view stringify(mutable_buffer &, const object &);
|
||||||
friend std::ostream &operator<<(std::ostream &, const object &);
|
friend std::ostream &operator<<(std::ostream &, const object &);
|
||||||
friend object serialize(const object &, char *&buf, char *const &stop);
|
|
||||||
friend size_t print(char *const &buf, const size_t &max, const object &);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ircd::json::object::member
|
struct ircd::json::object::member
|
||||||
|
@ -131,6 +130,7 @@ struct ircd::json::object::member
|
||||||
friend bool operator>(const member &, const member &);
|
friend bool operator>(const member &, const member &);
|
||||||
|
|
||||||
// writes a single member onto stream
|
// writes a single member onto stream
|
||||||
|
friend string_view stringify(mutable_buffer &, const object::member &);
|
||||||
friend std::ostream &operator<<(std::ostream &, const object::member &);
|
friend std::ostream &operator<<(std::ostream &, const object::member &);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -596,6 +596,22 @@ tuple<T...>::tuple(const std::initializer_list<member> &members)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class tuple,
|
||||||
|
class it_a,
|
||||||
|
class it_b,
|
||||||
|
class closure>
|
||||||
|
constexpr void
|
||||||
|
_key_transform(it_a it,
|
||||||
|
const it_b end,
|
||||||
|
closure&& lambda)
|
||||||
|
{
|
||||||
|
for(size_t i(0); i < tuple::size() && it != end; ++i)
|
||||||
|
{
|
||||||
|
*it = lambda(key<tuple, i>());
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<class tuple,
|
template<class tuple,
|
||||||
class it_a,
|
class it_a,
|
||||||
class it_b>
|
class it_b>
|
||||||
|
@ -603,11 +619,8 @@ constexpr void
|
||||||
_key_transform(it_a it,
|
_key_transform(it_a it,
|
||||||
const it_b end)
|
const it_b end)
|
||||||
{
|
{
|
||||||
for(size_t i(0); i < tuple::size(); ++i)
|
for(size_t i(0); i < tuple::size() && it != end; ++i)
|
||||||
{
|
{
|
||||||
if(it == end)
|
|
||||||
break;
|
|
||||||
|
|
||||||
*it = key<tuple, i>();
|
*it = key<tuple, i>();
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
@ -632,6 +645,28 @@ _key_transform(const tuple<T...> &tuple,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class it_a,
|
||||||
|
class it_b,
|
||||||
|
class closure,
|
||||||
|
class... T>
|
||||||
|
void
|
||||||
|
_member_transform(const tuple<T...> &tuple,
|
||||||
|
it_a it,
|
||||||
|
const it_b end,
|
||||||
|
closure&& lambda)
|
||||||
|
{
|
||||||
|
until(tuple, [&it, &end, &lambda]
|
||||||
|
(const auto &key, const auto &val)
|
||||||
|
{
|
||||||
|
if(it == end)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*it = lambda(key, val);
|
||||||
|
++it;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template<class it_a,
|
template<class it_a,
|
||||||
class it_b,
|
class it_b,
|
||||||
class... T>
|
class... T>
|
||||||
|
@ -640,46 +675,73 @@ _member_transform(const tuple<T...> &tuple,
|
||||||
it_a it,
|
it_a it,
|
||||||
const it_b end)
|
const it_b end)
|
||||||
{
|
{
|
||||||
for_each(tuple, [&it, &end]
|
until(tuple, [&it, &end]
|
||||||
(const auto &key, const auto &val)
|
(const auto &key, const auto &val)
|
||||||
{
|
{
|
||||||
if(it != end)
|
if(it == end)
|
||||||
{
|
return false;
|
||||||
|
|
||||||
*it = { key, val };
|
*it = { key, val };
|
||||||
++it;
|
++it;
|
||||||
}
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class... T>
|
template<class T>
|
||||||
object
|
constexpr bool
|
||||||
serialize(const tuple<T...> &tuple,
|
serialized_lex_cast()
|
||||||
char *&start,
|
|
||||||
char *const &stop)
|
|
||||||
{
|
{
|
||||||
std::array<member, tuple.size()> members;
|
using type = typename std::remove_reference<T>::type;
|
||||||
_member_transform(tuple, begin(members), end(members));
|
return std::is_arithmetic<type>::value;
|
||||||
return serialize(begin(members), end(members), start, stop);
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
typename std::enable_if<serialized_lex_cast<T>(), size_t>::type
|
||||||
|
serialized(T&& t)
|
||||||
|
{
|
||||||
|
return lex_cast(t).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class... T>
|
template<class... T>
|
||||||
size_t
|
size_t
|
||||||
print(char *const &buf,
|
serialized(const tuple<T...> &t)
|
||||||
const size_t &max,
|
{
|
||||||
|
constexpr const size_t member_count
|
||||||
|
{
|
||||||
|
tuple<T...>::size()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Number of commas for this object is one less than the member count, or 0
|
||||||
|
const size_t commas
|
||||||
|
{
|
||||||
|
member_count? member_count - 1 : 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// 2 for the {} and the comma count
|
||||||
|
const size_t overhead
|
||||||
|
{
|
||||||
|
2 + commas
|
||||||
|
};
|
||||||
|
|
||||||
|
std::array<size_t, member_count> sizes;
|
||||||
|
_member_transform(t, begin(sizes), end(sizes), []
|
||||||
|
(const string_view &key, auto&& val)
|
||||||
|
{
|
||||||
|
// " " :
|
||||||
|
return 1 + key.size() + 1 + 1 + serialized(val);
|
||||||
|
});
|
||||||
|
|
||||||
|
return std::accumulate(begin(sizes), end(sizes), overhead);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class... T>
|
||||||
|
string_view
|
||||||
|
stringify(mutable_buffer &buf,
|
||||||
const tuple<T...> &tuple)
|
const tuple<T...> &tuple)
|
||||||
{
|
{
|
||||||
std::array<member, tuple.size()> members;
|
std::array<member, tuple.size()> members;
|
||||||
_member_transform(tuple, begin(members), end(members));
|
_member_transform(tuple, begin(members), end(members));
|
||||||
return print(buf, max, begin(members), end(members));
|
return stringify(buf, begin(members), end(members));
|
||||||
}
|
|
||||||
|
|
||||||
template<class... T>
|
|
||||||
std::string
|
|
||||||
string(const tuple<T...> &tuple)
|
|
||||||
{
|
|
||||||
std::array<member, tuple.size()> members;
|
|
||||||
_member_transform(tuple, begin(members), end(members));
|
|
||||||
return string(begin(members), end(members));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class... T>
|
template<class... T>
|
||||||
|
|
|
@ -55,7 +55,7 @@ struct ircd::json::value
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool empty() const;
|
bool empty() const;
|
||||||
size_t size() const;
|
size_t serialized() const;
|
||||||
operator string_view() const;
|
operator string_view() const;
|
||||||
explicit operator std::string() const;
|
explicit operator std::string() const;
|
||||||
|
|
||||||
|
@ -80,6 +80,9 @@ struct ircd::json::value
|
||||||
friend bool operator>=(const value &a, const value &b);
|
friend bool operator>=(const value &a, const value &b);
|
||||||
friend bool operator<(const value &a, const value &b);
|
friend bool operator<(const value &a, const value &b);
|
||||||
friend bool operator>(const value &a, const value &b);
|
friend bool operator>(const value &a, const value &b);
|
||||||
|
|
||||||
|
friend size_t serialized(const value &);
|
||||||
|
friend string_view stringify(mutable_buffer &, const value &);
|
||||||
friend std::ostream &operator<<(std::ostream &, const value &);
|
friend std::ostream &operator<<(std::ostream &, const value &);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
433
ircd/json.cc
433
ircd/json.cc
|
@ -248,6 +248,12 @@ struct printer
|
||||||
template<class generator>
|
template<class generator>
|
||||||
bool operator()(char *&out, char *const &stop, generator&& gen) const;
|
bool operator()(char *&out, char *const &stop, generator&& gen) const;
|
||||||
|
|
||||||
|
template<class... args>
|
||||||
|
bool operator()(mutable_buffer &out, args&&... a) const
|
||||||
|
{
|
||||||
|
return operator()(begin(out), end(out), std::forward<args>(a)...);
|
||||||
|
}
|
||||||
|
|
||||||
printer();
|
printer();
|
||||||
}
|
}
|
||||||
const printer;
|
const printer;
|
||||||
|
@ -259,23 +265,6 @@ struct ostreamer
|
||||||
}
|
}
|
||||||
const ostreamer;
|
const ostreamer;
|
||||||
|
|
||||||
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::member *const &begin, const index::member *const &end);
|
|
||||||
size_t print(char *const &buf, const size_t &max, const index &);
|
|
||||||
size_t print(char *const &buf, const size_t &max, const members &);
|
|
||||||
|
|
||||||
array serialize(const array &, char *&start, char *const &stop);
|
|
||||||
object serialize(const object &, char *&start, char *const &stop);
|
|
||||||
object serialize(const index::member *const &beg, const index::member *const &end, char *&start, char *const &stop);
|
|
||||||
object serialize(const index &, char *&start, char *const &stop);
|
|
||||||
object serialize(const members &, char *&start, char *const &stop);
|
|
||||||
|
|
||||||
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 json
|
||||||
} // namespace ircd
|
} // namespace ircd
|
||||||
|
|
||||||
|
@ -318,18 +307,26 @@ ircd::json::printer::printer()
|
||||||
{
|
{
|
||||||
const auto recursor([this](auto &a, auto &b, auto &c)
|
const auto recursor([this](auto &a, auto &b, auto &c)
|
||||||
{
|
{
|
||||||
const auto recurse_array([&]
|
const auto recurse_array([&a]
|
||||||
{
|
{
|
||||||
char *out(const_cast<char *>(a.data()));
|
mutable_buffer mb
|
||||||
const auto r(serialize(json::array(a), out, out + a.size()));
|
{
|
||||||
a.resize(size_t(out - r.data()));
|
const_cast<char *>(a.data()), a.size()
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto r(stringify(mb, json::array(a)));
|
||||||
|
a.resize(r.size());
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto recurse_object([&]
|
const auto recurse_object([&a]
|
||||||
{
|
{
|
||||||
char *out(const_cast<char *>(a.data()));
|
mutable_buffer mb
|
||||||
const auto d(serialize(json::object(a), out, out + a.size()));
|
{
|
||||||
a.resize(size_t(out - d.data()));
|
const_cast<char *>(a.data()), a.size()
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto r(stringify(mb, json::object(a)));
|
||||||
|
a.resize(r.size());
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto quote_string([&]
|
const auto quote_string([&]
|
||||||
|
@ -400,104 +397,20 @@ const
|
||||||
return karma::generate(out, gg);
|
return karma::generate(out, gg);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
|
||||||
ircd::json::string(const members &list)
|
|
||||||
{
|
|
||||||
return string(std::begin(list), std::end(list));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
ircd::json::string(const index::member *const &begin,
|
|
||||||
const index::member *const &end)
|
|
||||||
{
|
|
||||||
std::string ret(size(begin, end), char());
|
|
||||||
print(const_cast<char *>(ret.data()), ret.size() + 1, begin, end);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
ircd::json::print(char *const &buf,
|
|
||||||
const size_t &max,
|
|
||||||
const index &obj)
|
|
||||||
{
|
|
||||||
if(unlikely(!max))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
char *out(buf);
|
|
||||||
serialize(obj, out, out + (max - 1));
|
|
||||||
*out = '\0';
|
|
||||||
return out - buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
ircd::string_view
|
ircd::string_view
|
||||||
ircd::json::stringify(char *const &buf,
|
ircd::json::stringify(mutable_buffer &buf,
|
||||||
const size_t &max,
|
const std::vector<json::object> &v)
|
||||||
const members &list)
|
|
||||||
{
|
{
|
||||||
const auto len
|
const auto print_member([&buf](const string_view &elem)
|
||||||
{
|
{
|
||||||
print(buf, max, std::begin(list), std::end(list))
|
//printer(buf, printer.elem, elem);
|
||||||
};
|
const auto cpsz(std::min(size(buf), elem.size()));
|
||||||
|
memcpy(begin(buf), elem.data(), cpsz);
|
||||||
return string_view{buf, len};
|
begin(buf) += cpsz;
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
ircd::json::print(char *const &buf,
|
|
||||||
const size_t &max,
|
|
||||||
const members &list)
|
|
||||||
{
|
|
||||||
return print(buf, max, std::begin(list), std::end(list));
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
ircd::json::print(char *const &buf,
|
|
||||||
const size_t &max,
|
|
||||||
const index::member *const &begin,
|
|
||||||
const index::member *const &end)
|
|
||||||
{
|
|
||||||
if(unlikely(!max))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
char *out(buf);
|
|
||||||
serialize(begin, end, out, out + (max - 1));
|
|
||||||
*out = '\0';
|
|
||||||
return out - buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
ircd::json::object
|
|
||||||
ircd::json::serialize(const members &list,
|
|
||||||
char *&out,
|
|
||||||
char *const &stop)
|
|
||||||
{
|
|
||||||
return serialize(std::begin(list), std::end(list), out, stop);
|
|
||||||
}
|
|
||||||
|
|
||||||
ircd::json::object
|
|
||||||
ircd::json::serialize(const index &obj,
|
|
||||||
char *&out,
|
|
||||||
char *const &stop)
|
|
||||||
{
|
|
||||||
const index::member *const &begin(&obj.idx.front());
|
|
||||||
const index::member *const &end(begin + obj.idx.size());
|
|
||||||
return serialize(begin, end, out, stop);
|
|
||||||
}
|
|
||||||
|
|
||||||
ircd::json::array
|
|
||||||
ircd::json::serialize(const std::vector<json::object> &v,
|
|
||||||
char *&out,
|
|
||||||
char *const &stop)
|
|
||||||
{
|
|
||||||
const auto print_member([&out, &stop](const string_view &elem)
|
|
||||||
{
|
|
||||||
//printer(out, stop, printer.elem, elem);
|
|
||||||
const auto cpsz(std::min(size_t(stop - out), elem.size()));
|
|
||||||
memcpy(out, elem.data(), cpsz);
|
|
||||||
out += cpsz;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
char *const start(out);
|
char *const start(begin(buf));
|
||||||
printer(out, stop, printer.array_begin);
|
printer(buf, printer.array_begin);
|
||||||
|
|
||||||
auto it(std::begin(v));
|
auto it(std::begin(v));
|
||||||
if(it != std::end(v))
|
if(it != std::end(v))
|
||||||
|
@ -505,66 +418,80 @@ ircd::json::serialize(const std::vector<json::object> &v,
|
||||||
print_member(*it);
|
print_member(*it);
|
||||||
for(++it; it != std::end(v); ++it)
|
for(++it; it != std::end(v); ++it)
|
||||||
{
|
{
|
||||||
printer(out, stop, printer.value_sep);
|
printer(buf, printer.value_sep);
|
||||||
print_member(*it);
|
print_member(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printer(out, stop, printer.array_end);
|
printer(buf, printer.array_end);
|
||||||
return string_view{start, out};
|
return string_view{start, begin(buf)};
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::json::object
|
ircd::string_view
|
||||||
ircd::json::serialize(const index::member *const &begin,
|
ircd::json::stringify(mutable_buffer &buf,
|
||||||
const index::member *const &end,
|
const members &list)
|
||||||
char *&out,
|
{
|
||||||
char *const &stop)
|
return stringify(buf, std::begin(list), std::end(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
ircd::string_view
|
||||||
|
ircd::json::stringify(mutable_buffer &buf,
|
||||||
|
const index &obj)
|
||||||
|
{
|
||||||
|
const member *const &begin(&obj.idx.front());
|
||||||
|
const member *const &end(begin + obj.idx.size());
|
||||||
|
return stringify(buf, begin, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
ircd::string_view
|
||||||
|
ircd::json::stringify(mutable_buffer &buf,
|
||||||
|
const member *const &begin,
|
||||||
|
const member *const &end)
|
||||||
{
|
{
|
||||||
const auto num(std::distance(begin, end));
|
const auto num(std::distance(begin, end));
|
||||||
const index::member *vec[num];
|
const member *vec[num];
|
||||||
for(auto i(0); i < num; ++i)
|
for(auto i(0); i < num; ++i)
|
||||||
vec[i] = begin + i;
|
vec[i] = begin + i;
|
||||||
|
|
||||||
return serialize(vec, vec + num, out, stop);
|
return stringify(buf, vec, vec + num);
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::json::object
|
ircd::string_view
|
||||||
ircd::json::serialize(const index::member *const *const &begin,
|
ircd::json::stringify(mutable_buffer &buf,
|
||||||
const index::member *const *const &end,
|
const member *const *const &b,
|
||||||
char *&out,
|
const member *const *const &e)
|
||||||
char *const &stop)
|
|
||||||
{
|
{
|
||||||
const auto print_string([&stop, &out](const value &value)
|
const auto print_string([&buf](const value &value)
|
||||||
{
|
{
|
||||||
printer(out, stop, printer.string, string_view{value});
|
printer(buf, printer.string, string_view{value});
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto print_literal([&stop, &out](const value &value)
|
const auto print_literal([&buf](const value &value)
|
||||||
{
|
{
|
||||||
printer(out, stop, printer.literal, string_view{value});
|
printer(buf, printer.literal, string_view{value});
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto print_object([&stop, &out](const value &value)
|
const auto print_object([&buf](const value &value)
|
||||||
{
|
{
|
||||||
if(value.serial)
|
if(value.serial)
|
||||||
{
|
{
|
||||||
printer(out, stop, printer.object, string_view{value});
|
printer(buf, printer.object, string_view{value});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(value.object);
|
assert(value.object);
|
||||||
serialize(*value.object, out, stop);
|
stringify(buf, *value.object);
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto print_array([&stop, &out](const value &value)
|
const auto print_array([&buf](const value &value)
|
||||||
{
|
{
|
||||||
if(value.serial)
|
if(value.serial)
|
||||||
{
|
{
|
||||||
//printer(out, stop, printer.array, value);
|
//printer(out, stop, printer.array, value);
|
||||||
const string_view data(value);
|
const string_view data(value);
|
||||||
const auto cpsz(std::min(size_t(stop - out), data.size()));
|
const auto cpsz(std::min(size(buf), data.size()));
|
||||||
memcpy(out, data.data(), cpsz);
|
memcpy(begin(buf), data.data(), cpsz);
|
||||||
out += cpsz;
|
begin(buf) += cpsz;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,27 +500,27 @@ ircd::json::serialize(const index::member *const *const &begin,
|
||||||
//serialize(*value.object, out, stop);
|
//serialize(*value.object, out, stop);
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto print_number([&stop, &out](const value &value)
|
const auto print_number([&buf](const value &value)
|
||||||
{
|
{
|
||||||
if(value.serial)
|
if(value.serial)
|
||||||
{
|
{
|
||||||
if(value.floats)
|
if(value.floats)
|
||||||
printer(out, stop, double_, string_view{value});
|
printer(buf, double_, string_view{value});
|
||||||
else
|
else
|
||||||
printer(out, stop, long_, string_view{value});
|
printer(buf, long_, string_view{value});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(value.floats)
|
if(value.floats)
|
||||||
printer(out, stop, double_, value.floating);
|
printer(buf, double_, value.floating);
|
||||||
else
|
else
|
||||||
printer(out, stop, long_, value.integer);
|
printer(buf, long_, value.integer);
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto print_member([&](const index::member &member)
|
const auto print_member([&](const member &member)
|
||||||
{
|
{
|
||||||
printer(out, stop, printer.name << printer.name_sep, member.first);
|
printer(buf, printer.name << printer.name_sep, member.first);
|
||||||
|
|
||||||
switch(member.second.type)
|
switch(member.second.type)
|
||||||
{
|
{
|
||||||
|
@ -605,40 +532,48 @@ ircd::json::serialize(const index::member *const *const &begin,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
char *const start(out);
|
char *const start(begin(buf));
|
||||||
printer(out, stop, printer.object_begin);
|
printer(buf, printer.object_begin);
|
||||||
|
|
||||||
auto it(begin);
|
auto it(b);
|
||||||
if(it != end)
|
if(it != e)
|
||||||
{
|
{
|
||||||
print_member(**it);
|
print_member(**it);
|
||||||
for(++it; it != end; ++it)
|
for(++it; it != e; ++it)
|
||||||
{
|
{
|
||||||
printer(out, stop, printer.value_sep);
|
printer(buf, printer.value_sep);
|
||||||
print_member(**it);
|
print_member(**it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printer(out, stop, printer.object_end);
|
printer(buf, printer.object_end);
|
||||||
return string_view{start, out};
|
return string_view{start, begin(buf)};
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::json::ostreamer::ostreamer()
|
ircd::json::ostreamer::ostreamer()
|
||||||
{
|
{
|
||||||
const auto recursor([this](auto &a, auto &b, auto &c)
|
const auto recursor([this](auto &a, auto &b, auto &c)
|
||||||
{
|
{
|
||||||
const auto recurse_array([&]
|
const auto recurse_array([&a]
|
||||||
{
|
{
|
||||||
char *out(const_cast<char *>(a.data()));
|
mutable_buffer mb
|
||||||
const auto r(serialize(json::array(a), out, out + a.size()));
|
{
|
||||||
a.resize(size_t(out - r.data()));
|
const_cast<char *>(a.data()), a.size()
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto r(stringify(mb, json::array(a)));
|
||||||
|
a.resize(r.size());
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto recurse_object([&]
|
const auto recurse_object([&a]
|
||||||
{
|
{
|
||||||
char *out(const_cast<char *>(a.data()));
|
mutable_buffer mb
|
||||||
const auto d(serialize(json::object(a), out, out + a.size()));
|
{
|
||||||
a.resize(size_t(out - d.data()));
|
const_cast<char *>(a.data()), a.size()
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto r(stringify(mb, json::object(a)));
|
||||||
|
a.resize(r.size());
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto quote_string([&]
|
const auto quote_string([&]
|
||||||
|
@ -735,7 +670,7 @@ ircd::json::operator<<(std::ostream &s, const index &obj)
|
||||||
karma::generate(osi, long_, value.integer);
|
karma::generate(osi, long_, value.integer);
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto stream_member([&](const index::member &member)
|
const auto stream_member([&](const member &member)
|
||||||
{
|
{
|
||||||
karma::generate(osi, ostreamer.name << ostreamer.name_sep, string_view(member.first));
|
karma::generate(osi, ostreamer.name << ostreamer.name_sep, string_view(member.first));
|
||||||
|
|
||||||
|
@ -766,6 +701,30 @@ ircd::json::operator<<(std::ostream &s, const index &obj)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::json::serialized(const members &m)
|
||||||
|
{
|
||||||
|
return serialized(std::begin(m), std::end(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::json::serialized(const member *const &begin,
|
||||||
|
const member *const &end)
|
||||||
|
{
|
||||||
|
const size_t ret(1 + !std::distance(begin, end));
|
||||||
|
return std::accumulate(begin, end, ret, []
|
||||||
|
(auto ret, const auto &member)
|
||||||
|
{
|
||||||
|
return ret += serialized(member) + 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::json::serialized(const member &member)
|
||||||
|
{
|
||||||
|
return serialized(member.first) + 1 + 1 + serialized(member.second);
|
||||||
|
}
|
||||||
|
|
||||||
ircd::json::index
|
ircd::json::index
|
||||||
ircd::json::operator+(const object &left, const object &right)
|
ircd::json::operator+(const object &left, const object &right)
|
||||||
{
|
{
|
||||||
|
@ -794,7 +753,7 @@ ircd::json::operator+=(index &left, const object &right)
|
||||||
if(deletion) // prevents adding the empty indicator as the new key!
|
if(deletion) // prevents adding the empty indicator as the new key!
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
left.idx.emplace_back(index::member{b});
|
left.idx.emplace_back(member{b});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,12 +763,12 @@ ircd::json::operator+=(index &left, const object &right)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &a(const_cast<index::member &>(*it));
|
auto &a(const_cast<member &>(*it));
|
||||||
switch(type(a.second))
|
switch(type(a.second))
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
a = index::member{b};
|
a = member{b};
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -825,7 +784,7 @@ ircd::json::operator+=(index &left, const object &right)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
a = index::member{string_view{a.first}, std::move(merged)};
|
a = member{string_view{a.first}, std::move(merged)};
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -839,15 +798,15 @@ ircd::json::index::index(recursive_t recursive,
|
||||||
:idx{object.count()}
|
:idx{object.count()}
|
||||||
{
|
{
|
||||||
std::transform(std::begin(object), std::end(object), std::begin(idx), [&]
|
std::transform(std::begin(object), std::end(object), std::begin(idx), [&]
|
||||||
(const object::member &m) -> index::member
|
(const object::member &m) -> member
|
||||||
{
|
{
|
||||||
switch(type(m.second))
|
switch(type(m.second))
|
||||||
{
|
{
|
||||||
case OBJECT:
|
case OBJECT:
|
||||||
return index::member{m.first, std::make_unique<index>(recursive, m.second)};
|
return member{m.first, std::make_unique<index>(recursive, m.second)};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return index::member{m};
|
return member{m};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -856,9 +815,9 @@ ircd::json::index::index(const object &object)
|
||||||
:idx{object.count()}
|
:idx{object.count()}
|
||||||
{
|
{
|
||||||
std::transform(std::begin(object), std::end(object), std::begin(idx), []
|
std::transform(std::begin(object), std::end(object), std::begin(idx), []
|
||||||
(const object::member &m) -> index::member
|
(const object::member &m) -> member
|
||||||
{
|
{
|
||||||
return index::member{m};
|
return member{m};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -945,35 +904,26 @@ const
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
ircd::json::size(const index::member *const &begin,
|
ircd::json::serialized(const index &index)
|
||||||
const index::member *const &end)
|
|
||||||
{
|
{
|
||||||
const size_t ret(1 + !std::distance(begin, end));
|
return index.serialized();
|
||||||
return std::accumulate(begin, end, ret, []
|
|
||||||
(auto ret, const auto &member)
|
|
||||||
{
|
|
||||||
return ret += member.first.size() + 1 + 1 + member.second.size() + 1;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
ircd::json::index::size()
|
ircd::json::index::serialized()
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
const size_t ret(1 + idx.empty());
|
const member *const &begin(&idx.front());
|
||||||
return std::accumulate(std::begin(idx), std::end(idx), ret, []
|
const member *const &end(begin + idx.size());
|
||||||
(auto ret, const auto &member)
|
return json::serialized(begin, end);
|
||||||
{
|
|
||||||
return ret += member.first.size() + 1 + 1 + member.second.size() + 1;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::json::index::operator std::string()
|
ircd::json::index::operator std::string()
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
std::string ret(size(), char());
|
const member *const &begin(&idx.front());
|
||||||
ret.resize(print(const_cast<char *>(ret.data()), ret.size() + 1, *this));
|
const member *const &end(begin + idx.size());
|
||||||
return ret;
|
return json::string(begin, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::json::value::~value()
|
ircd::json::value::~value()
|
||||||
|
@ -1059,14 +1009,20 @@ const
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
ircd::json::value::size()
|
ircd::json::serialized(const value &value)
|
||||||
|
{
|
||||||
|
return value.serialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::json::value::serialized()
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case NUMBER: return lex_cast(integer).size();
|
case NUMBER: return lex_cast(integer).size();
|
||||||
case STRING: return 1 + len + 1;
|
case STRING: return 1 + len + 1;
|
||||||
case OBJECT: return serial? len : object->size();
|
case OBJECT: return serial? len : object->serialized();
|
||||||
case ARRAY: return serial? len : 2;
|
case ARRAY: return serial? len : 2;
|
||||||
case LITERAL: return len;
|
case LITERAL: return len;
|
||||||
};
|
};
|
||||||
|
@ -1165,33 +1121,22 @@ ircd::json::operator==(const value &a, const value &b)
|
||||||
return static_cast<string_view>(a) == static_cast<string_view>(b);
|
return static_cast<string_view>(a) == static_cast<string_view>(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
ircd::string_view
|
||||||
ircd::json::print(char *const &buf,
|
ircd::json::stringify(mutable_buffer &buf,
|
||||||
const size_t &max,
|
|
||||||
const object &object)
|
const object &object)
|
||||||
{
|
|
||||||
if(unlikely(!max))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
char *out(buf);
|
|
||||||
serialize(object, out, out + (max - 1));
|
|
||||||
*out = '\0';
|
|
||||||
return std::distance(buf, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
ircd::json::object
|
|
||||||
ircd::json::serialize(const object &object,
|
|
||||||
char *&out,
|
|
||||||
char *const &stop)
|
|
||||||
{
|
{
|
||||||
static const auto throws([]
|
static const auto throws([]
|
||||||
{
|
{
|
||||||
throw print_error("The JSON generator failed to print object");
|
throw print_error("The JSON generator failed to print object");
|
||||||
});
|
});
|
||||||
|
|
||||||
char *const start(out);
|
char *const start(begin(buf));
|
||||||
karma::generate(out, maxwidth(stop - start)[printer.object] | eps[throws], object);
|
karma::generate(begin(buf), maxwidth(size(buf))[printer.object] | eps[throws], object);
|
||||||
return string_view{start, out};
|
|
||||||
|
return string_view
|
||||||
|
{
|
||||||
|
start, begin(buf)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream &
|
std::ostream &
|
||||||
|
@ -1279,43 +1224,28 @@ const
|
||||||
return { string_view::end(), string_view::end() };
|
return { string_view::end(), string_view::end() };
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
ircd::string_view
|
||||||
ircd::json::print(char *const &buf,
|
ircd::json::stringify(mutable_buffer &b,
|
||||||
const size_t &max,
|
const array &a)
|
||||||
const array &arr)
|
|
||||||
{
|
|
||||||
if(unlikely(!max))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
char *out(buf);
|
|
||||||
serialize(arr, out, out + (max - 1));
|
|
||||||
*out = '\0';
|
|
||||||
return std::distance(buf, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
ircd::json::array
|
|
||||||
ircd::json::serialize(const array &a,
|
|
||||||
char *&out,
|
|
||||||
char *const &stop)
|
|
||||||
{
|
{
|
||||||
static const auto throws([]
|
static const auto throws([]
|
||||||
{
|
{
|
||||||
throw print_error("The JSON generator failed to print array");
|
throw print_error("The JSON generator failed to print array");
|
||||||
});
|
});
|
||||||
|
|
||||||
char *const start(out);
|
char *const start(begin(b));
|
||||||
karma::generate(out, maxwidth(stop - out)[printer.array_begin] | eps[throws]);
|
karma::generate(begin(b), maxwidth(size(b))[printer.array_begin] | eps[throws]);
|
||||||
|
|
||||||
auto it(begin(a));
|
auto it(begin(a));
|
||||||
if(it != end(a))
|
if(it != end(a))
|
||||||
{
|
{
|
||||||
karma::generate(out, maxwidth(stop - out)[printer.elem] | eps[throws], *it);
|
karma::generate(begin(b), maxwidth(size(b))[printer.elem] | eps[throws], *it);
|
||||||
for(++it; it != end(a); ++it)
|
for(++it; it != end(a); ++it)
|
||||||
karma::generate(out, maxwidth(stop - out)[printer.value_sep << printer.elem] | eps[throws], *it);
|
karma::generate(begin(b), maxwidth(size(b))[printer.value_sep << printer.elem] | eps[throws], *it);
|
||||||
}
|
}
|
||||||
|
|
||||||
karma::generate(out, maxwidth(stop - out)[printer.array_end] | eps[throws]);
|
karma::generate(begin(b), maxwidth(size(b))[printer.array_end] | eps[throws]);
|
||||||
return string_view{start, out};
|
return string_view{start, begin(b)};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream &
|
std::ostream &
|
||||||
|
@ -1389,6 +1319,27 @@ const
|
||||||
return { string_view::end(), string_view::end() };
|
return { string_view::end(), string_view::end() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::json::serialized(const string_view &s)
|
||||||
|
{
|
||||||
|
switch(type(s, std::nothrow))
|
||||||
|
{
|
||||||
|
case NUMBER:
|
||||||
|
case OBJECT:
|
||||||
|
case ARRAY:
|
||||||
|
case LITERAL:
|
||||||
|
return s.size();
|
||||||
|
|
||||||
|
case STRING:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ret(s.size());
|
||||||
|
ret += !startswith(s, '"');
|
||||||
|
ret += !endswith(s, '"');
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
enum ircd::json::type
|
enum ircd::json::type
|
||||||
ircd::json::type(const string_view &buf)
|
ircd::json::type(const string_view &buf)
|
||||||
{
|
{
|
||||||
|
|
|
@ -99,11 +99,11 @@ ircd::m::init::init()
|
||||||
|
|
||||||
modules.emplace("root.so"s, "root.so"s);
|
modules.emplace("root.so"s, "root.so"s);
|
||||||
|
|
||||||
|
//TODO: conf obviously
|
||||||
listener = new ircd::listener
|
listener = new ircd::listener
|
||||||
{
|
{
|
||||||
//TODO: conf obviously
|
json::string(json::members
|
||||||
json::string
|
{
|
||||||
({
|
|
||||||
{ "name", "Chat Matrix" },
|
{ "name", "Chat Matrix" },
|
||||||
{ "host", "0.0.0.0" },
|
{ "host", "0.0.0.0" },
|
||||||
{ "port", 8447 },
|
{ "port", 8447 },
|
||||||
|
@ -141,7 +141,7 @@ ircd::m::bootstrap()
|
||||||
const auto type{"m.room.create"};
|
const auto type{"m.room.create"};
|
||||||
|
|
||||||
char content[512];
|
char content[512];
|
||||||
json::print(content, sizeof(content),
|
print(content, sizeof(content), json::members
|
||||||
{
|
{
|
||||||
{ "creator", user_id },
|
{ "creator", user_id },
|
||||||
});
|
});
|
||||||
|
@ -162,7 +162,7 @@ ircd::m::bootstrap()
|
||||||
const auto type{"m.room.member"};
|
const auto type{"m.room.member"};
|
||||||
|
|
||||||
char content[512];
|
char content[512];
|
||||||
json::print(content, sizeof(content),
|
print(content, sizeof(content), json::members
|
||||||
{
|
{
|
||||||
{ "membership", "join" },
|
{ "membership", "join" },
|
||||||
});
|
});
|
||||||
|
@ -438,7 +438,7 @@ ircd::m::room::membership(const m::id::user &user_id,
|
||||||
{ "type", "m.room.member" },
|
{ "type", "m.room.member" },
|
||||||
{ "state_key", user_id },
|
{ "state_key", user_id },
|
||||||
{ "sender", user_id },
|
{ "sender", user_id },
|
||||||
{ "content", json::stringify(cbuf, sizeof(cbuf), content) }
|
{ "content", stringify(cbuf, content) }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -257,8 +257,13 @@ ircd::resource::response::response(client &client,
|
||||||
const http::code &code)
|
const http::code &code)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
char cbuf[8192], *out(cbuf);
|
char cbuf[8192];
|
||||||
const auto object(serialize(index, out, cbuf + sizeof(cbuf)));
|
mutable_buffer buf{cbuf};
|
||||||
|
const json::object object
|
||||||
|
{
|
||||||
|
stringify(buf, index)
|
||||||
|
};
|
||||||
|
|
||||||
response(client, object, code);
|
response(client, object, code);
|
||||||
}
|
}
|
||||||
catch(const json::error &e)
|
catch(const json::error &e)
|
||||||
|
|
Loading…
Reference in a new issue