diff options
Diffstat (limited to 'build/target')
-rw-r--r-- | build/target | 225 |
1 files changed, 219 insertions, 6 deletions
diff --git a/build/target b/build/target index 8161438..b86ea94 100644 --- a/build/target +++ b/build/target @@ -8,15 +8,16 @@ #include <map> #include <string> #include <vector> -#include <memory> // unique_ptr -#include <cstddef> // size_t -#include <functional> // function, reference_wrapper +#include <memory> // unique_ptr +#include <cstddef> // size_t +#include <functional> // function, reference_wrapper #include <ostream> #include <cassert> -#include <utility> // move() +#include <utility> // move(), forward(), declval() #include <iterator> +#include <type_traits> -#include <butl/utility> // compare_c_string +#include <butl/utility> // compare_c_string, reverse_iterate() #include <butl/multi-index> // map_iterator_adapter #include <build/types> @@ -31,6 +32,9 @@ namespace build class target; class target_group; + target& + search (prerequisite&); // From <build/algorithm>. + // Target state. // enum class target_state {unknown, postponed, unchanged, changed, failed}; @@ -359,7 +363,7 @@ namespace build private: target* t_ {nullptr}; prerequisites_type* c_ {nullptr}; - prerequisites_type::iterator i_; + base_iterator i_; }; typedef std::reverse_iterator<iterator> reverse_iterator; @@ -500,6 +504,215 @@ namespace build static const target_type static_type; }; + // A member of a prerequisite. If 'target' is NULL, then this is the + // prerequisite itself. Otherwise, it is its member. In this case + // 'prerequisite' still refers to the prerequisite. + // + struct prerequisite_member + { + typedef build::target target_type; + typedef build::prerequisite prerequisite_type; + + prerequisite_ref& prerequisite; + target_type* target; + + template <typename T> + bool + is_a () const + { + return target != nullptr + ? target->is_a<T> () != nullptr + : prerequisite.get ().is_a<T> (); + } + + prerequisite_key + key () const + { + return target != nullptr + ? prerequisite_key {target->key (), nullptr} + : prerequisite.get ().key (); + } + + const build::target_type& + type () const + { + return target != nullptr ? target->type () : prerequisite.get ().type; + } + + target_type& + search () const + { + return target != nullptr ? *target : build::search (prerequisite); + } + + prerequisite_type& + as_prerequisite (tracer&) const; + }; + + inline std::ostream& + operator<< (std::ostream& os, const prerequisite_member& pm) + { + return os << pm.key (); + } + + // A "range" that presents a sequence of prerequisites (e.g., from + // group_prerequisites()) as a sequence of prerequisite_member's. For + // each prerequisite you will first "see" the prerequisite itself + // followed by all its members, if it resolves to a target group. + // You can skip the group members with the skip_group() iterator + // function. Usage: + // + // for (prerequisite_member pm: prerequisite_members (a, ...)) + // + // Where ... can be: + // + // t.prerequisites + // reverse_iterate(t.prerequisites) + // group_prerequisites (t) + // reverse_iterate (group_prerequisites (t)) + // + // But use shortcuts instead: + // + // prerequisite_members (a, t) + // reverse_prerequisite_members (a, t) + // group_prerequisite_members (a, t) + // reverse_group_prerequisite_members (a, t) + // + template <typename T> + class prerequisite_members_range; + + template <typename T> + inline prerequisite_members_range<T> + prerequisite_members (action a, T&& x) + { + return prerequisite_members_range<T> (a, std::forward<T> (x)); + } + + template <typename T> + class prerequisite_members_range + { + public: + prerequisite_members_range (action a, T&& r) + : a_ (a), r_ (std::forward<T> (r)) {} + + struct iterator + { + using base_iterator = decltype (std::declval<T> ().begin ()); + + typedef prerequisite_member value_type; + typedef const value_type* pointer; + typedef const value_type& reference; + typedef typename base_iterator::difference_type difference_type; + typedef std::forward_iterator_tag iterator_category; + + iterator (): a_ (0, 0) {} + iterator (action a, base_iterator i): a_ (a), i_ (i), g_ {nullptr, 0} {} + + iterator& operator++ (); + iterator operator++ (int) {iterator r (*this); return ++r;} + + // Skip iterating over this group's members, if any. Note that + // the only valid operation after this call is to increment the + // iterator. + // + // + void + skip_group () + { + // Pretend we are on the last member of some group. + // + j_ = 0; + g_.count = 1; + } + + /* + reference operator* () const + { + m_.prerequisite = *i; + m_.target = g_.count != 0 ? g_.members[j_] : nullptr; + return m_; + } + */ + + value_type operator* () const + { + return value_type {*i_, g_.count != 0 ? g_.members[j_] : nullptr}; + } + + pointer operator-> () const + { + static_assert ( + std::is_trivially_destructible<prerequisite_member>::value, + "prerequisite_member is not trivially destructible"); + + return new (&m_) + value_type {*i_, g_.count != 0 ? g_.members[j_] : nullptr}; + } + + friend bool + operator== (const iterator& x, const iterator& y) + { + return x.i_ == y.i_ && + x.g_.count == y.g_.count && + (x.g_.count == 0 || x.j_ == y.j_); + } + + friend bool + operator!= (const iterator& x, const iterator& y) {return !(x == y);} + + private: + action a_; + base_iterator i_; + group_view g_; + std::size_t j_; + mutable std::aligned_storage<sizeof (prerequisite_member), + alignof (prerequisite_member)>::type m_; + }; + + iterator + begin () const {return iterator (a_, r_.begin ());} + + iterator + end () const {return iterator (a_, r_.end ());} + + private: + action a_; + T r_; + }; + + // prerequisite_members(t.prerequisites) + // + inline auto + prerequisite_members (action a, target& t) + { + return prerequisite_members (a, t.prerequisites); + } + + // prerequisite_members(reverse_iterate(t.prerequisites)) + // + inline auto + reverse_prerequisite_members (action a, target& t) + { + return prerequisite_members (a, butl::reverse_iterate (t.prerequisites)); + } + + // prerequisite_members(group_prerequisites (t)) + // + inline auto + group_prerequisite_members (action a, target& t) + { + return prerequisite_members (a, group_prerequisites (t)); + } + + // prerequisite_members(reverse_iterate (group_prerequisites (t))) + // + inline auto + reverse_group_prerequisite_members (action a, target& t) + { + return prerequisite_members ( + a, butl::reverse_iterate (group_prerequisites (t))); + } + // Modification time-based target. // class mtime_target: public target |