From fd689eb883655dcb29e505b041cd02fac01f0bac Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 27 Aug 2015 15:11:40 +0200 Subject: Dist module/meta-operation initial implementation --- build/rule-map | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 7 deletions(-) (limited to 'build/rule-map') diff --git a/build/rule-map b/build/rule-map index 883800b..0ef0036 100644 --- a/build/rule-map +++ b/build/rule-map @@ -8,8 +8,9 @@ #include #include #include +#include // unique_ptr #include -#include // reference_wrapper +#include // reference_wrapper #include @@ -25,21 +26,76 @@ namespace build butl::prefix_map, '.'>>; - // This is an "indexed map" with (operation_id - 1) being the - // index. + // This is an "indexed map" with operation_id being the index. Entry + // with id 0 is a wildcard. // - class rule_map: public std::vector + class operation_rule_map { public: template void insert (operation_id oid, const char* hint, rule& r) { - if (oid > size ()) - resize (oid < 3 ? 3 : oid); // 3 is the number of builtin operations. + // 3 is the number of builtin operations. + // + if (oid >= map_.size ()) + map_.resize ((oid < 3 ? 3 : oid) + 1); - (*this)[oid - 1][typeid (T)].emplace (hint, r); + map_[oid][typeid (T)].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; + } + + private: + std::vector 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 + void + insert (meta_operation_id mid, operation_id oid, const char* hint, rule& r) + { + if (mid_ == mid) + map_.insert (oid, hint, r); + else + { + if (next_ == nullptr) + next_.reset (new rule_map (mid)); + + next_->insert (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) {} + + private: + meta_operation_id mid_; + operation_rule_map map_; + std::unique_ptr next_; }; } -- cgit v1.1