aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/variable.cxx6
-rw-r--r--libbuild2/variable.hxx30
-rw-r--r--libbuild2/variable.ixx31
-rw-r--r--libbuild2/variable.txx166
4 files changed, 231 insertions, 2 deletions
diff --git a/libbuild2/variable.cxx b/libbuild2/variable.cxx
index 643a061..546eb91 100644
--- a/libbuild2/variable.cxx
+++ b/libbuild2/variable.cxx
@@ -1523,7 +1523,11 @@ namespace build2
template struct LIBBUILD2_DEFEXPORT value_traits<dir_paths>;
template struct LIBBUILD2_DEFEXPORT value_traits<uint64s>;
- template struct LIBBUILD2_DEFEXPORT value_traits<std::map<string, string>>;
+ template struct LIBBUILD2_DEFEXPORT
+ value_traits<vector<pair<string, string>>>;
+
+ template struct LIBBUILD2_DEFEXPORT
+ value_traits<std::map<string, string>>;
template struct LIBBUILD2_DEFEXPORT
value_traits<std::map<project_name, dir_path>>;
diff --git a/libbuild2/variable.hxx b/libbuild2/variable.hxx
index 6a2c681..3389a8e 100644
--- a/libbuild2/variable.hxx
+++ b/libbuild2/variable.hxx
@@ -954,6 +954,33 @@ namespace build2
static const value_type_ex value_type;
};
+ // vector<pair<K, V>>
+ //
+ template <typename K, typename V>
+ struct value_traits<vector<pair<K, V>>>
+ {
+ static_assert (sizeof (vector<pair<K, V>>) <= value::size_,
+ "insufficient space");
+
+ static void assign (value&, vector<pair<K, V>>&&);
+ static void append (value&, vector<pair<K, V>>&&);
+ static void prepend (value& v, vector<pair<K, V>>&& x) {
+ return append (v, move (x));}
+ static bool empty (const vector<pair<K, V>>& x) {return x.empty ();}
+
+ static const vector<pair<K, V>> empty_instance;
+
+ // Make sure these are static-initialized together. Failed that VC will
+ // make sure it's done in the wrong order.
+ //
+ struct value_type_ex: build2::value_type
+ {
+ string type_name;
+ value_type_ex (value_type&&);
+ };
+ static const value_type_ex value_type;
+ };
+
// map<K, V>
//
template <typename K, typename V>
@@ -995,6 +1022,9 @@ namespace build2
extern template struct LIBBUILD2_DECEXPORT value_traits<uint64s>;
extern template struct LIBBUILD2_DECEXPORT
+ value_traits<vector<pair<string, string>>>;
+
+ extern template struct LIBBUILD2_DECEXPORT
value_traits<std::map<string, string>>;
extern template struct LIBBUILD2_DECEXPORT
diff --git a/libbuild2/variable.ixx b/libbuild2/variable.ixx
index d341c26..d6bf119 100644
--- a/libbuild2/variable.ixx
+++ b/libbuild2/variable.ixx
@@ -707,6 +707,37 @@ namespace build2
new (&v.data_) vector<T> (move (x));
}
+ // vector<pair<K, V>> value
+ //
+ template <typename K, typename V>
+ inline void value_traits<vector<pair<K, V>>>::
+ assign (value& v, vector<pair<K, V>>&& x)
+ {
+ if (v)
+ v.as<vector<pair<K, V>>> () = move (x);
+ else
+ new (&v.data_) vector<pair<K, V>> (move (x));
+ }
+
+ template <typename K, typename V>
+ inline void value_traits<vector<pair<K, V>>>::
+ append (value& v, vector<pair<K, V>>&& x)
+ {
+ if (v)
+ {
+ vector<pair<K, V>>& y (v.as<vector<pair<K, V>>> ());
+
+ if (y.empty ())
+ y.swap (x);
+ else
+ y.insert (y.end (),
+ make_move_iterator (x.begin ()),
+ make_move_iterator (x.end ()));
+ }
+ else
+ new (&v.data_) vector<pair<K, V>> (move (x));
+ }
+
// map<K, V> value
//
template <typename K, typename V>
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<T>>
};
+ // vector<pair<K, V>> value
+ //
+ template <typename K, typename V>
+ void
+ pair_vector_append (value& v, names&& ns, const variable* var)
+ {
+ vector<pair<K, V>>& p (v
+ ? v.as<vector<pair<K, V>>> ()
+ : *new (&v.data_) vector<pair<K, V>> ());
+
+ // 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<vector<pair<K, V>>>::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<vector<pair<K, V>>>::value_type.name
+ << " key-value '" << l << "'" << l.pair << "'" << r << "'";
+
+ if (var != nullptr)
+ dr << " in variable " << var->name;
+ }
+
+ try
+ {
+ K k (value_traits<K>::convert (move (l), nullptr));
+
+ try
+ {
+ V v (value_traits<V>::convert (move (r), nullptr));
+
+ p.emplace_back (move (k), move (v));
+ }
+ catch (const invalid_argument&)
+ {
+ diag_record dr (fail);
+
+ dr << "invalid " << value_traits<V>::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<K>::value_type.name
+ << " element key '" << l << "'";
+
+ if (var != nullptr)
+ dr << " in variable " << var->name;
+ }
+ }
+ }
+
+ template <typename K, typename V>
+ void
+ pair_vector_assign (value& v, names&& ns, const variable* var)
+ {
+ if (v)
+ v.as<vector<pair<K, V>>> ().clear ();
+
+ pair_vector_append<K, V> (v, move (ns), var);
+ }
+
+ template <typename K, typename V>
+ static names_view
+ pair_vector_reverse (const value& v, names& s)
+ {
+ auto& vv (v.as<vector<pair<K, V>>> ());
+ s.reserve (2 * vv.size ());
+
+ for (const auto& p: vv)
+ {
+ s.push_back (value_traits<K>::reverse (p.first));
+ s.back ().pair = '@';
+ s.push_back (value_traits<V>::reverse (p.second));
+ }
+
+ return s;
+ }
+
+ template <typename K, typename V>
+ static int
+ pair_vector_compare (const value& l, const value& r)
+ {
+ auto& lv (l.as<vector<pair<K, V>>> ());
+ auto& rv (r.as<vector<pair<K, V>>> ());
+
+ 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<K>::compare (li->first, ri->first)) != 0 ||
+ (r = value_traits<V>::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 <typename K, typename V>
+ value_traits<vector<pair<K, V>>>::value_type_ex::
+ value_type_ex (value_type&& v)
+ : value_type (move (v))
+ {
+ type_name = value_traits<K>::type_name;
+ type_name += '_';
+ type_name += value_traits<V>::type_name;
+ type_name += "_pair_vector";
+ name = type_name.c_str ();
+ }
+
+ template <typename K, typename V>
+ const vector<pair<K, V>> value_traits<vector<pair<K, V>>>::empty_instance;
+
+ template <typename K, typename V>
+ const typename value_traits<std::vector<pair<K, V>>>::value_type_ex
+ value_traits<vector<pair<K, V>>>::value_type = build2::value_type // VC14 wants =
+ {
+ nullptr, // Patched above.
+ sizeof (vector<pair<K, V>>),
+ nullptr, // No base.
+ nullptr, // No element.
+ &default_dtor<vector<pair<K, V>>>,
+ &default_copy_ctor<vector<pair<K, V>>>,
+ &default_copy_assign<vector<pair<K, V>>>,
+ &pair_vector_assign<K, V>,
+ &pair_vector_append<K, V>,
+ &pair_vector_append<K, V>, // Prepend is the same as append.
+ &pair_vector_reverse<K, V>,
+ nullptr, // No cast (cast data_ directly).
+ &pair_vector_compare<K, V>,
+ &default_empty<vector<pair<K, V>>>
+ };
+
// map<K, V> value
//
template <typename K, typename V>
@@ -574,7 +738,7 @@ namespace build2
}
template <typename K, typename V>
- const std::map<K,V> value_traits<std::map<K, V>>::empty_instance;
+ const std::map<K, V> value_traits<std::map<K, V>>::empty_instance;
template <typename K, typename V>
const typename value_traits<std::map<K, V>>::value_type_ex