From 9fb791e9fad6c63fc1dac49f4d05ae63b8a3db9b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 5 Jan 2016 11:55:15 +0200 Subject: Rename build directory/namespace to build2 --- build2/variable.txx | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 build2/variable.txx (limited to 'build2/variable.txx') diff --git a/build2/variable.txx b/build2/variable.txx new file mode 100644 index 0000000..907072e --- /dev/null +++ b/build2/variable.txx @@ -0,0 +1,168 @@ +// file : build2/variable.txx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include // make_move_iterator() + +#include + +namespace build2 +{ + // vector value + // + template + bool + vector_assign (names& v, const variable& var) + { + // Verify each element has valid value of T. + // + for (name& n: v) + { + if (!assign (n)) + fail << "invalid " << value_traits::value_type.name << " element " + << "'" << n << "' in variable '" << var.name << "'"; + } + + return !v.empty (); + } + + template + bool + vector_append (names& v, names a, const variable& var) + { + // Verify that what we are appending is valid. + // + vector_assign (a, var); + + if (v.empty ()) + v = move (a); + else + v.insert (v.end (), + std::make_move_iterator (a.begin ()), + std::make_move_iterator (a.end ())); + + return !v.empty (); + } + + template + const std::string value_traits>::type_name = std::string ( + value_traits::value_type.name) + 's'; + + template + const value_type value_traits>::value_type + { + value_traits>::type_name.c_str (), + &vector_assign, + &vector_append + }; + + // map value + // + template + map_value& map_value:: + assign (std::map m) + { + d->clear (); + for (auto& p: m) + { + d->emplace_back (p.first); // Const, can't move. + d->back ().pair = '='; + d->emplace_back (std::move (p.second)); + } + + return *this; + } + + template + auto map_value:: + find (const K& k) -> iterator + { + // @@ Scan backwards to handle duplicates. + // + for (auto i (d->rbegin ()); i != d->rend (); ++i) + if (as (*++i) == k) + return iterator (--(i.base ())); + + return end (); + } + + template + auto map_value:: + find (const K& k) const -> const_iterator + { + // @@ Scan backwards to handle duplicates. + // + for (auto i (d->rbegin ()); i != d->rend (); ++i) + if (as (*++i) == k) + return const_iterator (--(i.base ())); + + return end (); + } + + template + bool + map_assign (names& v, const variable& var) + { + // Verify we have a sequence of pairs and each lhs/rhs is a valid + // value of K/V. + // + for (auto i (v.begin ()); i != v.end (); ++i) + { + if (i->pair == '\0') + fail << value_traits>::value_type.name << " key-value " + << "pair expected instead of '" << *i << "' " + << "in variable '" << var.name << "'"; + + if (!assign (*i)) + fail << "invalid " << value_traits::value_type.name << " key " + << "'" << *i << "' in variable '" << var.name << "'"; + + ++i; // Got to have the second half of the pair. + + if (!assign (*i)) + fail << "invalid " << value_traits::value_type.name << " value " + << "'" << *i << "' in variable '" << var.name << "'"; + } + + //@@ When doing sorting, note that assign() can convert the + // value. + + //@@ Is sorting really the right trade-off (i.e., insertion + // vs search)? Perhaps linear search is ok? + + return !v.empty (); + } + + template + bool + map_append (names& v, names a, const variable& var) + { + //@@ Not weeding out duplicates. + + // Verify that what we are appending is valid. + // + map_assign (a, var); + + if (v.empty ()) + v = move (a); + else + v.insert (v.end (), + std::make_move_iterator (a.begin ()), + std::make_move_iterator (a.end ())); + + return !v.empty (); + } + + template + const std::string value_traits>::type_name = std::string ( + value_traits::value_type.name) + '_' + + value_traits::value_type.name + "_map"; + + template + const value_type value_traits>::value_type + { + value_traits>::type_name.c_str (), + &map_assign, + &map_append + }; +} -- cgit v1.1