From 36d6b4e5549dc45baf890105de5ef487211f0144 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 6 Feb 2024 05:22:12 +0200 Subject: Add experimental support for JSON value types New types: json json_array json_object New functions: $json.value_type() $json.value_size() $json.member_{name,value}() $json.object_names() $json.array_size() $json.array_find(, ) $json.array_find_index(, ) $json.load() $json.parse() $json.serialize([, ]) For example, to load a JSON value from a file: j = $json.load($src_base/board.json) Or to construct it in a buildfile: j = [json] one@1 two@([json] 2 3 4) three@([json] x@1 y@-1) This can also be done incrementally with append/prepend: j = [json_object] j += one@1 j += two@([json] 2 3 4) j += three@([json] x@1 y@-1) Instead of using this JSON-like syntax, one can also specify valid JSON input text: j = [json] '{"one":1, "two":[2, 3, 4], "three":{"x":1, "y":-1}' Besides the above set of functions, other handy ways to access components in a JSON value are iteration and subscript. For example: for m: $j print $member_name($m) $member_value($m) print ($j[three]) A subscript can be nested: print ($j[two][1]) print ($j[three][x]) While a JSON value can be printed directly like any other value, the representation will not be pretty-printed. As a result, for complex JSON values, printing a serialized representation might be a more readable option: info $serialize($j) --- libbuild2/json.ixx | 222 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 libbuild2/json.ixx (limited to 'libbuild2/json.ixx') diff --git a/libbuild2/json.ixx b/libbuild2/json.ixx new file mode 100644 index 0000000..c2b8845 --- /dev/null +++ b/libbuild2/json.ixx @@ -0,0 +1,222 @@ +// file : libbuild2/json.ixx -*- C++ -*- +// license : MIT; see accompanying LICENSE file + +namespace build2 +{ + inline json_value:: + ~json_value () noexcept + { + switch (type) + { + case json_type::null: + case json_type::boolean: + case json_type::signed_number: + case json_type::unsigned_number: + case json_type::hexadecimal_number: break; + case json_type::string: string.~string_type (); break; + case json_type::array: array.~array_type (); break; + case json_type::object: object.~object_type (); break; + } + } + + inline json_value:: + json_value (json_type t) noexcept + : type (t) + { + switch (type) + { + case json_type::null: break; + case json_type::boolean: boolean = false; break; + case json_type::signed_number: signed_number = 0; break; + case json_type::unsigned_number: + case json_type::hexadecimal_number: unsigned_number = 0; break; + case json_type::string: new (&string) string_type (); break; + case json_type::array: new (&array) array_type (); break; + case json_type::object: new (&object) object_type (); break; + } + } + + inline json_value:: + json_value (std::nullptr_t) noexcept + : type (json_type::null) + { + } + + inline json_value:: + json_value (bool v) noexcept + : type (json_type::boolean), boolean (v) + { + } + + inline json_value:: + json_value (int64_t v) noexcept + : type (json_type::signed_number), signed_number (v) + { + } + + inline json_value:: + json_value (uint64_t v, bool hex) noexcept + : type (hex + ? json_type::hexadecimal_number + : json_type::unsigned_number), + unsigned_number (v) + { + } + + inline json_value:: + json_value (string_type v) + : type (json_type::string), string (move (v)) + { + } + + inline const json_value& json_value:: + at (const string_type& n) const + { + return at (n.c_str ()); + } + + inline json_value& json_value:: + at (const string_type& n) + { + return at (n.c_str ()); + } + + inline const json_value& json_value:: + operator[] (const string_type& n) const + { + return operator[] (n.c_str ()); + } + + inline json_value& json_value:: + operator[] (const string_type& n) + { + return operator[] (n.c_str ()); + } + + inline json_value:: + json_value (json_value&& v) noexcept + : type (v.type) + { + switch (type) + { + case json_type::null: + break; + case json_type::boolean: + boolean = v.boolean; + break; + case json_type::signed_number: + signed_number = v.signed_number; + break; + case json_type::unsigned_number: + case json_type::hexadecimal_number: + unsigned_number = v.unsigned_number; + break; + case json_type::string: + new (&string) string_type (move (v.string)); + v.string.~string_type (); + break; + case json_type::array: + new (&array) array_type (move (v.array)); + v.array.~array_type (); + break; + case json_type::object: + new (&object) object_type (move (v.object)); + v.object.~object_type (); + break; + } + + v.type = json_type::null; + } + + inline json_value:: + json_value (const json_value& v) + : type (v.type) + { + switch (type) + { + case json_type::null: + break; + case json_type::boolean: + boolean = v.boolean; + break; + case json_type::signed_number: + signed_number = v.signed_number; + break; + case json_type::unsigned_number: + case json_type::hexadecimal_number: + unsigned_number = v.unsigned_number; + break; + case json_type::string: + new (&string) string_type (v.string); + break; + case json_type::array: + new (&array) array_type (v.array); + break; + case json_type::object: + new (&object) object_type (v.object); + break; + } + } + + inline json_value& json_value:: + operator= (json_value&& v) noexcept + { + if (this != &v) + { + this->~json_value (); + new (this) json_value (move (v)); + } + return *this; + } + + inline json_value& json_value:: + operator= (const json_value& v) + { + if (this != &v) + { + this->~json_value (); + new (this) json_value (v); + } + return *this; + } + + // json_array + // + inline json_array:: + json_array () noexcept + : json_value (json_type::array) + { + } + + inline json_array:: + json_array (json_parser& p) + : json_value (p, json_type::array) + { + } + + inline void json_array:: + serialize (json_buffer_serializer& s) const + { + json_value::serialize (s, json_type::array); + } + + // json_object + // + inline json_object:: + json_object () noexcept + : json_value (json_type::object) + { + } + + inline json_object:: + json_object (json_parser& p) + : json_value (p, json_type::object) + { + } + + inline void json_object:: + serialize (json_buffer_serializer& s) const + { + json_value::serialize (s, json_type::object); + } +} -- cgit v1.1