0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-29 10:12:39 +01:00

ircd::json: Add commentary; Add path related.

This commit is contained in:
Jason Volk 2017-08-23 14:42:58 -06:00
parent 413d5d22a9
commit a9f52a70b2
3 changed files with 67 additions and 1 deletions

View file

@ -22,6 +22,40 @@
#pragma once
#define HAVE_IRCD_JSON_H
//
// The IRCd JSON subsystem is meant to be a fast, safe, and extremely
// lightweight interface. We have taken a somewhat non-traditional approach
// and it's important for the developer to understand a few things.
//
// Most JSON interfaces are functions to convert some JSON input to and from
// text into native-machine state like JSON.parse() for JS, boost::ptree, etc.
// For a parsing operation, they make a pass recursing over the entire text,
// allocating native structures, copying data into them, indexing their keys,
// and perhaps performing native-type conversions and checks to present the
// user with a final tree of machine-state usable in their language. The
// original input is then discarded.
//
// Instead, we are interested in having the ability to *compute directly over
// JSON text* itself, and perform the allocating, indexing, copying and
// converting entirely at the time and place of our discretion -- if ever.
//
// The core of this system is a robust and efficient abstract formal grammar
// built with boost::spirit. The formal grammar provides a *proof of robust-
// ness*: security vulnerabilities are more easily spotted by vetting this
// grammar rather than laboriously tracing the program flow of an informal
// handwritten parser.
//
// Next we have taught boost::spirit how to parse into std::string_view rather
// than std::string. Parsing is now a composition of pointers into the original
// string of JSON. No dynamic allocation ever takes place. No copying of data
// ever takes place. IRCd can service an entire request from the original
// network input with absolutely minimal requisite cost.
//
// The output side is also ambitious but probably a little more friendly to
// the developer. We leverage boost::spirit here also providing *formally
// proven* output safety. In other words, the grammar prevents exploits like
// injecting and terminating JSON as it composes the output.
//
namespace ircd {
namespace json {
@ -47,6 +81,9 @@ enum type
enum type type(const string_view &);
enum type type(const string_view &, std::nothrow_t);
using path = std::initializer_list<string_view>;
std::ostream &operator<<(std::ostream &, const path &);
} // namespace json
} // namespace ircd
@ -54,4 +91,26 @@ enum type type(const string_view &, std::nothrow_t);
#include "json/object.h"
#include "json/value.h"
#include "json/index.h"
// #include "json/parse.h"
#include "json/parse.h"
namespace ircd {
using json::operator<<;
} // namespace ircd
inline std::ostream &
ircd::json::operator<<(std::ostream &s, const path &p)
{
auto it(std::begin(p));
if(it != std::end(p))
{
s << *it;
++it;
}
for(; it != std::end(p); ++it)
s << '.' << *it;
return s;
}

View file

@ -52,6 +52,7 @@ struct parse
return std::tuple_size<tuple_type>();
}
parse() = default;
template<class R> parse(R &r, const json::object &obj);
};

View file

@ -25,6 +25,12 @@
namespace ircd {
namespace json {
// The ircd::json::value is used if we have to keep state in machine-form
// rather than directly computing JSON strings. This class ends up being useful
// for recursive initializer_lists to compose JSON from machine values. It
// is lightweight, consuming the space of two pointers which is the same size
// as a string_view.
//
struct value
{
union // xxx std::variant