aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2024-01-23 09:22:36 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2024-01-23 09:22:36 +0200
commit19b1f25a1209c7af9e73c0e68ba33574a3b4cbb7 (patch)
tree37705ff14d47e08d21f8d16fa8b572e312b19bda
parent7d5c863e01b4a70d5ef3614b91694cf080a420c9 (diff)
Add reversejson-type
-rw-r--r--libbuild2/json.cxx2
-rw-r--r--libbuild2/json.hxx20
-rw-r--r--libbuild2/parser.cxx1
-rw-r--r--libbuild2/variable.cxx76
4 files changed, 96 insertions, 3 deletions
diff --git a/libbuild2/json.cxx b/libbuild2/json.cxx
index dfa1a07..53f7ae4 100644
--- a/libbuild2/json.cxx
+++ b/libbuild2/json.cxx
@@ -181,6 +181,8 @@ namespace build2
container_type c; // For exception safety.
while (*p.next () != event::end_object)
{
+ // @@ Override duplicates or fail?
+
string_type n (p.name ());
json_value v (p);
v.name = move (n);
diff --git a/libbuild2/json.hxx b/libbuild2/json.hxx
index 6fc633c..9a57b8f 100644
--- a/libbuild2/json.hxx
+++ b/libbuild2/json.hxx
@@ -241,13 +241,31 @@ namespace build2
// names are ignored.
//
int
- compare (const json_value&, bool ignore_name = false) const;
+ compare (const json_value&, bool ignore_name = false) const;
};
// Throws invalid_json_output.
//
LIBBUILD2_SYMEXPORT void
serialize (butl::json::buffer_serializer&, const json_value&);
+
+ inline bool
+ operator== (const json_value& x, const json_value& y) {return x.compare (y) == 0;}
+
+ inline bool
+ operator!= (const json_value& x, const json_value& y) {return !(x == y);}
+
+ inline bool
+ operator< (const json_value& x, const json_value& y) {return x.compare (y) < 0;}
+
+ inline bool
+ operator<= (const json_value& x, const json_value& y) {return x.compare (y) <= 0;}
+
+ inline bool
+ operator> (const json_value& x, const json_value& y) {return !(x <= y);}
+
+ inline bool
+ operator>= (const json_value& x, const json_value& y) {return !(x < y);}
}
#endif // LIBBUILD2_JSON_HXX
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx
index b695018..517f058 100644
--- a/libbuild2/parser.cxx
+++ b/libbuild2/parser.cxx
@@ -5753,6 +5753,7 @@ namespace build2
n == "dir_paths" ? ptr (value_traits<dir_paths>::value_type) :
n == "names" ? ptr (value_traits<vector<name>>::value_type) :
n == "cmdline" ? ptr (value_traits<cmdline>::value_type) :
+ n == "json" ? ptr (value_traits<json_value>::value_type) :
nullptr;
}
diff --git a/libbuild2/variable.cxx b/libbuild2/variable.cxx
index c83d55e..efc1eb2 100644
--- a/libbuild2/variable.cxx
+++ b/libbuild2/variable.cxx
@@ -1743,9 +1743,81 @@ namespace build2
*/
static names_view
- json_reverse (const value&, names& storage, bool)
+ json_reverse (const value& x, names& ns, bool)
{
- return names_view (storage); // @@ TODO
+ const json_value& v (x.as<json_value> ());
+
+ switch (v.type)
+ {
+ case json_type::null:
+ {
+ // @@ Hm, it would be nice if this somehow got mapped to [null]/empty
+ // but still be round-trippable to JSON null. Perhaps via type
+ // hint?
+ //
+ ns.push_back (name ("null"));
+ break;
+ }
+ case json_type::boolean:
+ {
+ ns.push_back (name (v.boolean ? "true" : "false"));
+ break;
+ }
+ case json_type::signed_number:
+ {
+ ns.push_back (value_traits<int64_t>::reverse (v.signed_number));
+ break;
+ }
+ case json_type::unsigned_number:
+ {
+ ns.push_back (value_traits<uint64_t>::reverse (v.unsigned_number));
+ break;
+ }
+ case json_type::string:
+ // @@ Hm, it would be nice if this somehow got mapped to unquoted
+ // string but still be round-trippable to JSON null. Perhaps via
+ // type hint?
+ //
+ // @@ If not, optimize for case where no escaping/quoting required?
+ //
+ case json_type::array:
+ case json_type::object:
+ {
+ // Serialize as JSON output.
+ //
+ string o;
+
+#ifndef BUILD2_BOOTSTRAP
+ using namespace butl::json;
+
+ try
+ {
+ // Disable pretty-printing so that the output is all on the same
+ // line. While it's not going to be easy to read for larger JSON
+ // outputs, it will fit better into the existing model where none of
+ // the value representations use formatting newlines. If a pretty-
+ // printed representation is required, then the @@ function can be
+ // used to obtain it.
+ //
+ buffer_serializer s (o, 0 /* indentation */);
+ serialize (s, v);
+ }
+ catch (const invalid_json_output& e)
+ {
+ // @@ How can we communicate event, offset? But for that to be
+ // useful we would also need to somehow also dump the value.
+ //
+ fail << "invalid json value: " << e;
+ }
+#else
+ fail << "json serialization requested during bootstrap";
+#endif
+ ns.push_back (name (move (o)));
+ break;
+ }
+ }
+
+ return ns;
}
static int