diff --git a/include/ircd/json/json.h b/include/ircd/json/json.h index cb584338f..0e73b9a10 100644 --- a/include/ircd/json/json.h +++ b/include/ircd/json/json.h @@ -22,30 +22,13 @@ namespace ircd::json IRCD_EXCEPTION(error, not_found); IRCD_EXCEPTION(parse_error, recursion_limit); - struct value; - struct member; - struct string; - struct object; - struct array; - struct vector; - struct iov; - - enum type - { - STRING = 0, - OBJECT = 1, - ARRAY = 2, - NUMBER = 3, - LITERAL = 4, - }; - enum type type(const string_view &); - enum type type(const string_view &, std::nothrow_t); - string_view reflect(const enum type &); - - template string_view stringify(const mutable_buffer &&mb, T&&... t); + template + string_view stringify(const mutable_buffer &&mb, T&&... t); } +#include "type.h" #include "util.h" +#include "string.h" #include "array.h" #include "object.h" #include "vector.h" @@ -55,6 +38,7 @@ namespace ircd::json #include "strung.h" #include "tuple/tuple.h" #include "stack.h" +#include "tool.h" namespace ircd { diff --git a/include/ircd/json/string.h b/include/ircd/json/string.h new file mode 100644 index 000000000..4e394c09c --- /dev/null +++ b/include/ircd/json/string.h @@ -0,0 +1,52 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2019 Jason Volk +// +// 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. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_JSON_STRING_H + +namespace ircd::json +{ + struct string; +} + +/// Strong type representing quoted strings in JSON (which may be unquoted +/// automatically when this type is encountered in a tuple etc). +struct ircd::json::string +:string_view +{ + string() = default; + string(json::string &&) = default; + string(const json::string &) = default; + string(const string_view &s); + + string &operator=(json::string &&) = default; + string &operator=(const json::string &) = default; + string &operator=(const string_view &s); +}; + +inline +ircd::json::string::string(const string_view &s) +:string_view +{ + surrounds(s, '"')? + unquote(s): + s +} +{} + +inline ircd::json::string & +ircd::json::string::operator=(const string_view &s) +{ + *static_cast(this) = surrounds(s, '"')? + unquote(s): + s; + + return *this; +} diff --git a/include/ircd/json/tool.h b/include/ircd/json/tool.h new file mode 100644 index 000000000..e9b21d375 --- /dev/null +++ b/include/ircd/json/tool.h @@ -0,0 +1,19 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2019 Jason Volk +// +// 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. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_JSON_TOOL_H + +namespace ircd::json +{ + strung remove(const strung &, const string_view &key); + strung remove(const strung &, const size_t &index); + strung insert(const strung &, const member &); +} diff --git a/include/ircd/json/type.h b/include/ircd/json/type.h new file mode 100644 index 000000000..ccb66f7a0 --- /dev/null +++ b/include/ircd/json/type.h @@ -0,0 +1,47 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2019 Jason Volk +// +// 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. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_JSON_TYPE_H + +namespace ircd::json +{ + enum type :uint8_t; + struct value; + struct member; + struct string; + struct object; + struct array; + struct vector; + struct iov; + using members = std::initializer_list; + + enum type type(const string_view &); + enum type type(const string_view &, std::nothrow_t); + string_view reflect(const enum type &); + + extern const string_view literal_null; + extern const string_view literal_true; + extern const string_view literal_false; + extern const string_view empty_string; + extern const string_view empty_object; + extern const string_view empty_array; + extern const int64_t undefined_number; +} + +enum ircd::json::type +:uint8_t +{ + STRING = 0, + OBJECT = 1, + ARRAY = 2, + NUMBER = 3, + LITERAL = 4, +}; diff --git a/include/ircd/json/util.h b/include/ircd/json/util.h index 4282af3ef..29778cc39 100644 --- a/include/ircd/json/util.h +++ b/include/ircd/json/util.h @@ -11,21 +11,16 @@ #pragma once #define HAVE_IRCD_JSON_UTIL_H +// This section contains utilities which are useful other parts of ircd::json +// or developers directly. This interface itself (though not its definition) +// has little dependence on other headers in ircd::json. In contrast, a suite +// of rich developer tools which depend on various assets in ircd::json are +// found in tool.h instead. namespace ircd::json { - struct string; template struct buffer; + using name_hash_t = size_t; - using members = std::initializer_list; - - extern const string_view literal_null; - extern const string_view literal_true; - extern const string_view literal_false; - extern const string_view empty_string; - extern const string_view empty_object; - extern const string_view empty_array; - extern const int64_t undefined_number; - constexpr name_hash_t name_hash(const string_view name); constexpr name_hash_t operator ""_(const char *const name, const size_t len); @@ -45,34 +40,6 @@ namespace ircd::json string_view escape(const mutable_buffer &out, const string_view &in); } -/// Strong type representing quoted strings in JSON (which may be unquoted -/// automatically when this type is encountered in a tuple etc) -struct ircd::json::string -:string_view -{ - string() = default; - string(json::string &&) = default; - string(const json::string &) = default; - string(const string_view &s) - :string_view - { - surrounds(s, '"')? - unquote(s): - s - }{} - - string &operator=(json::string &&) = default; - string &operator=(const json::string &) = default; - string &operator=(const string_view &s) - { - *static_cast(this) = surrounds(s, '"')? - unquote(s): - s; - - return *this; - } -}; - /// Alternative to `json::strung` which uses a fixed array rather than an /// allocated string as the target. template diff --git a/include/ircd/json/value.h b/include/ircd/json/value.h index 4afcf8a21..f2de8675b 100644 --- a/include/ircd/json/value.h +++ b/include/ircd/json/value.h @@ -81,7 +81,7 @@ struct ircd::json::value }; uint64_t len : 57; ///< length indicator - enum type type : 3; ///< json::type indicator + uint64_t type : 3; ///< json::type indicator uint64_t serial : 1; ///< only *string is used. type indicates JSON uint64_t alloc : 1; ///< indicates the pointer for type is owned uint64_t floats : 1; ///< for NUMBER type, integer or floating diff --git a/ircd/json.cc b/ircd/json.cc index d96e55a23..c5115be28 100644 --- a/ircd/json.cc +++ b/ircd/json.cc @@ -400,6 +400,88 @@ ircd::json::input::throws_exceeded() }; } +/////////////////////////////////////////////////////////////////////////////// +// +// json/tool.h +// + +ircd::json::strung +ircd::json::insert(const strung &s, + const json::member &m) +{ + if(!empty(s) && type(s) != type::OBJECT) + throw type_error + { + "Cannot insert member into JSON of type %s", + reflect(type(s)) + }; + + size_t mctr {0}; + thread_local std::array mb; + for(const object::member &m : object{s}) + mb.at(mctr++) = member{m}; + + mb.at(mctr++) = m; + return strung + { + mb.data(), mb.data() + mctr + }; +} + +ircd::json::strung +ircd::json::remove(const strung &s, + const string_view &key) +{ + if(empty(s)) + return s; + + if(type(s) != type::OBJECT) + throw type_error + { + "Cannot remove object member '%s' from JSON of type %s", + key, + reflect(type(s)) + }; + + size_t mctr {0}; + thread_local std::array mb; + for(const object::member &m : object{s}) + if(m.first != key) + mb.at(mctr++) = m; + + return strung + { + mb.data(), mb.data() + mctr + }; +} + +ircd::json::strung +ircd::json::remove(const strung &s, + const size_t &idx) +{ + if(empty(s)) + return s; + + if(type(s) != type::ARRAY) + throw type_error + { + "Cannot remove array element [%zu] from JSON of type %s", + idx, + reflect(type(s)) + }; + + size_t mctr{0}, i{0}; + thread_local std::array mb; + for(const string_view &m : array{s}) + if(i++ != idx) + mb.at(mctr++) = m; + + return strung + { + mb.data(), mb.data() + mctr + }; +} + /////////////////////////////////////////////////////////////////////////////// // // json/stack.h @@ -1762,83 +1844,6 @@ ircd::json::iov::defaults::defaults(iov &iov, // json/strung.h // -ircd::json::strung -ircd::json::insert(const strung &s, - const json::member &m) -{ - if(!empty(s) && type(s) != type::OBJECT) - throw type_error - { - "Cannot insert member into JSON of type %s", - reflect(type(s)) - }; - - size_t mctr {0}; - thread_local std::array mb; - for(const object::member &m : object{s}) - mb.at(mctr++) = member{m}; - - mb.at(mctr++) = m; - return strung - { - mb.data(), mb.data() + mctr - }; -} - -ircd::json::strung -ircd::json::remove(const strung &s, - const string_view &key) -{ - if(empty(s)) - return s; - - if(type(s) != type::OBJECT) - throw type_error - { - "Cannot remove object member '%s' from JSON of type %s", - key, - reflect(type(s)) - }; - - size_t mctr {0}; - thread_local std::array mb; - for(const object::member &m : object{s}) - if(m.first != key) - mb.at(mctr++) = m; - - return strung - { - mb.data(), mb.data() + mctr - }; -} - -ircd::json::strung -ircd::json::remove(const strung &s, - const size_t &idx) -{ - if(empty(s)) - return s; - - if(type(s) != type::ARRAY) - throw type_error - { - "Cannot remove array element [%zu] from JSON of type %s", - idx, - reflect(type(s)) - }; - - size_t mctr{0}, i{0}; - thread_local std::array mb; - for(const string_view &m : array{s}) - if(i++ != idx) - mb.at(mctr++) = m; - - return strung - { - mb.data(), mb.data() + mctr - }; -} - ircd::json::strung::operator json::array() const @@ -3196,7 +3201,7 @@ ircd::json::defined(const value &a) enum ircd::json::type ircd::json::type(const value &a) { - return a.type; + return static_cast(a.type); } //