From 4682c05d8ce192088e04fc2b96c767a47555774a Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 7 Jul 2017 09:41:42 -0400 Subject: [PATCH] use libmaa's xcalloc, dynamically link everything --- Makefile | 4 ++-- bfilter.c | 30 +++++++++++++++++++----------- bfilter.h | 2 ++ bfilter.py | 13 ------------- libfnv.so.0 | Bin 0 -> 53792 bytes 5 files changed, 23 insertions(+), 26 deletions(-) create mode 100755 libfnv.so.0 diff --git a/Makefile b/Makefile index d64d712..619033b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ default: bfilter.c bfilter.h - $(CC) -g -Wall -Wextra -std=gnu99 -Wpointer-arith -Wmissing-prototypes -lm -L. -O3 ./bfilter.c -o test --static `pkg-config --libs --cflags libfnv` -Wl,-rpath,/home/wes/bfilter; + $(CC) -g -Wall -Wextra -std=gnu99 -Wpointer-arith -Wmissing-prototypes -lmaa -lfnv -lm -L. -O0 ./bfilter.c -o test -Wl,-rpath,/home/wes/bfilter; lib: bfilter.c bfilter.h - $(CC) -g -DLIB -c -fpic -Wall -Wextra -pedantic -Wpointer-arith -Werror -std=c99 -lm -L. -O3 ./bfilter.c --static `pkg-config --libs --cflags libfnv` -Wl,-rpath,/home/wes/bfilter; + $(CC) -g -DLIB -c -fpic -Wall -Wextra -pedantic -Wpointer-arith -Werror -std=c99 -lmaa -lfnv -lm -L. -O0 ./bfilter.c -Wl,-rpath,/home/wes/bfilter; $(CC) -shared -o bfilter.so bfilter.o; diff --git a/bfilter.c b/bfilter.c index fab2f73..2e9fe44 100644 --- a/bfilter.c +++ b/bfilter.c @@ -2,6 +2,8 @@ #include #include #include +#include + #include "bfilter.h" int @@ -28,18 +30,14 @@ print_barray(bit_array_t *arr) { bit_array_t* empty_bfilter(int size) { int width = (size/32) + 1; // 32 for a 32 bit int - uint32_t *barray = malloc((sizeof (int)) * width); - - bit_array_t *result = malloc(sizeof (bit_array_t)); - result->num_ints = width; - result->num_elems = width*32; + uint32_t *barray = xcalloc(width, (sizeof (int))); - for(int i = 0; i < width; i++) { - barray[i] = 0; - } + bit_array_t *result = xcalloc(1, sizeof (bit_array_t)); result->arr = barray; + result->num_ints = width; + result->num_elems = width*32; return result; } @@ -134,13 +132,13 @@ hash(const char *input, uint32_t k, size_t m) { fnv_hashes_t fnv = hash_fnv(input); if (k <= 2) { - hashes_t hashes = malloc((sizeof (uint32_t)) * 2); + hashes_t hashes = xcalloc(2, (sizeof (uint32_t))); hashes[0] = fnv.hash_1 % m; hashes[1] = fnv.hash_2 % m; return hashes; } - hashes_t hashes = malloc((sizeof (uint32_t)) * k); + hashes_t hashes = xcalloc(k, (sizeof (uint32_t))); hashes[0] = fnv.hash_1 % m; hashes[1] = fnv.hash_2 % m; @@ -163,6 +161,7 @@ bfilter_set(bit_array_t *filter, for(int i = 0; i < k; i++) { setbit(filter, hashes[i]); } + free(hashes); return 0; } @@ -182,9 +181,17 @@ bfilter_get(bit_array_t *filter, exists = 0; } } + free(hashes); return exists; } +int +release_bfilter(bit_array_t *filter) { + free(filter->arr); + free(filter); + return 0; +} + #ifndef LIB int main (void) { @@ -213,6 +220,7 @@ main (void) { bfilter_set(test, test_string7, k); bfilter_set(test, test_string8, k); bfilter_set(test, test_string9, k); + bfilter_set(test, test_string10, k); bfilter_set(test, test_string11, k); printf("%d\n", bfilter_get(test, test_string7, k)); @@ -223,7 +231,7 @@ main (void) { printf("%d\n", bfilter_get(test, test_string10, k)); printf("%d\n", bfilter_get(test, test_string10, k)); - print_barray(test); + release_bfilter(test); return EXIT_SUCCESS; } diff --git a/bfilter.h b/bfilter.h index a353d95..76778bb 100644 --- a/bfilter.h +++ b/bfilter.h @@ -34,3 +34,5 @@ int bfilter_set(bit_array_t *, const char*, int); int bfilter_get(bit_array_t *, const char*, int); int getbit(bit_array_t *, int); + +int release_bfilter(bit_array_t *); diff --git a/bfilter.py b/bfilter.py index 96e0445..8ca0525 100755 --- a/bfilter.py +++ b/bfilter.py @@ -59,16 +59,3 @@ class BloomFilter: def __getitem__(self, key): return lib.bfilter_get(self.bitset, key.encode("UTF-8"), self.k) == 1 - - -with open("./roadnottaken") as rnt: - words = rnt.read().split(" ") - for word in words: - test.add(word) - - for word in words: - print(test[word]) - - print(test["wes"]) - -# lib.print_barray(bfilter) diff --git a/libfnv.so.0 b/libfnv.so.0 new file mode 100755 index 0000000000000000000000000000000000000000..e62477c11ce50a104f1eff1acb6d048932386ef0 GIT binary patch literal 53792 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