summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYves Orton <demerphq@gmail.com>2012-12-03 11:49:00 +0100
committerYves Orton <demerphq@gmail.com>2012-12-03 11:49:00 +0100
commit8c9e24c7f6088cb5fe0779c2c11c1fb4ca8ae693 (patch)
tree581f3bfeccb0e1921e7ab9ddd401971face6ea43
parentc1abd561a0a322ca22ba5ef8301a708c37336afb (diff)
downloadperl-8c9e24c7f6088cb5fe0779c2c11c1fb4ca8ae693.tar.gz
Make it possible to simulate old style one-at-a-time hashing
With a 0 seed and ONE_AT_A_TIME_OLD hashing enabled one can simulate older perls (with the exception there is no rehashing at play). This includes a modest tweak to reduce ops per character by comparing the string pointer to the end of the string, instead of maintaining a position counter.
-rw-r--r--hv.h33
1 files changed, 25 insertions, 8 deletions
diff --git a/hv.h b/hv.h
index 969e9d3d2a..3937b5d488 100644
--- a/hv.h
+++ b/hv.h
@@ -143,11 +143,19 @@ struct xpvhv {
#define PERL_HASH_FUNC_MURMUR3
#define PERL_HASH_FUNC_SIPHASH
#define PERL_HASH_FUNC_ONE_AT_A_TIME
+#define PERL_HASH_FUNC_ONE_AT_A_TIME_OLD
#define PERL_HASH_FUNC_BUZZHASH16
*/
-#if !(defined(PERL_HASH_FUNC_SDBM) || defined(PERL_HASH_FUNC_DJB2) || defined(PERL_HASH_FUNC_SUPERFAST) \
- || defined(PERL_HASH_FUNC_MURMUR3) || defined(PERL_HASH_FUNC_ONE_AT_A_TIME) || defined(PERL_HASH_FUNC_BUZZHASH16))
+#if !( 0 \
+ || defined(PERL_HASH_FUNC_SDBM) \
+ || defined(PERL_HASH_FUNC_DJB2) \
+ || defined(PERL_HASH_FUNC_SUPERFAST) \
+ || defined(PERL_HASH_FUNC_MURMUR3) \
+ || defined(PERL_HASH_FUNC_ONE_AT_A_TIME) \
+ || defined(PERL_HASH_FUNC_ONE_AT_A_TIME_OLD) \
+ || defined(PERL_HASH_FUNC_BUZZHASH16) \
+ )
#define PERL_HASH_FUNC_MURMUR3
#endif
@@ -627,11 +635,20 @@ struct xpvhv {
(hash) = hash_PeRlHaSh;\
} STMT_END
-#elif defined(PERL_HASH_FUNC_ONE_AT_A_TIME)
-/* DEFAULT/HISTORIC HASH FUNCTION */
-#define PERL_HASH_FUNC "ONE_AT_A_TIME"
+#elif defined(PERL_HASH_FUNC_ONE_AT_A_TIME) || defined(PERL_HASH_FUNC_ONE_AT_A_TIME_OLD)
+
#define PERL_HASH_SEED_BYTES 4
+#ifdef PERL_HASH_FUNC_ONE_AT_A_TIME
+/* new version, add the length to the seed so that adding characters changes the "seed" being used. */
+#define PERL_HASH_FUNC "ONE_AT_A_TIME"
+#define MIX_SEED_AND_LEN(seed,len) (seed + len)
+#else
+/* old version, just use the seed. - not recommended */
+#define PERL_HASH_FUNC "ONE_AT_A_TIME_OLD"
+#define MIX_SEED_AND_LEN(seed,len) (seed)
+#endif
+
/* FYI: This is the "One-at-a-Time" algorithm by Bob Jenkins
* from requirements by Colin Plumb.
* (http://burtleburtle.net/bob/hash/doobs.html) */
@@ -639,9 +656,9 @@ struct xpvhv {
STMT_START { \
const char * const s_PeRlHaSh_tmp = (str); \
const unsigned char *s_PeRlHaSh = (const unsigned char *)s_PeRlHaSh_tmp; \
- I32 i_PeRlHaSh = len; \
- U32 hash_PeRlHaSh = PERL_HASH_SEED_U32 ^ len; \
- while (i_PeRlHaSh--) { \
+ const unsigned char *end_PeRlHaSh = (const unsigned char *)s_PeRlHaSh_tmp + (len); \
+ U32 hash_PeRlHaSh = MIX_SEED_AND_LEN(PERL_HASH_SEED_U32, len); \
+ while (s_PeRlHaSh < end_PeRlHaSh) { \
hash_PeRlHaSh += (U8)*s_PeRlHaSh++; \
hash_PeRlHaSh += (hash_PeRlHaSh << 10); \
hash_PeRlHaSh ^= (hash_PeRlHaSh >> 6); \