diff options
Diffstat (limited to 'build/variable.txx')
-rw-r--r-- | build/variable.txx | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/build/variable.txx b/build/variable.txx new file mode 100644 index 0000000..1b32584 --- /dev/null +++ b/build/variable.txx @@ -0,0 +1,160 @@ +// file : build/variable.txx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include <iterator> // make_move_iterator() + +#include <build/diagnostics> + +namespace build +{ + // vector<T> value + // + template <typename T> + bool + vector_assign (names& v, const variable& var) + { + // Verify each element has valid value of T. + // + for (name& n: v) + { + if (!assign<T> (n)) + fail << "invalid " << value_traits<T>::value_type.name << " element " + << "'" << n << "' in variable '" << var.name << "'"; + } + + return !v.empty (); + } + + template <typename T> + bool + vector_append (names& v, names a, const variable& var) + { + // Verify that what we are appending is valid. + // + vector_assign<T> (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 <typename T> + const value_type value_traits<std::vector<T>>::value_type + { + value_traits<T>::value_type.name + 's', + &vector_assign<T>, + &vector_append<T> + }; + + // map<K, V> value + // + template <typename K, typename V, typename D> + map_value<K, V, D>& map_value<K, V, D>:: + assign (std::map<K, V> 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 <typename K, typename V, typename D> + auto map_value<K, V, D>:: + find (const K& k) -> iterator + { + // @@ Scan backwards to handle duplicates. + // + for (auto i (d->rbegin ()); i != d->rend (); ++i) + if (as<K> (*++i) == k) + return iterator (--(i.base ())); + + return end (); + } + + template <typename K, typename V, typename D> + auto map_value<K, V, D>:: + find (const K& k) const -> const_iterator + { + // @@ Scan backwards to handle duplicates. + // + for (auto i (d->rbegin ()); i != d->rend (); ++i) + if (as<K> (*++i) == k) + return const_iterator (--(i.base ())); + + return end (); + } + + template <typename K, typename V> + 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<std::map<K, V>>::value_type.name << " key-value " + << "pair expected instead of '" << *i << "' " + << "in variable '" << var.name << "'"; + + if (!assign<K> (*i)) + fail << "invalid " << value_traits<K>::value_type.name << " key " + << "'" << *i << "' in variable '" << var.name << "'"; + + ++i; // Got to have the second half of the pair. + + if (!assign<V> (*i)) + fail << "invalid " << value_traits<V>::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 <typename K, typename V> + bool + map_append (names& v, names a, const variable& var) + { + //@@ Not weeding out duplicates. + + // Verify that what we are appending is valid. + // + map_assign<K, V> (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 <typename K, typename V> + const value_type value_traits<std::map<K, V>>::value_type + { + value_traits<K>::value_type.name + '_' + + value_traits<V>::value_type.name + "_map", + &map_assign<K, V>, + &map_append<K, V> + }; +} |