aboutsummaryrefslogtreecommitdiff
path: root/build2/target-key
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-04-21 07:19:03 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-04-21 07:19:03 +0200
commit1397444e5de3281431d2174564dfd76fe7b7b32f (patch)
treea58a822b31ae403f83868bdc8157d4caa82c32f8 /build2/target-key
parent855ee25d977c3e658162210de3c418922e1fe949 (diff)
Use hash map/set for targets/prerequisites to resolve key change issue
Diffstat (limited to 'build2/target-key')
-rw-r--r--build2/target-key64
1 files changed, 42 insertions, 22 deletions
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 <map>
+#include <functional> // hash
#include <butl/utility> // 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<build2::target_key>
+ {
+ 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<const build2::target_type*> () (k.type),
+ hash<build2::dir_path> () (*k.dir),
+ hash<build2::dir_path> () (*k.out),
+ hash<string> () (*k.name));
+ }
+ };
+}
+
#endif // BUILD2_TARGET_KEY