From 1397444e5de3281431d2174564dfd76fe7b7b32f Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 21 Apr 2016 07:19:03 +0200 Subject: Use hash map/set for targets/prerequisites to resolve key change issue --- build2/target-key | 64 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 22 deletions(-) (limited to 'build2/target-key') diff --git a/build2/target-key b/build2/target-key index 2c0d0f2..c911a1f 100644 --- a/build2/target-key +++ b/build2/target-key @@ -6,6 +6,7 @@ #define BUILD2_TARGET_KEY #include +#include // hash #include // compare_c_string @@ -25,30 +26,26 @@ namespace build2 const dir_path* const dir; // Can be relative if part of prerequisite_key. const dir_path* const out; // Can be relative if part of prerequisite_key. const string* const name; - const string* const& ext; - - friend bool - operator< (const target_key& x, const target_key& y) - { - const target_type* xt (x.type); - const target_type* yt (y.type); - - int t, n, d, o; - - // Unspecified and specified extension are assumed equal. The - // extension strings are from the pool, so we can just compare - // pointers. - // - return - ((t = xt < yt ? -1 : xt > yt ? 1 : 0) < 0) || - (t == 0 && (n = x.name->compare (*y.name)) < 0) || - (t == 0 && n == 0 && (d = x.dir->compare (*y.dir)) < 0) || - (t == 0 && n == 0 && d == 0 && (o = x.out->compare (*y.out)) < 0) || - (t == 0 && n == 0 && d == 0 && o == 0 && - x.ext != nullptr && y.ext != nullptr && *x.ext < *y.ext); - } + const string* const& ext; //@@ Iffy, whan happens when move/copy? }; + inline bool + operator== (const target_key& x, const target_key& y) + { + // Unspecified and specified extension are assumed equal. The extension + // strings are from the pool, so we can just compare pointers. + // + return + x.type == y.type && + *x.dir == *y.dir && + *x.out == *y.out && + *x.name == *y.name && + (x.ext == nullptr || y.ext == nullptr || x.ext == y.ext); + } + + inline bool + operator!= (const target_key& x, const target_key& y) {return !(x == y);} + // If the target type has a custom print function, call that. Otherwise, // call to_stream() with the current stream verbosity as a third argument. // Both are defined in target.cxx. @@ -60,4 +57,27 @@ namespace build2 to_stream (ostream&, const target_key&, uint16_t ext_verb); } +namespace std +{ + // Note that we ignore the extension when calculating the hash because of + // its special "unspecified" logic (see operator== above). + // + template <> + struct hash + { + using argument_type = build2::target_key; + using result_type = size_t; + + size_t + operator() (const build2::target_key& k) const noexcept + { + return build2::combine_hash ( + hash () (k.type), + hash () (*k.dir), + hash () (*k.out), + hash () (*k.name)); + } + }; +} + #endif // BUILD2_TARGET_KEY -- cgit v1.1