diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2016-01-05 11:55:15 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2016-01-05 11:55:15 +0200 |
commit | 9fb791e9fad6c63fc1dac49f4d05ae63b8a3db9b (patch) | |
tree | d60322d4382ca5f97b676c5abe2e39524f35eab4 /build2/rule-map | |
parent | f159b1dac68c8714f7ba71ca168e3b695891aad9 (diff) |
Rename build directory/namespace to build2
Diffstat (limited to 'build2/rule-map')
-rw-r--r-- | build2/rule-map | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/build2/rule-map b/build2/rule-map new file mode 100644 index 0000000..f86ef16 --- /dev/null +++ b/build2/rule-map @@ -0,0 +1,115 @@ +// file : build2/rule-map -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_RULE_MAP +#define BUILD2_RULE_MAP + +#include <map> +#include <vector> +#include <string> +#include <memory> // unique_ptr +#include <functional> // reference_wrapper + +#include <butl/prefix-map> + +#include <build2/types> +#include <build2/operation> + +namespace build2 +{ + class rule; + + using target_type_rule_map = std::map< + const target_type*, + butl::prefix_map<std::string, // Rule hint. + std::reference_wrapper<rule>, '.'>>; + + // This is an "indexed map" with operation_id being the index. Entry + // with id 0 is a wildcard. + // + class operation_rule_map + { + public: + template <typename T> + void + insert (operation_id oid, const char* hint, rule& r) + { + // 3 is the number of builtin operations. + // + if (oid >= map_.size ()) + map_.resize ((oid < 3 ? 3 : oid) + 1); + + map_[oid][&T::static_type].emplace (hint, r); + } + + // Return NULL if not found. + // + const target_type_rule_map* + operator[] (operation_id oid) const + { + return map_.size () > oid ? &map_[oid] : nullptr; + } + + bool + empty () const {return map_.empty ();} + + private: + std::vector<target_type_rule_map> map_; + }; + + // This is another indexed map but this time meta_operation_id is the + // index. The implementation is different, however: here we use a linked + // list with the first, statically-allocated node corresponding to the + // perform meta-operation. The idea is to try and get away with a dynamic + // allocation for the common cases since most rules will be registered + // for perform, at least on non-root scopes. + // + class rule_map + { + public: + + template <typename T> + void + insert (action_id a, const char* hint, rule& r) + { + insert<T> (a >> 4, a & 0x0F, hint, r); + } + + template <typename T> + void + insert (meta_operation_id mid, operation_id oid, const char* hint, rule& r) + { + if (mid_ == mid) + map_.insert<T> (oid, hint, r); + else + { + if (next_ == nullptr) + next_.reset (new rule_map (mid)); + + next_->insert<T> (mid, oid, hint, r); + } + } + + // Return NULL if not found. + // + const operation_rule_map* + operator[] (meta_operation_id mid) const + { + return mid == mid_ ? &map_ : next_ == nullptr ? nullptr : (*next_)[mid]; + } + + explicit + rule_map (meta_operation_id mid = perform_id): mid_ (mid) {} + + bool + empty () const {return map_.empty () && next_ == nullptr;} + + private: + meta_operation_id mid_; + operation_rule_map map_; + std::unique_ptr<rule_map> next_; + }; +} + +#endif // BUILD2_RULE_MAP |