aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2024-02-06 16:51:24 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2024-02-07 15:02:57 +0200
commitfcc239ecdbd1467a4ac8b17a353e1b0ae7fd63a0 (patch)
tree93d8ebe044272ddb03ce4dac64ed11f870967c01
parentac2974380f1986480b3a974d97dd120f81c3e2af (diff)
Map JSON null in subscript/iteration to [null] instead of empty
This in fact feels more natural in the "for consumption" model and also helps with the nested subscript semantics.
-rw-r--r--libbuild2/variable.cxx47
-rw-r--r--tests/type/json/testscript20
2 files changed, 43 insertions, 24 deletions
diff --git a/libbuild2/variable.cxx b/libbuild2/variable.cxx
index 1785e56..1c899f9 100644
--- a/libbuild2/variable.cxx
+++ b/libbuild2/variable.cxx
@@ -1905,9 +1905,10 @@ namespace build2
return l.as<json_value> ().compare (r.as<json_value> ());
}
- // Return null value if the index/name is out of range.
+ // Return the value as well as the indication of whether the index/name is
+ // in range.
//
- static value
+ static pair<value, bool>
json_subscript_impl (const value& val, value* val_data,
uint64_t i, const string& n, bool index)
{
@@ -1918,13 +1919,12 @@ namespace build2
if (index)
{
if (i >= (jv.type == json_type::array ? jv.array.size () :
- jv.type == json_type::object ? jv.object.size () : 1))
- return value ();
+ jv.type == json_type::object ? jv.object.size () :
+ jv.type == json_type::null ? 0 : 1))
+ return make_pair (value (), false);
switch (jv.type)
{
- case json_type::null:
- return value (); // JSON null has no elements.
case json_type::boolean:
case json_type::signed_number:
case json_type::unsigned_number:
@@ -1963,6 +1963,8 @@ namespace build2
: json_member (m));
break;
}
+ case json_type::null:
+ assert (false);
}
}
else
@@ -1975,7 +1977,7 @@ namespace build2
}));
if (i == jv.object.end ())
- return value ();
+ return make_pair (value (), false);
// Steal the member value if possible.
//
@@ -1996,20 +1998,29 @@ namespace build2
// @@ TODO: split this function into two (index/name) once get rid of this.
//
#if 1
+ value r;
switch (jr.type)
{
- case json_type::null: return value (names {});
- case json_type::boolean: return value (jr.boolean);
- case json_type::signed_number: return value (jr.signed_number);
+ // Seeing that we are reversing for consumption, it feels natural to
+ // reverse JSON null to our [null] rather than empty. This, in
+ // particular, helps nested subscript.
+ //
+#if 0
+ case json_type::null: r = value (names {}); break;
+#else
+ case json_type::null: r = value (); break;
+#endif
+ case json_type::boolean: r = value (jr.boolean); break;
+ case json_type::signed_number: r = value (jr.signed_number); break;
case json_type::unsigned_number:
- case json_type::hexadecimal_number: return value (jr.unsigned_number);
- case json_type::string: return value (move (jr.string));
+ case json_type::hexadecimal_number: r = value (jr.unsigned_number); break;
+ case json_type::string: r = value (move (jr.string)); break;
case json_type::array:
- case json_type::object: break;
+ case json_type::object: r = value (move (jr)); break;
}
#endif
- return value (move (jr));
+ return make_pair (move (r), true);
}
static value
@@ -2081,7 +2092,7 @@ namespace build2
}
value r (jv != nullptr
- ? json_subscript_impl (val, val_data, i, n, index)
+ ? json_subscript_impl (val, val_data, i, n, index).first
: value ());
// Typify null values so that we get called for nested subscripts.
@@ -2100,12 +2111,12 @@ namespace build2
//
for (uint64_t i (0);; ++i)
{
- value e (json_subscript_impl (val, nullptr, i, {}, true));
+ pair<value, bool> e (json_subscript_impl (val, nullptr, i, {}, true));
- if (e.null)
+ if (!e.second)
break;
- f (move (e), i == 0);
+ f (move (e.first), i == 0);
}
}
diff --git a/tests/type/json/testscript b/tests/type/json/testscript
index 2663a22..5295fbc 100644
--- a/tests/type/json/testscript
+++ b/tests/type/json/testscript
@@ -303,7 +303,7 @@
print ($j[4])
EOI
2
-
+ [null]
[null]
EOO
@@ -316,7 +316,7 @@
print ($j[five])
EOI
2
-
+ [null]
[null]
EOO
@@ -332,30 +332,38 @@
: nested
:
$* <<EOI >>EOO
- o = [json] one@([json] 1 2 ([json] a@3 b@4)) two@([json] x@x y@([json] 5 6))
+ o = [json] one@([json] 1 2 ([json] a@3 b@4) null) two@([json] x@x y@([json] 5 6))
print ($o[one][1])
print ($o[one][2][b])
print ($o[two][y][1])
print ($o[two][bogus][junk])
print ($o[two][bogus][junk][garbage])
+ print ($o[one][3][junk]) # JSON null
+ print ($o[one][3][junk][garbage])
- a = [json] ([json] one@1 two@([json] 2 3)) ([json] 4 5)
+ a = [json] ([json] one@1 two@([json] 2 3)) ([json] 4 5) null
print ($a[0][one])
print ($a[0][two][1])
print ($a[1][1])
print ($a[1][123][junk])
print ($a[1][123][junk][garbage])
+ print ($a[2][junk]) # JSON null
+ print ($a[2][junk][garbage])
EOI
2
4
6
[null]
[null]
+ [null]
+ [null]
1
3
5
[null]
[null]
+ [null]
+ [null]
EOO
: reverse
@@ -368,7 +376,7 @@
print (([json] one@0xdecaf)[one])
print (([json] one@abc)[one])
EOI
-
+ [null]
true
123
-123
@@ -435,7 +443,7 @@
for v: ([json] null true 123 -123 0xdecaf abc)
print $v
EOI
-
+ [null]
true
123
-123