diff --git a/include/ircd/json.h b/include/ircd/json.h index 77519e6e3..f2757c221 100644 --- a/include/ircd/json.h +++ b/include/ircd/json.h @@ -50,6 +50,11 @@ namespace ircd::json enum type type(const string_view &, std::nothrow_t); string_view reflect(const enum type &); + using name_hash_t = size_t; + constexpr name_hash_t name_hash(const char *const name, const size_t len = 0); + constexpr name_hash_t name_hash(const string_view &name); + constexpr name_hash_t operator ""_(const char *const name, const size_t len); + /// Higher order type beyond a string to cleanly delimit multiple keys. using path = std::initializer_list; std::ostream &operator<<(std::ostream &, const path &); @@ -78,6 +83,7 @@ namespace ircd::json namespace ircd { + using json::operator ""_; using json::operator<<; } @@ -188,3 +194,21 @@ ircd::json::operator<<(std::ostream &s, const path &p) return s; } + +constexpr ircd::json::name_hash_t +ircd::json::operator ""_(const char *const text, const size_t len) +{ + return name_hash(text, len); +} + +constexpr ircd::json::name_hash_t +ircd::json::name_hash(const string_view &name) +{ + return ircd::hash(name); +} + +constexpr ircd::json::name_hash_t +ircd::json::name_hash(const char *const name, const size_t len) +{ + return ircd::hash(name); +} diff --git a/include/ircd/json/object.h b/include/ircd/json/object.h index 0df8d0b92..684d24382 100644 --- a/include/ircd/json/object.h +++ b/include/ircd/json/object.h @@ -25,6 +25,9 @@ namespace ircd::json { struct object; + + template T at(const object &); + template T get(const object &, const T &def = {}); } /// Lightweight interface to a JSON object string. @@ -81,6 +84,7 @@ struct ircd::json::object const_iterator end() const; const_iterator begin() const; const_iterator find(const string_view &key) const; + const_iterator find(const name_hash_t &key) const; // util size_t count() const; @@ -214,6 +218,25 @@ catch(const bad_lex_cast &e) typeid(T).name()); } +template +T +ircd::json::at(const object &object) +try +{ + const auto it(object.find(key)); + if(it == end(object)) + throw not_found("[key hash] '%zu'", key); + + return lex_cast(it->second); +} +catch(const bad_lex_cast &e) +{ + throw type_error("[key hash] '%zu' must cast to type %s", + key, + typeid(T).name()); +} + template T ircd::json::object::at(const string_view &key) @@ -273,6 +296,25 @@ catch(const bad_lex_cast &e) return def; } +template +ircd::string_view +ircd::json::get(const object &object, + const T &def) +try +{ + const auto it{object.find(key)}; + if(it == end(object)) + return def; + + const string_view sv{it->second}; + return !sv.empty()? lex_cast(sv) : def; +} +catch(const bad_lex_cast &e) +{ + return def; +} + template T ircd::json::object::get(const string_view &key, @@ -329,6 +371,17 @@ const return find(key) != end(); } +inline ircd::json::object::const_iterator +ircd::json::object::find(const name_hash_t &key) +const +{ + return std::find_if(begin(), end(), [&key] + (const auto &member) + { + return name_hash(member.first) == key; + }); +} + inline ircd::json::object::const_iterator ircd::json::object::find(const string_view &key) const diff --git a/include/ircd/json/tuple.h b/include/ircd/json/tuple.h index 10e0bc6f8..ca02752ca 100644 --- a/include/ircd/json/tuple.h +++ b/include/ircd/json/tuple.h @@ -22,19 +22,6 @@ #pragma once #define HAVE_IRCD_JSON_TUPLE_H -namespace ircd::json -{ - constexpr size_t operator ""_(const char *const text, const size_t len) - { - return ircd::hash(text); - } -} - -namespace ircd -{ - using json::operator ""_; -} - namespace ircd { namespace json { @@ -169,7 +156,7 @@ template(), size_t>::type indexof() { - const auto equal + constexpr auto equal { ircd::hash(key()) == hash }; @@ -190,7 +177,7 @@ template(), size_t>::type indexof(const char *const &name) { - const auto equal + constexpr auto equal { _constexpr_equal(key(), name) };