aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar mtklein <mtklein@chromium.org>2015-10-15 12:23:01 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-10-15 12:23:02 -0700
commitc8d1dd48c01f562cfffe64da0e5cee5ed2713541 (patch)
treed561462e44e5b2f644b41c1fd670c1e66c5f03de
parentb9519f86bbce946e505980a4fa950fdc4bcf74ab (diff)
SkTHash: hash from fnptr to functor type
Passing &SkGoodHash to SkTHashMap and SkTHashSet doesn't guarantee that it's actually instantiated. Using a functor does. BUG=skia: Review URL: https://codereview.chromium.org/1405053002
-rw-r--r--dm/DM.cpp6
-rw-r--r--include/private/SkChecksum.h21
-rw-r--r--include/private/SkTHash.h8
-rw-r--r--src/pdf/SkPDFCanon.h10
-rw-r--r--tests/ChecksumTest.cpp12
-rw-r--r--tests/HashTest.cpp10
6 files changed, 39 insertions, 28 deletions
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 4b32d2fc1a..ccff84c906 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -144,7 +144,11 @@ struct Gold : public SkString {
this->append(name);
this->append(md5);
}
- static uint32_t Hash(const Gold& g) { return SkGoodHash((const SkString&)g); }
+ struct Hash {
+ uint32_t operator()(const Gold& g) const {
+ return SkGoodHash()((const SkString&)g);
+ }
+ };
};
static SkTHashSet<Gold, Gold::Hash> gGold;
diff --git a/include/private/SkChecksum.h b/include/private/SkChecksum.h
index 8eb1766ec0..cbc8a73a3e 100644
--- a/include/private/SkChecksum.h
+++ b/include/private/SkChecksum.h
@@ -182,17 +182,20 @@ public:
// SkGoodHash should usually be your first choice in hashing data.
// It should be both reasonably fast and high quality.
-
-template <typename K>
-uint32_t SkGoodHash(const K& k) {
- if (sizeof(K) == 4) {
+struct SkGoodHash {
+ template <typename K>
+ SK_WHEN(sizeof(K) == 4, uint32_t) operator()(const K& k) const {
return SkChecksum::Mix(*(const uint32_t*)&k);
}
- return SkChecksum::Murmur3(&k, sizeof(K));
-}
-inline uint32_t SkGoodHash(const SkString& k) {
- return SkChecksum::Murmur3(k.c_str(), k.size());
-}
+ template <typename K>
+ SK_WHEN(sizeof(K) != 4, uint32_t) operator()(const K& k) const {
+ return SkChecksum::Murmur3(&k, sizeof(K));
+ }
+
+ uint32_t operator()(const SkString& k) const {
+ return SkChecksum::Murmur3(k.c_str(), k.size());
+ }
+};
#endif
diff --git a/include/private/SkTHash.h b/include/private/SkTHash.h
index 53d52754bd..8a644e3b01 100644
--- a/include/private/SkTHash.h
+++ b/include/private/SkTHash.h
@@ -191,7 +191,7 @@ private:
// Maps K->V. A more user-friendly wrapper around SkTHashTable, suitable for most use cases.
// K and V are treated as ordinary copyable C++ types, with no assumed relationship between the two.
-template <typename K, typename V, uint32_t(*HashK)(const K&) = &SkGoodHash>
+template <typename K, typename V, typename HashK = SkGoodHash>
class SkTHashMap : SkNoncopyable {
public:
SkTHashMap() {}
@@ -247,14 +247,14 @@ private:
K key;
V val;
static const K& GetKey(const Pair& p) { return p.key; }
- static uint32_t Hash(const K& key) { return HashK(key); }
+ static uint32_t Hash(const K& key) { return HashK()(key); }
};
SkTHashTable<Pair, K> fTable;
};
// A set of T. T is treated as an ordiary copyable C++ type.
-template <typename T, uint32_t(*HashT)(const T&) = &SkGoodHash>
+template <typename T, typename HashT = SkGoodHash>
class SkTHashSet : SkNoncopyable {
public:
SkTHashSet() {}
@@ -293,7 +293,7 @@ public:
private:
struct Traits {
static const T& GetKey(const T& item) { return item; }
- static uint32_t Hash(const T& item) { return HashT(item); }
+ static uint32_t Hash(const T& item) { return HashT()(item); }
};
SkTHashTable<T, T, Traits> fTable;
};
diff --git a/src/pdf/SkPDFCanon.h b/src/pdf/SkPDFCanon.h
index 988b2855e1..3d2ba6a77d 100644
--- a/src/pdf/SkPDFCanon.h
+++ b/src/pdf/SkPDFCanon.h
@@ -102,10 +102,12 @@ private:
SkASSERT(rhs.fPtr);
return *fPtr == *rhs.fPtr;
}
- static uint32_t Hash(const WrapGS& w) {
- SkASSERT(w.fPtr);
- return w.fPtr->hash();
- }
+ struct Hash {
+ uint32_t operator()(const WrapGS& w) const {
+ SkASSERT(w.fPtr);
+ return w.fPtr->hash();
+ }
+ };
};
SkTHashSet<WrapGS, WrapGS::Hash> fGraphicStateRecords;
diff --git a/tests/ChecksumTest.cpp b/tests/ChecksumTest.cpp
index 0302ea9886..c095a5ac11 100644
--- a/tests/ChecksumTest.cpp
+++ b/tests/ChecksumTest.cpp
@@ -52,14 +52,14 @@ DEF_TEST(Checksum, r) {
}
DEF_TEST(GoodHash, r) {
- ASSERT(SkGoodHash(( int32_t)4) == 614249093); // 4 bytes. Hits SkChecksum::Mix fast path.
- ASSERT(SkGoodHash((uint32_t)4) == 614249093); // (Ditto)
+ ASSERT(SkGoodHash()(( int32_t)4) == 614249093); // 4 bytes. Hits SkChecksum::Mix fast path.
+ ASSERT(SkGoodHash()((uint32_t)4) == 614249093); // (Ditto)
// None of these are 4 byte sized, so they use SkChecksum::Murmur3, not SkChecksum::Mix.
- ASSERT(SkGoodHash((uint64_t)4) == 3491892518);
- ASSERT(SkGoodHash((uint16_t)4) == 899251846);
- ASSERT(SkGoodHash( (uint8_t)4) == 962700458);
+ ASSERT(SkGoodHash()((uint64_t)4) == 3491892518);
+ ASSERT(SkGoodHash()((uint16_t)4) == 899251846);
+ ASSERT(SkGoodHash()( (uint8_t)4) == 962700458);
// Tests SkString is correctly specialized.
- ASSERT(SkGoodHash(SkString("Hi")) == 55667557);
+ ASSERT(SkGoodHash()(SkString("Hi")) == 55667557);
}
diff --git a/tests/HashTest.cpp b/tests/HashTest.cpp
index c90c377cc2..c9b1bc967b 100644
--- a/tests/HashTest.cpp
+++ b/tests/HashTest.cpp
@@ -120,14 +120,16 @@ private:
uint32_t* fCounter;
};
-uint32_t hash_copy_counter(const CopyCounter&) {
- return 0; // let them collide, what do we care?
-}
+struct HashCopyCounter {
+ uint32_t operator()(const CopyCounter&) const {
+ return 0; // let them collide, what do we care?
+ }
+};
}
DEF_TEST(HashSetCopyCounter, r) {
- SkTHashSet<CopyCounter, hash_copy_counter> set;
+ SkTHashSet<CopyCounter, HashCopyCounter> set;
uint32_t globalCounter = 0;
CopyCounter copyCounter1(1, &globalCounter);