From c0743592bfae808b61a8146fd97af94b50156f0e Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 12 Nov 2019 12:20:34 +0200 Subject: Add support for vector> variable values --- libbuild2/variable.txx | 166 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 1 deletion(-) (limited to 'libbuild2/variable.txx') diff --git a/libbuild2/variable.txx b/libbuild2/variable.txx index 041dc94..5029edf 100644 --- a/libbuild2/variable.txx +++ b/libbuild2/variable.txx @@ -424,6 +424,170 @@ namespace build2 &default_empty> }; + // vector> value + // + template + void + pair_vector_append (value& v, names&& ns, const variable* var) + { + vector>& p (v + ? v.as>> () + : *new (&v.data_) vector> ()); + + // Verify we have a sequence of pairs and convert each lhs/rhs to K/V. + // + for (auto i (ns.begin ()); i != ns.end (); ++i) + { + name& l (*i); + + if (!l.pair) + { + diag_record dr (fail); + + dr << value_traits>>::value_type.name + << " key-value pair expected instead of '" << l << "'"; + + if (var != nullptr) + dr << " in variable " << var->name; + } + + name& r (*++i); // Got to have the second half of the pair. + + if (l.pair != '@') + { + diag_record dr (fail); + + dr << "unexpected pair style for " + << value_traits>>::value_type.name + << " key-value '" << l << "'" << l.pair << "'" << r << "'"; + + if (var != nullptr) + dr << " in variable " << var->name; + } + + try + { + K k (value_traits::convert (move (l), nullptr)); + + try + { + V v (value_traits::convert (move (r), nullptr)); + + p.emplace_back (move (k), move (v)); + } + catch (const invalid_argument&) + { + diag_record dr (fail); + + dr << "invalid " << value_traits::value_type.name + << " element value '" << r << "'"; + + if (var != nullptr) + dr << " in variable " << var->name; + } + } + catch (const invalid_argument&) + { + diag_record dr (fail); + + dr << "invalid " << value_traits::value_type.name + << " element key '" << l << "'"; + + if (var != nullptr) + dr << " in variable " << var->name; + } + } + } + + template + void + pair_vector_assign (value& v, names&& ns, const variable* var) + { + if (v) + v.as>> ().clear (); + + pair_vector_append (v, move (ns), var); + } + + template + static names_view + pair_vector_reverse (const value& v, names& s) + { + auto& vv (v.as>> ()); + s.reserve (2 * vv.size ()); + + for (const auto& p: vv) + { + s.push_back (value_traits::reverse (p.first)); + s.back ().pair = '@'; + s.push_back (value_traits::reverse (p.second)); + } + + return s; + } + + template + static int + pair_vector_compare (const value& l, const value& r) + { + auto& lv (l.as>> ()); + auto& rv (r.as>> ()); + + auto li (lv.begin ()), le (lv.end ()); + auto ri (rv.begin ()), re (rv.end ()); + + for (; li != le && ri != re; ++li, ++ri) + { + int r; + if ((r = value_traits::compare (li->first, ri->first)) != 0 || + (r = value_traits::compare (li->second, ri->second)) != 0) + return r; + } + + if (li == le && ri != re) // l shorter than r. + return -1; + + if (ri == re && li != le) // r shorter than l. + return 1; + + return 0; + } + + template + value_traits>>::value_type_ex:: + value_type_ex (value_type&& v) + : value_type (move (v)) + { + type_name = value_traits::type_name; + type_name += '_'; + type_name += value_traits::type_name; + type_name += "_pair_vector"; + name = type_name.c_str (); + } + + template + const vector> value_traits>>::empty_instance; + + template + const typename value_traits>>::value_type_ex + value_traits>>::value_type = build2::value_type // VC14 wants = + { + nullptr, // Patched above. + sizeof (vector>), + nullptr, // No base. + nullptr, // No element. + &default_dtor>>, + &default_copy_ctor>>, + &default_copy_assign>>, + &pair_vector_assign, + &pair_vector_append, + &pair_vector_append, // Prepend is the same as append. + &pair_vector_reverse, + nullptr, // No cast (cast data_ directly). + &pair_vector_compare, + &default_empty>> + }; + // map value // template @@ -574,7 +738,7 @@ namespace build2 } template - const std::map value_traits>::empty_instance; + const std::map value_traits>::empty_instance; template const typename value_traits>::value_type_ex -- cgit v1.1