From a56f19c4f9c8ed5f916d7edbe1f73b7b49e68e83 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 Apr 2013 17:49:18 +0200 Subject: [PATCH] kdbus: generare bloom filters properly for messages we send --- Makefile.am | 8 +- src/libsystemd-bus/bus-bloom.c | 93 +++++++ src/libsystemd-bus/bus-bloom.h | 30 +++ src/libsystemd-bus/bus-internal.c | 13 + src/libsystemd-bus/bus-internal.h | 3 +- src/libsystemd-bus/bus-kernel.c | 93 ++++++- src/libsystemd-bus/test-bus-kernel.c | 2 +- src/shared/MurmurHash3.c | 349 +++++++++++++++++++++++++++ src/shared/MurmurHash3.h | 38 +++ 9 files changed, 615 insertions(+), 14 deletions(-) create mode 100644 src/libsystemd-bus/bus-bloom.c create mode 100644 src/libsystemd-bus/bus-bloom.h create mode 100644 src/shared/MurmurHash3.c create mode 100644 src/shared/MurmurHash3.h diff --git a/Makefile.am b/Makefile.am index eee73e595..5a632a909 100644 --- a/Makefile.am +++ b/Makefile.am @@ -680,7 +680,9 @@ libsystemd_shared_la_SOURCES = \ src/shared/calendarspec.h \ src/shared/fileio.c \ src/shared/fileio.h \ - src/shared/output-mode.h + src/shared/output-mode.h \ + src/shared/MurmurHash3.c \ + src/shared/MurmurHash3.h #------------------------------------------------------------------------------- noinst_LTLIBRARIES += \ @@ -1711,7 +1713,9 @@ libsystemd_bus_la_SOURCES = \ src/libsystemd-bus/bus-type.c \ src/libsystemd-bus/bus-type.h \ src/libsystemd-bus/bus-match.c \ - src/libsystemd-bus/bus-match.h + src/libsystemd-bus/bus-match.h \ + src/libsystemd-bus/bus-bloom.c \ + src/libsystemd-bus/bus-bloom.h libsystemd_bus_la_LIBADD = \ libsystemd-id128-internal.la \ diff --git a/src/libsystemd-bus/bus-bloom.c b/src/libsystemd-bus/bus-bloom.c new file mode 100644 index 000000000..cb65e47b4 --- /dev/null +++ b/src/libsystemd-bus/bus-bloom.c @@ -0,0 +1,93 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "util.h" +#include "MurmurHash3.h" + +#include "bus-bloom.h" + +static inline void set_bit(uint64_t filter[], unsigned b) { + filter[b >> 6] |= 1ULL << (b & 63); +} + +void bloom_add_data(uint64_t filter[BLOOM_SIZE/8], const void *data, size_t n) { + uint16_t hash[8]; + unsigned k = 0; + + /* + * Our bloom filter has the following parameters: + * + * m=512 (bits in the filter) + * k=8 (hash functions) + * + * We calculate a single 128bit MurmurHash value of which we + * use 8 parts of 9 bits as individual hash functions. + * + */ + + MurmurHash3_x64_128(data, n, 0, hash); + + assert_cc(BLOOM_SIZE*8 == 512); + + for (k = 0; k < ELEMENTSOF(hash); k++) + set_bit(filter, hash[k] & 511); +} + +void bloom_add_pair(uint64_t filter[BLOOM_SIZE/8], const char *a, const char *b) { + size_t n; + char *c; + + assert(filter); + assert(a); + assert(b); + + n = strlen(a) + 1 + strlen(b); + c = alloca(n + 1); + strcpy(stpcpy(stpcpy(c, a), ":"), b); + + bloom_add_data(filter, c, n); +} + +void bloom_add_prefixes(uint64_t filter[BLOOM_SIZE/8], const char *a, const char *b, char sep) { + size_t n; + char *c, *p; + + assert(filter); + assert(a); + assert(b); + + n = strlen(a) + 1 + strlen(b); + c = alloca(n + 1); + + p = stpcpy(stpcpy(c, a), ":"); + strcpy(p, b); + + for (;;) { + char *e; + + e = strrchr(p, sep); + if (!e || e == p) + break; + + *e = 0; + bloom_add_data(filter, c, e - c); + } +} diff --git a/src/libsystemd-bus/bus-bloom.h b/src/libsystemd-bus/bus-bloom.h new file mode 100644 index 000000000..1bf14a333 --- /dev/null +++ b/src/libsystemd-bus/bus-bloom.h @@ -0,0 +1,30 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2013 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include + +#define BLOOM_SIZE 64 + +void bloom_add_data(uint64_t filter[BLOOM_SIZE/8], const void *data, size_t n); +void bloom_add_pair(uint64_t filter[BLOOM_SIZE/8], const char *a, const char *b); +void bloom_add_prefixes(uint64_t filter[BLOOM_SIZE/8], const char *a, const char *b, char sep); diff --git a/src/libsystemd-bus/bus-internal.c b/src/libsystemd-bus/bus-internal.c index 327135460..0e66f3d35 100644 --- a/src/libsystemd-bus/bus-internal.c +++ b/src/libsystemd-bus/bus-internal.c @@ -241,3 +241,16 @@ int bus_message_type_from_string(const char *s, uint8_t *u) { return 0; } + +const char *bus_message_type_to_string(uint8_t u) { + if (u == SD_BUS_MESSAGE_TYPE_SIGNAL) + return "signal"; + else if (u == SD_BUS_MESSAGE_TYPE_METHOD_CALL) + return "method_call"; + else if (u == SD_BUS_MESSAGE_TYPE_METHOD_ERROR) + return "error"; + else if (u == SD_BUS_MESSAGE_TYPE_METHOD_RETURN) + return "method_return"; + else + return NULL; +} diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h index 9a118f8a2..4babfac86 100644 --- a/src/libsystemd-bus/bus-internal.h +++ b/src/libsystemd-bus/bus-internal.h @@ -150,8 +150,6 @@ struct sd_bus { uint64_t hello_serial; unsigned iteration_counter; - - uint64_t bloom_size; }; static inline void bus_unrefp(sd_bus **b) { @@ -191,6 +189,7 @@ bool namespace_simple_pattern(const char *pattern, const char *value); bool path_simple_pattern(const char *pattern, const char *value); int bus_message_type_from_string(const char *s, uint8_t *u); +const char *bus_message_type_to_string(uint8_t u); #define error_name_is_valid interface_name_is_valid diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c index 264c6994d..f36f60e49 100644 --- a/src/libsystemd-bus/bus-kernel.c +++ b/src/libsystemd-bus/bus-kernel.c @@ -30,6 +30,7 @@ #include "bus-internal.h" #include "bus-message.h" #include "bus-kernel.h" +#include "bus-bloom.h" #define KDBUS_MSG_FOREACH_DATA(d, k) \ for ((d) = (k)->data; \ @@ -80,17 +81,83 @@ static void append_destination(struct kdbus_msg_data **d, const char *s, size_t *d = (struct kdbus_msg_data*) ((uint8_t*) *d + (*d)->size); } -static void append_bloom(struct kdbus_msg_data **d, const void *p, size_t length) { +static void* append_bloom(struct kdbus_msg_data **d, size_t length) { + void *r; + assert(d); - assert(p); *d = ALIGN8_PTR(*d); (*d)->size = offsetof(struct kdbus_msg_data, data) + length; (*d)->type = KDBUS_MSG_BLOOM; - memcpy((*d)->data, p, length); + r = (*d)->data; *d = (struct kdbus_msg_data*) ((uint8_t*) *d + (*d)->size); + + return r; +} + +static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) { + unsigned i; + int r; + + assert(m); + assert(bloom); + + memset(bloom, 0, BLOOM_SIZE); + + bloom_add_pair(bloom, "message-type", bus_message_type_to_string(m->header->type)); + + if (m->interface) + bloom_add_pair(bloom, "interface", m->interface); + if (m->member) + bloom_add_pair(bloom, "member", m->member); + if (m->path) { + bloom_add_pair(bloom, "path", m->path); + bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/'); + } + + r = sd_bus_message_rewind(m, true); + if (r < 0) + return r; + + for (i = 0; i < 64; i++) { + char type; + const char *t; + char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")]; + char *e; + + r = sd_bus_message_peek_type(m, &type, NULL); + if (r < 0) + return r; + + if (type != SD_BUS_TYPE_STRING && + type != SD_BUS_TYPE_OBJECT_PATH && + type != SD_BUS_TYPE_SIGNATURE) + break; + + r = sd_bus_message_read_basic(m, type, &t); + if (r < 0) + return r; + + e = stpcpy(buf, "arg"); + if (i < 10) + *(e++) = '0' + i; + else { + *(e++) = '0' + (i / 10); + *(e++) = '0' + (i % 10); + } + + *e = 0; + bloom_add_pair(bloom, buf, t); + + strcpy(e, "-dot-prefix"); + bloom_add_prefixes(bloom, buf, t, '.'); + strcpy(e, "-slash-prefix"); + bloom_add_prefixes(bloom, buf, t, '/'); + } + + return 0; } static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { @@ -122,7 +189,7 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { sz += 3 * ALIGN8(offsetof(struct kdbus_msg_data, vec) + sizeof(struct kdbus_vec)); /* Add space for bloom filter */ - sz += ALIGN8(offsetof(struct kdbus_msg_data, data) + b->bloom_size); + sz += ALIGN8(offsetof(struct kdbus_msg_data, data) + BLOOM_SIZE); /* Add in well-known destination header */ if (well_known) { @@ -164,9 +231,13 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { void *p; /* For now, let's add a mask all bloom filter */ - p = alloca(b->bloom_size); - memset(p, 0xFF, b->bloom_size); - append_bloom(&d, p, b->bloom_size); + p = append_bloom(&d, BLOOM_SIZE); + r = bus_message_setup_bloom(m, p); + if (r < 0) { + free(m->kdbus); + m->kdbus = NULL; + return -r; + } } m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus; @@ -207,10 +278,12 @@ int bus_kernel_take_fd(sd_bus *b) { hello.conn_flags > 0xFFFFFFFFULL) return -ENOTSUP; + if (hello.bloom_size != BLOOM_SIZE) + return -ENOTSUP; + if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0) return -ENOMEM; - b->bloom_size = hello.bloom_size; b->is_kernel = true; b->bus_client = true; @@ -479,7 +552,9 @@ int bus_kernel_create(const char *name, char **s) { make->size = offsetof(struct kdbus_cmd_bus_make, name) + strlen(make->name) + 1; make->flags = KDBUS_ACCESS_WORLD | KDBUS_POLICY_OPEN; make->bus_flags = 0; - make->bloom_size = 16; + make->bloom_size = BLOOM_SIZE; + + assert_cc(BLOOM_SIZE % 8 == 0); p = strjoin("/dev/kdbus/", make->name, "/bus", NULL); if (!p) diff --git a/src/libsystemd-bus/test-bus-kernel.c b/src/libsystemd-bus/test-bus-kernel.c index 2164daf69..5a5d9fc25 100644 --- a/src/libsystemd-bus/test-bus-kernel.c +++ b/src/libsystemd-bus/test-bus-kernel.c @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) { printf("unique b: %s\n", ub); - r = sd_bus_emit_signal(a, "/foo", "waldo.com", "Piep", "s", "I am a string"); + r = sd_bus_emit_signal(a, "/foo/bar/waldo", "waldo.com", "Piep", "sss", "I am a string", "/this/is/a/path", "and.this.a.domain.name"); assert_se(r >= 0); r = sd_bus_process(b, &m); diff --git a/src/shared/MurmurHash3.c b/src/shared/MurmurHash3.c new file mode 100644 index 000000000..dc56f6b0f --- /dev/null +++ b/src/shared/MurmurHash3.c @@ -0,0 +1,349 @@ +//----------------------------------------------------------------------------- +// MurmurHash3 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. + +// Note - The x86 and x64 versions do _not_ produce the same results, as the +// algorithms are optimized for their respective platforms. You can still +// compile and run any of them on any platform, but your performance with the +// non-native version will be less than optimal. + +#include "MurmurHash3.h" + +//----------------------------------------------------------------------------- +// Platform-specific functions and macros + +// Microsoft Visual Studio + +#if defined(_MSC_VER) + +#define FORCE_INLINE __forceinline + +#include + +#define ROTL32(x,y) _rotl(x,y) +#define ROTL64(x,y) _rotl64(x,y) + +#define BIG_CONSTANT(x) (x) + +// Other compilers + +#else // defined(_MSC_VER) + +#define FORCE_INLINE __attribute__((always_inline)) + +static inline uint32_t rotl32 ( uint32_t x, int8_t r ) +{ + return (x << r) | (x >> (32 - r)); +} + +static inline uint64_t rotl64 ( uint64_t x, int8_t r ) +{ + return (x << r) | (x >> (64 - r)); +} + +#define ROTL32(x,y) rotl32(x,y) +#define ROTL64(x,y) rotl64(x,y) + +#define BIG_CONSTANT(x) (x##LLU) + +#endif // !defined(_MSC_VER) + +//----------------------------------------------------------------------------- +// Block read - if your platform needs to do endian-swapping or can only +// handle aligned reads, do the conversion here + +static FORCE_INLINE uint32_t getblock32 ( const uint32_t * p, int i ) +{ + return p[i]; +} + +static FORCE_INLINE uint64_t getblock64 ( const uint64_t * p, int i ) +{ + return p[i]; +} + +//----------------------------------------------------------------------------- +// Finalization mix - force all bits of a hash block to avalanche + +static FORCE_INLINE uint32_t fmix32 ( uint32_t h ) +{ + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + + return h; +} + +//---------- + +static FORCE_INLINE uint64_t fmix64 ( uint64_t k ) +{ + k ^= k >> 33; + k *= BIG_CONSTANT(0xff51afd7ed558ccd); + k ^= k >> 33; + k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53); + k ^= k >> 33; + + return k; +} + +//----------------------------------------------------------------------------- + +void MurmurHash3_x86_32 ( const void * key, size_t len, + uint32_t seed, void * out ) +{ + const uint8_t * data = (const uint8_t*)key; + const int nblocks = len / 4; + + uint32_t h1 = seed; + + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; + + const uint8_t * tail; + uint32_t k1; + + //---------- + // body + + const uint32_t * blocks = (const uint32_t *)(data + nblocks*4); + + for(int i = -nblocks; i; i++) + { + k1 = getblock32(blocks,i); + + k1 *= c1; + k1 = ROTL32(k1,15); + k1 *= c2; + + h1 ^= k1; + h1 = ROTL32(h1,13); + h1 = h1*5+0xe6546b64; + } + + //---------- + // tail + + tail = (const uint8_t*)(data + nblocks*4); + + k1 = 0; + + switch(len & 3) + { + case 3: k1 ^= tail[2] << 16; + case 2: k1 ^= tail[1] << 8; + case 1: k1 ^= tail[0]; + k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; + + h1 = fmix32(h1); + + *(uint32_t*)out = h1; +} + +//----------------------------------------------------------------------------- + +void MurmurHash3_x86_128 ( const void * key, const size_t len, + uint32_t seed, void * out ) +{ + const uint8_t * data = (const uint8_t*)key; + const int nblocks = len / 16; + + uint32_t h1 = seed; + uint32_t h2 = seed; + uint32_t h3 = seed; + uint32_t h4 = seed; + + const uint32_t c1 = 0x239b961b; + const uint32_t c2 = 0xab0e9789; + const uint32_t c3 = 0x38b34ae5; + const uint32_t c4 = 0xa1e38b93; + + const uint8_t * tail; + + uint32_t k1; + uint32_t k2; + uint32_t k3; + uint32_t k4; + + //---------- + // body + + const uint32_t * blocks = (const uint32_t *)(data + nblocks*16); + + for(int i = -nblocks; i; i++) + { + k1 = getblock32(blocks,i*4+0); + k2 = getblock32(blocks,i*4+1); + k3 = getblock32(blocks,i*4+2); + k4 = getblock32(blocks,i*4+3); + + k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + + h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b; + + k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2; + + h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747; + + k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3; + + h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35; + + k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4; + + h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17; + } + + //---------- + // tail + + tail = (const uint8_t*)(data + nblocks*16); + + k1 = 0; + k2 = 0; + k3 = 0; + k4 = 0; + + switch(len & 15) + { + case 15: k4 ^= tail[14] << 16; + case 14: k4 ^= tail[13] << 8; + case 13: k4 ^= tail[12] << 0; + k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4; + + case 12: k3 ^= tail[11] << 24; + case 11: k3 ^= tail[10] << 16; + case 10: k3 ^= tail[ 9] << 8; + case 9: k3 ^= tail[ 8] << 0; + k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3; + + case 8: k2 ^= tail[ 7] << 24; + case 7: k2 ^= tail[ 6] << 16; + case 6: k2 ^= tail[ 5] << 8; + case 5: k2 ^= tail[ 4] << 0; + k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2; + + case 4: k1 ^= tail[ 3] << 24; + case 3: k1 ^= tail[ 2] << 16; + case 2: k1 ^= tail[ 1] << 8; + case 1: k1 ^= tail[ 0] << 0; + k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len; + + h1 += h2; h1 += h3; h1 += h4; + h2 += h1; h3 += h1; h4 += h1; + + h1 = fmix32(h1); + h2 = fmix32(h2); + h3 = fmix32(h3); + h4 = fmix32(h4); + + h1 += h2; h1 += h3; h1 += h4; + h2 += h1; h3 += h1; h4 += h1; + + ((uint32_t*)out)[0] = h1; + ((uint32_t*)out)[1] = h2; + ((uint32_t*)out)[2] = h3; + ((uint32_t*)out)[3] = h4; +} + +//----------------------------------------------------------------------------- + +void MurmurHash3_x64_128 ( const void * key, const size_t len, + const uint32_t seed, void * out ) +{ + const uint8_t * data = (const uint8_t*)key; + const int nblocks = len / 16; + + uint64_t h1 = seed; + uint64_t h2 = seed; + + const uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5); + const uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f); + + const uint8_t *tail; + + uint64_t k1; + uint64_t k2; + + //---------- + // body + + const uint64_t * blocks = (const uint64_t *)(data); + + for(int i = 0; i < nblocks; i++) + { + k1 = getblock64(blocks,i*2+0); + k2 = getblock64(blocks,i*2+1); + + k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; + + h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729; + + k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2; + + h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5; + } + + //---------- + // tail + + tail = (const uint8_t*)(data + nblocks*16); + + k1 = 0; + k2 = 0; + + switch(len & 15) + { + case 15: k2 ^= (uint64_t)(tail[14]) << 48; + case 14: k2 ^= (uint64_t)(tail[13]) << 40; + case 13: k2 ^= (uint64_t)(tail[12]) << 32; + case 12: k2 ^= (uint64_t)(tail[11]) << 24; + case 11: k2 ^= (uint64_t)(tail[10]) << 16; + case 10: k2 ^= (uint64_t)(tail[ 9]) << 8; + case 9: k2 ^= (uint64_t)(tail[ 8]) << 0; + k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2; + + case 8: k1 ^= (uint64_t)(tail[ 7]) << 56; + case 7: k1 ^= (uint64_t)(tail[ 6]) << 48; + case 6: k1 ^= (uint64_t)(tail[ 5]) << 40; + case 5: k1 ^= (uint64_t)(tail[ 4]) << 32; + case 4: k1 ^= (uint64_t)(tail[ 3]) << 24; + case 3: k1 ^= (uint64_t)(tail[ 2]) << 16; + case 2: k1 ^= (uint64_t)(tail[ 1]) << 8; + case 1: k1 ^= (uint64_t)(tail[ 0]) << 0; + k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; h2 ^= len; + + h1 += h2; + h2 += h1; + + h1 = fmix64(h1); + h2 = fmix64(h2); + + h1 += h2; + h2 += h1; + + ((uint64_t*)out)[0] = h1; + ((uint64_t*)out)[1] = h2; +} + +//----------------------------------------------------------------------------- diff --git a/src/shared/MurmurHash3.h b/src/shared/MurmurHash3.h new file mode 100644 index 000000000..07c474eba --- /dev/null +++ b/src/shared/MurmurHash3.h @@ -0,0 +1,38 @@ +//----------------------------------------------------------------------------- +// MurmurHash3 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. + +#ifndef _MURMURHASH3_H_ +#define _MURMURHASH3_H_ + +//----------------------------------------------------------------------------- +// Platform-specific functions and macros + +// Microsoft Visual Studio + +#if defined(_MSC_VER) + +typedef unsigned char uint8_t; +typedef unsigned long uint32_t; +typedef unsigned __int64 uint64_t; + +// Other compilers + +#else // defined(_MSC_VER) + +#include +#include + +#endif // !defined(_MSC_VER) + +//----------------------------------------------------------------------------- + +void MurmurHash3_x86_32 ( const void * key, size_t len, uint32_t seed, void * out ); + +void MurmurHash3_x86_128 ( const void * key, size_t len, uint32_t seed, void * out ); + +void MurmurHash3_x64_128 ( const void * key, size_t len, uint32_t seed, void * out ); + +//----------------------------------------------------------------------------- + +#endif // _MURMURHASH3_H_ -- 2.30.2