summaryrefslogtreecommitdiffstats
path: root/zix
diff options
context:
space:
mode:
Diffstat (limited to 'zix')
-rw-r--r--zix/digest.c90
-rw-r--r--zix/digest.h26
2 files changed, 103 insertions, 13 deletions
diff --git a/zix/digest.c b/zix/digest.c
index d6ceb0e..4fc7608 100644
--- a/zix/digest.c
+++ b/zix/digest.c
@@ -1,5 +1,5 @@
/*
- Copyright 2012-2014 David Robillard <http://drobilla.net>
+ Copyright 2012-2020 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -20,23 +20,29 @@
# include <smmintrin.h>
#endif
+#include <assert.h>
+#include <stdint.h>
+
+#ifdef __SSE4_2__
+
+// SSE 4.2 CRC32
+
ZIX_API uint32_t
zix_digest_start(void)
{
-#ifdef __SSE4_2__
- return 1; // CRC32 initial value
-#else
- return 5381; // DJB hash initial value
-#endif
+ return 1;
}
ZIX_API uint32_t
zix_digest_add(uint32_t hash, const void* const buf, const size_t len)
{
const uint8_t* str = (const uint8_t*)buf;
-#ifdef __SSE4_2__
- // SSE 4.2 CRC32
- for (size_t i = 0; i < (len / sizeof(uint32_t)); ++i) {
+
+ for (size_t i = 0; i < (len / sizeof(uint64_t)); ++i) {
+ hash = (uint32_t)_mm_crc32_u64(hash, *(const uint64_t*)str);
+ str += sizeof(uint64_t);
+ }
+ if (len & sizeof(uint32_t)) {
hash = _mm_crc32_u32(hash, *(const uint32_t*)str);
str += sizeof(uint32_t);
}
@@ -47,11 +53,71 @@ zix_digest_add(uint32_t hash, const void* const buf, const size_t len)
if (len & sizeof(uint8_t)) {
hash = _mm_crc32_u8(hash, *(const uint8_t*)str);
}
+
+ return hash;
+}
+
+ZIX_API uint32_t
+zix_digest_add_64(uint32_t hash, const void* const buf, const size_t len)
+{
+ assert((uintptr_t)buf % sizeof(uint64_t) == 0);
+ assert(len % sizeof(uint64_t) == 0);
+
+ const uint64_t* ptr = (const uint64_t*)buf;
+
+ for (size_t i = 0; i < (len / sizeof(uint64_t)); ++i) {
+ hash = (uint32_t)_mm_crc32_u64(hash, *ptr);
+ ++ptr;
+ }
+
+ return hash;
+}
+
+ZIX_API uint32_t
+zix_digest_add_ptr(const uint32_t hash, const void* const ptr)
+{
+#if UINTPTR_MAX == UINT64_MAX
+ return (uint32_t)_mm_crc32_u64(hash, (uintptr_t)ptr);
+#else
+ return _mm_crc32_u32(hash, (uintptr_t)ptr);
+#endif
+}
+
#else
- // Classic DJB hash
+
+// Classic DJB hash
+
+ZIX_API uint32_t
+zix_digest_start(void)
+{
+ return 5381;
+}
+
+ZIX_API uint32_t
+zix_digest_add(uint32_t hash, const void* const buf, const size_t len)
+{
+ const uint8_t* str = (const uint8_t*)buf;
+
for (size_t i = 0; i < len; ++i) {
- hash = (hash << 5u) + hash + str[i];
+ hash = (hash << 5) + hash + str[i];
}
-#endif
+
return hash;
}
+
+ZIX_API uint32_t
+zix_digest_add_64(uint32_t hash, const void* const buf, const size_t len)
+{
+ assert((uintptr_t)buf % sizeof(uint64_t) == 0);
+ assert(len % sizeof(uint64_t) == 0);
+
+ return zix_digest_add(hash, buf, len);
+}
+
+ZIX_API uint32_t
+zix_digest_add_ptr(const uint32_t hash, const void* const ptr)
+{
+ return zix_digest_add(hash, &ptr, sizeof(ptr));
+}
+
+#endif
diff --git a/zix/digest.h b/zix/digest.h
index 264c918..16ba9b9 100644
--- a/zix/digest.h
+++ b/zix/digest.h
@@ -1,5 +1,5 @@
/*
- Copyright 2012 David Robillard <http://drobilla.net>
+ Copyright 2012-2020 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -26,12 +26,36 @@
extern "C" {
#endif
+/**
+ Return an initial empty digest value.
+*/
ZIX_API uint32_t
zix_digest_start(void);
+/**
+ Update `hash` to include `buf`, a buffer of `len` bytes.
+
+ This can be used for any size or alignment.
+*/
ZIX_API uint32_t
zix_digest_add(uint32_t hash, const void* buf, size_t len);
+/**
+ Update `hash` to include `buf`, a 64-bit aligned buffer of `len` bytes.
+
+ Both `buf` and `len` must be evenly divisible by 8 (64 bits).
+*/
+ZIX_API uint32_t
+zix_digest_add_64(uint32_t hash, const void* buf, size_t len);
+
+/**
+ Update `hash` to include `ptr`.
+
+ This hashes the value of the pointer itself, and does not dereference `ptr`.
+*/
+ZIX_API uint32_t
+zix_digest_add_ptr(uint32_t hash, const void* ptr);
+
#ifdef __cplusplus
} /* extern "C" */
#endif