From ca41ca8f9a6b21588248e5fee1a013363f3f52a8 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 13 Mar 2015 14:34:24 +0200 Subject: Add support for "first" and "last" execution modes --- build/utility | 106 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 16 deletions(-) (limited to 'build/utility') diff --git a/build/utility b/build/utility index 93fb441..cd0d8ad 100644 --- a/build/utility +++ b/build/utility @@ -16,6 +16,7 @@ #include #include +#include #include namespace build @@ -41,6 +42,36 @@ namespace build bool operator() (const P& x, const P& y) const {return *x < *y;} }; + // Support for reverse iteration using range-based for-loop: + // + // for (... : reverse_iterate (x)) ... + // + template + class reverse_range + { + T& x_; + + public: + reverse_range (T& x): x_ (x) {} + + auto begin () const -> decltype (this->x_.rbegin ()) + { + return x_.rbegin (); + } + + auto end () const -> decltype (this->x_.rend ()) + { + return x_.rend (); + } + }; + + template + inline reverse_range + reverse_iterate (T& x) + { + return reverse_range (x); + } + // Call a function if there is an exception. // @@ -99,51 +130,94 @@ namespace build extern string_pool extension_pool; - // A pool of strings in which each string is assigned an individual - // index (or id) of type I (e.g., uint8_t, uint16_t, etc., depending - // on how many entries are expected). Index value 0 is reserved to - // indicate the no entry condition. + // A pool of strings and, optionally, other accompanying data in which + // each entry is assigned an individual index (or id) of type I (e.g., + // uint8_t, uint16_t, etc., depending on how many entries are expected). + // Index value 0 is reserved to indicate the no entry condition. // + template + struct string_table_element + { + const I i; + const D d; + }; + template + struct string_table_element + { + const I i; + const std::string d; + }; + + template + struct string_table_traits + { + // By default, look for the key() function in D. But you can + // also specialize this class template. + // + static const std::string& + key (const D& d) {return d.key ();} + }; + + template <> + struct string_table_traits + { + static const std::string& + key (const std::string& d) {return d;} + }; + + template struct string_table { - // Find existing or insert new. + // Insert new entry unless one already exists. // I - insert (const std::string& s) + insert (const D& d) { std::size_t i (vec_.size () + 1); - auto r (map_.emplace (s, static_cast (i))); + + // Note: move(d) would be tricky since key still points to it. + // + auto r (map_.emplace ( + key_type (&traits::key (d)), + value_type {static_cast (i), d})); if (r.second) { assert (i <= std::numeric_limits::max ()); - vec_.push_back (&r.first->first); + + r.first->first.p = &traits::key (r.first->second.d); // Update key. + vec_.push_back (r.first); } - return r.first->second; + return r.first->second.i; } // Find existing. // I - find (const std::string& s) const + find (const std::string& k) const { - auto i (map_.find (s)); - return i != map_.end () ? i->second : 0; + auto i (map_.find (key_type (&k))); + return i != map_.end () ? i->second.i : 0; } // Reverse lookup. // - const std::string& - operator[] (I i) const {assert (i > 0); return *vec_[i - 1];} + const D& + operator[] (I i) const {assert (i > 0); return vec_[i - 1]->second.d;} I size () const {return static_cast (vec_.size ());} private: - std::unordered_map map_; - std::vector vec_; + using key_type = set_key; + using value_type = string_table_element; + using map_type = std::unordered_map; + using traits = string_table_traits; + + map_type map_; + std::vector vec_; }; } -- cgit v1.1