From c2d2a1ac0ac41a068c4bf09f8236a61d576e74f5 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 20 Feb 2024 08:57:32 +0200 Subject: Add custom subscript, iterate functions for vector and set value types --- libbuild2/variable.cxx | 5 +-- libbuild2/variable.txx | 83 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 5 deletions(-) (limited to 'libbuild2') diff --git a/libbuild2/variable.cxx b/libbuild2/variable.cxx index 6f9f0fb..4a08b4d 100644 --- a/libbuild2/variable.cxx +++ b/libbuild2/variable.cxx @@ -2093,8 +2093,9 @@ namespace build2 return r; } - void json_iterate (const value& val, - const function& f) + static void + json_iterate (const value& val, + const function& f) { // Implement in terms of subscript for consistency (in particular, // iterating over simple values like number, string). diff --git a/libbuild2/variable.txx b/libbuild2/variable.txx index 501e103..9d39ed7 100644 --- a/libbuild2/variable.txx +++ b/libbuild2/variable.txx @@ -629,6 +629,68 @@ namespace build2 return 0; } + // Provide subscript for vector for efficiency. + // + template + value + vector_subscript (const value& val, value* val_data, + value&& sub, + const location& sloc, + const location& bloc) + { + // Process subscript even if the value is null to make sure it is valid. + // + size_t i; + try + { + i = static_cast (convert (move (sub))); + } + catch (const invalid_argument& e) + { + fail (sloc) << "invalid " << value_traits>::value_type.name + << " value subscript: " << e << + info (bloc) << "use the '\\[' escape sequence if this is a " + << "wildcard pattern"; + } + + value r; + if (!val.null) + { + const auto& v (val.as> ()); + if (i < v.size ()) + { + const T& e (v[i]); + + // Steal the value if possible. + // + r = &val == val_data ? T (move (const_cast (e))) : T (e); + } + } + + // Typify null values so that type-specific subscript (e.g., for + // json_value) gets called for chained subscripts. + // + if (r.null) + r.type = &value_traits::value_type; + + return r; + } + + // Provide iterate for vector for efficiency. + // + template + void + vector_iterate (const value& val, + const function& f) + { + const auto& v (val.as> ()); // Never NULL. + + for (auto b (v.begin ()), i (b), e (v.end ()); i != e; ++i) + { + f (value (*i), i == b); + } + } + // Make sure these are static-initialized together. Failed that VC will make // sure it's done in the wrong order. // @@ -670,8 +732,8 @@ namespace build2 nullptr, // No cast (cast data_ directly). &vector_compare, &default_empty>, - nullptr, // Subscript. - nullptr // Iterate. + &vector_subscript, + &vector_iterate }; // vector> value @@ -999,6 +1061,21 @@ namespace build2 return value (r); } + // Provide iterate for set for efficiency. + // + template + void + set_iterate (const value& val, + const function& f) + { + const auto& v (val.as> ()); // Never NULL. + + for (auto b (v.begin ()), i (b), e (v.end ()); i != e; ++i) + { + f (value (*i), i == b); + } + } + // Make sure these are static-initialized together. Failed that VC will make // sure it's done in the wrong order. // @@ -1054,7 +1131,7 @@ namespace build2 &set_compare, &default_empty>, &set_subscript, - nullptr // Iterate. + &set_iterate }; // map value -- cgit v1.1