// file : build2/variable.txx -*- C++ -*- // copyright : Copyright (c) 2014-2016 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 }; }