├── .gitignore ├── AUTHORS ├── COPYING ├── Makefile.am ├── NEWS ├── README ├── autogen.sh ├── benchmark ├── Makefile.am ├── fnv.c └── rand.c ├── check.mk ├── configure.ac ├── coverage └── Makefile.am ├── m4 └── ax_create_stdint_h.m4 ├── snippets ├── Makefile.am ├── bloomfilter.c ├── bloomfilter.h ├── fnv.c ├── fnv.h ├── linkedlist.c ├── linkedlist.h ├── mt19937.c ├── rand.c ├── rand.h ├── skiplist.c ├── skiplist.h └── utils.h └── tests ├── Makefile.am ├── bloomfilter.c ├── fnv.c ├── linkedlist.c ├── rand.c └── skiplist.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.gcda 2 | *.gcno 3 | *.o 4 | *.la 5 | *.lo 6 | *.swp 7 | *~ 8 | Makefile.in 9 | Makefile 10 | ChangeLog 11 | INSTALL 12 | aclocal.m4 13 | compile 14 | config.guess 15 | config.h 16 | config.h.in 17 | config.log 18 | config.status 19 | config.sub 20 | configure 21 | depcomp 22 | install-sh 23 | libtool 24 | ltmain.sh 25 | missing 26 | stamp-h1 27 | autom4te.cache 28 | .deps 29 | .libs 30 | m4/libtool.m4 31 | m4/ltoptions.m4 32 | m4/ltsugar.m4 33 | m4/ltversion.m4 34 | m4/lt~obsolete.m4 35 | coverage/*.coverage 36 | coverage/report 37 | tests/test-* 38 | snippets/snippets-stdint.h 39 | benchmark/fnv 40 | benchmark/rand 41 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Sebastian Dröge 2 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | 3 | if HAVE_CHECK 4 | tests_dir = tests 5 | else 6 | tests_dir = 7 | endif 8 | 9 | SUBDIRS = snippets $(tests_dir) benchmark coverage 10 | DIST_SUBDIRS = snippets tests benchmark coverage 11 | 12 | clean-local: 13 | -find $(top_builddir) -name *.gcda | xargs rm 14 | -find $(top_builddir) -name *.gcno | xargs rm 15 | 16 | check-valgrind: 17 | $(MAKE) -C tests check-valgrind 18 | 19 | if ENABLE_COVERAGE 20 | coverage: clean all check 21 | $(MAKE) -C coverage coverage 22 | endif 23 | 24 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdroege/snippets/b760be3ef9c57e7a8a03fd73bb90666169cc3f39/NEWS -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This library contains some algorithms and data structures that I've 2 | developed for my own usage, because no free alternative with the 3 | required features was available or had too many dependencies on 4 | third party libraries. 5 | 6 | Everything in this library is implemented in plain, portable C 7 | and has no external dependencies. It can be used in other software 8 | under the terms of the GNU Lesser General Public License version 3 9 | or any newer version. 10 | 11 | * Algorithms: 12 | + Fowler–Noll–Vo hash function in 32, 64, 128, 256, 512 and 13 | 1024 bit variants. 14 | + Pseudo random number generator for uniformly distributed 15 | 32 bit integers and doubles in arbitrary ranges. Uses 16 | the MT19937 mersenne prime twister. 17 | 18 | * Data structures: 19 | + (Double) Linked list 20 | - O(1) append/prepend 21 | - Pointer storage or data storage with single allocation 22 | - Memory managment 23 | + Skip list 24 | - Configurable maximum node level and level probability 25 | - Iteratable in both directions 26 | + Bloom filter 27 | - Uses enhanced double hashing 28 | - Arbitrary number of hash functions 29 | - Arbitrary filter size 30 | 31 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | srcdir=`dirname $0` 4 | test -z "$srcdir" && srcdir=. 5 | 6 | ORIGDIR=`pwd` 7 | cd $srcdir 8 | 9 | # Automake requires that ChangeLog exist. 10 | touch ChangeLog 11 | mkdir -p m4 12 | 13 | autoreconf -v --install || exit 1 14 | cd $ORIGDIR || exit $? 15 | 16 | $srcdir/configure --enable-maintainer-mode --enable-more-warnings --enable-warnings-as-errors "$@" 17 | -------------------------------------------------------------------------------- /benchmark/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_PROGRAMS = \ 2 | fnv \ 3 | rand 4 | 5 | fnv_SOURCES = fnv.c 6 | fnv_CFLAGS = -I$(top_srcdir) -I$(top_builddir) 7 | fnv_LDADD = $(top_builddir)/snippets/libsnippets.la $(LIBM) 8 | 9 | rand_SOURCES = rand.c 10 | rand_CFLAGS = -I$(top_srcdir) -I$(top_builddir) 11 | rand_LDADD = $(top_builddir)/snippets/libsnippets.la $(LIBM) 12 | -------------------------------------------------------------------------------- /benchmark/fnv.c: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifdef HAVE_CONFIG_H 21 | #include "config.h" 22 | #endif 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | static uint8_t test_data[8096]; 30 | 31 | typedef void (*fnv_func) (const uint8_t * data, size_t len, uint8_t * hash); 32 | 33 | static uint64_t 34 | run (fnv_func func, int runs) 35 | { 36 | struct timeval tv_start, tv_end; 37 | uint64_t start, end; 38 | int i; 39 | uint8_t hash[128]; 40 | 41 | gettimeofday (&tv_start, NULL); 42 | for (i = 0; i < runs; i++) 43 | func (test_data, sizeof (test_data), hash); 44 | gettimeofday (&tv_end, NULL); 45 | 46 | start = tv_start.tv_sec * 1000000 + tv_start.tv_usec; 47 | end = tv_end.tv_sec * 1000000 + tv_end.tv_usec; 48 | 49 | return end - start; 50 | } 51 | 52 | #define RUN(func, runs) do { \ 53 | uint64_t _duration; \ 54 | _duration = run (func, runs); \ 55 | printf (#func ":\t%04lu.%06lus for " #runs " runs (%lf kb/s)\n", _duration / 1000000, _duration % 1000000, (((double)runs) * sizeof (test_data) * 1000.0) / ((double)_duration)); \ 56 | } while (0); 57 | 58 | int 59 | main (int argc, char **argv) 60 | { 61 | int i; 62 | 63 | for (i = 0; i < sizeof (test_data); i++) 64 | test_data[i] = i & 0xff; 65 | 66 | RUN (snippets_fnv1_32, 100000); 67 | RUN (snippets_fnv1a_32, 100000); 68 | 69 | RUN (snippets_fnv1_64, 100000); 70 | RUN (snippets_fnv1a_64, 100000); 71 | 72 | RUN (snippets_fnv1_128, 100000); 73 | RUN (snippets_fnv1a_128, 100000); 74 | 75 | RUN (snippets_fnv1_256, 100000); 76 | RUN (snippets_fnv1a_256, 100000); 77 | 78 | RUN (snippets_fnv1_512, 100000); 79 | RUN (snippets_fnv1a_512, 100000); 80 | 81 | RUN (snippets_fnv1_1024, 100000); 82 | RUN (snippets_fnv1a_1024, 100000); 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /benchmark/rand.c: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifdef HAVE_CONFIG_H 21 | #include "config.h" 22 | #endif 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #define NRUNS 250000000 31 | 32 | #define RUN(func, name) do { \ 33 | uint64_t start, end, duration; \ 34 | struct timeval tv_start, tv_end; \ 35 | \ 36 | gettimeofday (&tv_start, NULL); \ 37 | func(); \ 38 | gettimeofday (&tv_end, NULL); \ 39 | \ 40 | start = tv_start.tv_sec * 1000000 + tv_start.tv_usec; \ 41 | end = tv_end.tv_sec * 1000000 + tv_end.tv_usec; \ 42 | \ 43 | duration = end - start; \ 44 | printf (name ":\t%04lu.%06lus for %d runs\n", duration / 1000000, duration % 1000000, NRUNS); \ 45 | } while (0); 46 | 47 | static void 48 | mt19937_uint32 (void) 49 | { 50 | SnippetsRand *rand = snippets_rand_new (time (0)); 51 | unsigned int i; 52 | 53 | for (i = 0; i < NRUNS; i++) 54 | snippets_rand_uint32 (rand); 55 | 56 | snippets_rand_free (rand); 57 | } 58 | 59 | static void 60 | mt19937_uint32_range (void) 61 | { 62 | SnippetsRand *rand = snippets_rand_new (time (0)); 63 | unsigned int i; 64 | 65 | for (i = 0; i < NRUNS; i++) 66 | snippets_rand_uint32_range (rand, 100, 1000); 67 | 68 | snippets_rand_free (rand); 69 | } 70 | 71 | static void 72 | mt19937_double (void) 73 | { 74 | SnippetsRand *rand = snippets_rand_new (time (0)); 75 | unsigned int i; 76 | 77 | for (i = 0; i < NRUNS; i++) 78 | snippets_rand_double (rand); 79 | 80 | snippets_rand_free (rand); 81 | } 82 | 83 | static void 84 | mt19937_double_range (void) 85 | { 86 | SnippetsRand *rand = snippets_rand_new (time (0)); 87 | unsigned int i; 88 | 89 | for (i = 0; i < NRUNS; i++) 90 | snippets_rand_double_range (rand, 100, 1000); 91 | 92 | snippets_rand_free (rand); 93 | } 94 | 95 | int 96 | main (int argc, char **argv) 97 | { 98 | RUN (mt19937_uint32, "MT19937 uint32 "); 99 | RUN (mt19937_uint32_range, "MT19937 uint32 range "); 100 | RUN (mt19937_double, "MT19937 double "); 101 | RUN (mt19937_double_range, "MT19937 double range "); 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /check.mk: -------------------------------------------------------------------------------- 1 | %.check: % 2 | ./$* 3 | 4 | if HAVE_GDB 5 | %.gdb: % 6 | $(LIBTOOL) --mode=execute \ 7 | $(GDB) $* 8 | endif 9 | 10 | if HAVE_VALGRIND 11 | 12 | if HAVE_VALGRIND_3_4_0 13 | VALGRIND_TRACK_ORIGINS=--track-origins=yes 14 | else 15 | VALGRIND_TRACK_ORIGINS= 16 | endif 17 | 18 | %.valgrind: % 19 | $(LIBTOOL) --mode=execute \ 20 | $(VALGRIND) -q \ 21 | $(foreach s,$(SUPPRESSIONS),--suppressions=$(s)) \ 22 | --tool=memcheck \ 23 | --leak-check=full \ 24 | $(VALGRIND_TRACK_ORIGINS) \ 25 | --leak-resolution=high \ 26 | ./$* 2>&1 | tee valgrind.log 27 | @if $(EGREP) '==[0-9]+==' valgrind.log > /dev/null 2>&1; then \ 28 | rm valgrind.log; \ 29 | exit 1; \ 30 | fi 31 | @rm valgrind.log 32 | 33 | %.valgrind.gen-suppressions: % 34 | $(LIBTOOL) --mode=execute \ 35 | $(VALGRIND) -q \ 36 | $(foreach s,$(SUPPRESSIONS),--suppressions=$(s)) \ 37 | --tool=memcheck \ 38 | --leak-check=full \ 39 | $(VALGRIND_TRACK_ORIGINS) \ 40 | --gen-suppressions=all \ 41 | --leak-resolution=high \ 42 | ./$* 2>&1 | tee valgrind.log 43 | @if $(EGREP) '==[0-9]+==' valgrind.log > /dev/null 2>&1; then \ 44 | rm valgrind.log; \ 45 | exit 1; \ 46 | fi 47 | @rm valgrind.log 48 | 49 | check-valgrind: $(TESTS) 50 | @failed=0; \ 51 | for test in $(TESTS); do \ 52 | $(MAKE) $$test.valgrind; \ 53 | if test "$$?" -ne 0; then \ 54 | echo "Valgrind error for test $$test"; \ 55 | failed=`expr $$failed + 1`; \ 56 | whicht="$$whicht $$test"; \ 57 | fi; \ 58 | done; \ 59 | if test "$$failed" -ne 0; then \ 60 | echo "$$failed tests had leaks or errors under valgrind:"; \ 61 | echo "$$whicht"; \ 62 | false; \ 63 | fi 64 | endif 65 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([snippets], [0.0.1]) 2 | AC_CONFIG_SRCDIR([Makefile.am]) 3 | AC_CONFIG_MACRO_DIR([m4]) 4 | AC_CONFIG_HEADERS(config.h) 5 | 6 | AM_INIT_AUTOMAKE([dist-bzip2 -Wno-portability]) 7 | AM_MAINTAINER_MODE 8 | 9 | LT_INIT([pic-only]) 10 | 11 | m4_ifdef([AM_SILENT_RULES], 12 | [AM_SILENT_RULES([yes])], 13 | [ 14 | AM_DEFAULT_VERBOSITY=1 15 | AC_SUBST(AM_DEFAULT_VERBOSITY) 16 | ] 17 | ) 18 | 19 | AC_PROG_CC 20 | AC_PROG_CC_STDC 21 | AC_PROG_CPP 22 | AC_PROG_GREP 23 | AC_PROG_INSTALL 24 | AM_PROG_CC_C_O 25 | 26 | AC_HEADER_STDC 27 | AC_C_CONST 28 | AC_C_INLINE 29 | AC_ISC_POSIX 30 | AC_SYS_LARGEFILE 31 | 32 | AC_C_BIGENDIAN 33 | 34 | AC_CHECK_LIBM 35 | AC_SUBST(LIBM) 36 | 37 | # set libtool versioning 38 | # +1 : 0 : +1 == new interface that does not break old one. 39 | # +1 : 0 : 0 == changed/removed an interface. Breaks old apps. 40 | # ? : +1 : ? == internal changes that doesn't break anything. 41 | # CURRENT : REVISION : AGE 42 | LT_CURRENT=0 43 | LT_REVISION=0 44 | LT_AGE=0 45 | 46 | AC_SUBST(LT_CURRENT) 47 | AC_SUBST(LT_REVISION) 48 | AC_SUBST(LT_AGE) 49 | 50 | AX_CREATE_STDINT_H([snippets/snippets-stdint.h]) 51 | 52 | PKG_PROG_PKG_CONFIG 53 | 54 | PKG_CHECK_MODULES(CHECK, check, have_check="yes", have_check="no") 55 | AC_SUBST(CHECK_CFLAGS) 56 | AC_SUBST(CHECK_LIBS) 57 | AM_CONDITIONAL(HAVE_CHECK, test "x$have_check" != "xno") 58 | 59 | AC_PATH_PROG(VALGRIND, valgrind, no) 60 | AM_CONDITIONAL(HAVE_VALGRIND, test "x$VALGRIND" != "xno") 61 | 62 | have_valgrind_3_4_0=no 63 | if test "x$VALGRIND" != "xno"; then 64 | valgrind_version=0 65 | valgrind_version="`$VALGRIND --version | head -n 1 | sed 's/^[[^0-9]]*//' | sed 's/[[^0-9]]*$//' | cut -d' ' -f1`" 66 | AC_MSG_CHECKING([for valgrind version $valgrind_version >= 3.4.0]) 67 | if perl -we "exit ((v$valgrind_version ge v3.4.0) ? 0 : 1)"; then 68 | have_valgrind_3_4_0=yes 69 | AC_MSG_RESULT([yes]) 70 | else 71 | AC_MSG_RESULT([no]) 72 | fi 73 | fi 74 | AM_CONDITIONAL(HAVE_VALGRIND_3_4_0, test "x$have_valgrind_3_4_0" = "xyes") 75 | 76 | AC_PATH_PROG(GDB, gdb, no) 77 | AM_CONDITIONAL(HAVE_GDB, test ! "x$GDB" = "xno") 78 | 79 | AC_ARG_ENABLE([coverage], 80 | AS_HELP_STRING([--enable-coverage], 81 | [enable code coverage output (default=no)])], 82 | [], 83 | [enable_coverage=no]) 84 | 85 | if test "x$enable_coverage" = "xyes"; then 86 | if test "x$enable_shared" != "xno"; then 87 | AC_MSG_ERROR([--disable-shared is required for coverage reporting]) 88 | fi 89 | 90 | AC_PATH_PROG(LCOV, lcov, no) 91 | AC_PATH_PROG(GENHTML, genhtml, no) 92 | 93 | if test "x$LCOV" != "xno" -a "x$GENHTML" != "xno"; then 94 | CFLAGS="$CFLAGS -O0 -g -fprofile-arcs -ftest-coverage" 95 | LDFLAGS="$LDFLAGS -fprofile-arcs" 96 | else 97 | AC_MSG_ERROR([lcov is required to build coverage information]) 98 | fi 99 | fi 100 | AM_CONDITIONAL(ENABLE_COVERAGE, test "x$enable_coverage" != "xno") 101 | 102 | CFLAGS="$CFLAGS -Wall" 103 | 104 | AC_ARG_ENABLE(more-warnings, 105 | AC_HELP_STRING([--enable-more-warnings], [Enable more compiler warnings]), 106 | set_more_warnings="$enableval", set_more_warnings=no) 107 | 108 | AC_MSG_CHECKING(for more warnings) 109 | if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then 110 | AC_MSG_RESULT(yes) 111 | 112 | for option in -Wchar-subscripts -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wcast-align -Wredundant-decls -Wundef -Wwrite-strings -Wformat-nonliteral -Wformat-security -Wold-style-definition -Winit-self -Wmissing-include-dirs -Waddress -Waggregate-return -Wno-multichar; do 113 | SAVE_CFLAGS="$CFLAGS" 114 | CFLAGS="$CFLAGS $option" 115 | AC_MSG_CHECKING([whether gcc understands $option]) 116 | AC_TRY_COMPILE([], [], 117 | has_option=yes, 118 | has_option=no,) 119 | if test $has_option = no; then 120 | CFLAGS="$SAVE_CFLAGS" 121 | fi 122 | AC_MSG_RESULT($has_option) 123 | unset has_option 124 | unset SAVE_CFLAGS 125 | done 126 | unset option 127 | else 128 | AC_MSG_RESULT(no) 129 | fi 130 | 131 | AC_ARG_ENABLE(warnings-as-errors, 132 | AC_HELP_STRING([--enable-warnings-as-errors], [Handle compiler warnings as errors]), 133 | set_werror="$enableval", set_werror=no) 134 | 135 | AC_MSG_CHECKING(for handling compiler warnings as errors) 136 | if test "$GCC" = "yes" -a "$set_werror" != "no"; then 137 | AC_MSG_RESULT(yes) 138 | CFLAGS="$CFLAGS -Werror" 139 | else 140 | AC_MSG_RESULT(no) 141 | fi 142 | 143 | AC_CONFIG_FILES([ 144 | Makefile 145 | snippets/Makefile 146 | tests/Makefile 147 | benchmark/Makefile 148 | coverage/Makefile 149 | ]) 150 | 151 | AC_OUTPUT 152 | -------------------------------------------------------------------------------- /coverage/Makefile.am: -------------------------------------------------------------------------------- 1 | coverage: 2 | $(LCOV) -d $(top_builddir) -c -o full.coverage 3 | $(LCOV) -e full.coverage *snippets/* -o snippets.coverage 4 | $(GENHTML) --show-details -t "Tests Coverage" --legend snippets.coverage -o report 5 | 6 | clean-local: 7 | rm -rf report 8 | 9 | CLEANFILES = \ 10 | *.coverage 11 | 12 | -------------------------------------------------------------------------------- /m4/ax_create_stdint_h.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.nongnu.org/autoconf-archive/ax_create_stdint_h.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CREATE_STDINT_H [( HEADER-TO-GENERATE [, HEDERS-TO-CHECK])] 8 | # 9 | # DESCRIPTION 10 | # 11 | # the "ISO C9X: 7.18 Integer types " section requires the 12 | # existence of an include file that defines a set of typedefs, 13 | # especially uint8_t,int32_t,uintptr_t. Many older installations will not 14 | # provide this file, but some will have the very same definitions in 15 | # . In other enviroments we can use the inet-types in 16 | # which would define the typedefs int8_t and u_int8_t 17 | # respectivly. 18 | # 19 | # This macros will create a local "_stdint.h" or the headerfile given as 20 | # an argument. In many cases that file will just "#include " or 21 | # "#include ", while in other environments it will provide the 22 | # set of basic 'stdint's definitions/typedefs: 23 | # 24 | # int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,intptr_t,uintptr_t 25 | # int_least32_t.. int_fast32_t.. intmax_t 26 | # 27 | # which may or may not rely on the definitions of other files, or using 28 | # the AC_CHECK_SIZEOF macro to determine the actual sizeof each type. 29 | # 30 | # if your header files require the stdint-types you will want to create an 31 | # installable file mylib-int.h that all your other installable header may 32 | # include. So if you have a library package named "mylib", just use 33 | # 34 | # AX_CREATE_STDINT_H(mylib-int.h) 35 | # 36 | # in configure.ac and go to install that very header file in Makefile.am 37 | # along with the other headers (mylib.h) - and the mylib-specific headers 38 | # can simply use "#include " to obtain the stdint-types. 39 | # 40 | # Remember, if the system already had a valid , the generated 41 | # file will include it directly. No need for fuzzy HAVE_STDINT_H things... 42 | # (oops, GCC 4.2.x has deliberatly disabled its stdint.h for non-c99 43 | # compilation and the c99-mode is not the default. Therefore this macro 44 | # will not use the compiler's stdint.h - please complain to the GCC 45 | # developers). 46 | # 47 | # LICENSE 48 | # 49 | # Copyright (c) 2008 Guido U. Draheim 50 | # 51 | # This program is free software; you can redistribute it and/or modify it 52 | # under the terms of the GNU General Public License as published by the 53 | # Free Software Foundation; either version 2 of the License, or (at your 54 | # option) any later version. 55 | # 56 | # This program is distributed in the hope that it will be useful, but 57 | # WITHOUT ANY WARRANTY; without even the implied warranty of 58 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 59 | # Public License for more details. 60 | # 61 | # You should have received a copy of the GNU General Public License along 62 | # with this program. If not, see . 63 | # 64 | # As a special exception, the respective Autoconf Macro's copyright owner 65 | # gives unlimited permission to copy, distribute and modify the configure 66 | # scripts that are the output of Autoconf when processing the Macro. You 67 | # need not follow the terms of the GNU General Public License when using 68 | # or distributing such scripts, even though portions of the text of the 69 | # Macro appear in them. The GNU General Public License (GPL) does govern 70 | # all other use of the material that constitutes the Autoconf Macro. 71 | # 72 | # This special exception to the GPL applies to versions of the Autoconf 73 | # Macro released by the Autoconf Archive. When you make and distribute a 74 | # modified version of the Autoconf Macro, you may extend this special 75 | # exception to the GPL to apply to your modified version as well. 76 | 77 | AC_DEFUN([AX_CHECK_DATA_MODEL],[ 78 | AC_CHECK_SIZEOF(char) 79 | AC_CHECK_SIZEOF(short) 80 | AC_CHECK_SIZEOF(int) 81 | AC_CHECK_SIZEOF(long) 82 | AC_CHECK_SIZEOF(void*) 83 | ac_cv_char_data_model="" 84 | ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char" 85 | ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short" 86 | ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int" 87 | ac_cv_long_data_model="" 88 | ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int" 89 | ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long" 90 | ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp" 91 | AC_MSG_CHECKING([data model]) 92 | case "$ac_cv_char_data_model/$ac_cv_long_data_model" in 93 | 122/242) ac_cv_data_model="IP16" ; n="standard 16bit machine" ;; 94 | 122/244) ac_cv_data_model="LP32" ; n="standard 32bit machine" ;; 95 | 122/*) ac_cv_data_model="i16" ; n="unusual int16 model" ;; 96 | 124/444) ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;; 97 | 124/488) ac_cv_data_model="LP64" ; n="standard 64bit unixish" ;; 98 | 124/448) ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;; 99 | 124/*) ac_cv_data_model="i32" ; n="unusual int32 model" ;; 100 | 128/888) ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;; 101 | 128/*) ac_cv_data_model="i64" ; n="unusual int64 model" ;; 102 | 222/*2) ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;; 103 | 333/*3) ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;; 104 | 444/*4) ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;; 105 | 666/*6) ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;; 106 | 888/*8) ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;; 107 | 222/*|333/*|444/*|666/*|888/*) : 108 | ac_cv_data_model="iDSP" ; n="unusual dsptype" ;; 109 | *) ac_cv_data_model="none" ; n="very unusual model" ;; 110 | esac 111 | AC_MSG_RESULT([$ac_cv_data_model ($ac_cv_long_data_model, $n)]) 112 | ]) 113 | 114 | dnl AX_CHECK_HEADER_STDINT_X([HEADERLIST][,ACTION-IF]) 115 | AC_DEFUN([AX_CHECK_HEADER_STDINT_X],[ 116 | AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[ 117 | ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h) 118 | AC_MSG_RESULT([(..)]) 119 | for i in m4_ifval([$1],[$1],[stdint.h inttypes.h sys/inttypes.h sys/types.h]) 120 | do 121 | unset ac_cv_type_uintptr_t 122 | unset ac_cv_type_uint64_t 123 | AC_CHECK_TYPE(uintptr_t,[ac_cv_header_stdint_x=$i],continue,[#include <$i>]) 124 | AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>]) 125 | m4_ifvaln([$2],[$2]) break 126 | done 127 | AC_MSG_CHECKING([for stdint uintptr_t]) 128 | ]) 129 | ]) 130 | 131 | AC_DEFUN([AX_CHECK_HEADER_STDINT_O],[ 132 | AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[ 133 | ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h) 134 | AC_MSG_RESULT([(..)]) 135 | for i in m4_ifval([$1],[$1],[inttypes.h sys/inttypes.h sys/types.h stdint.h]) 136 | do 137 | unset ac_cv_type_uint32_t 138 | unset ac_cv_type_uint64_t 139 | AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],continue,[#include <$i>]) 140 | AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>]) 141 | m4_ifvaln([$2],[$2]) break 142 | break; 143 | done 144 | AC_MSG_CHECKING([for stdint uint32_t]) 145 | ]) 146 | ]) 147 | 148 | AC_DEFUN([AX_CHECK_HEADER_STDINT_U],[ 149 | AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[ 150 | ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h) 151 | AC_MSG_RESULT([(..)]) 152 | for i in m4_ifval([$1],[$1],[sys/types.h inttypes.h sys/inttypes.h]) ; do 153 | unset ac_cv_type_u_int32_t 154 | unset ac_cv_type_u_int64_t 155 | AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],continue,[#include <$i>]) 156 | AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>]) 157 | m4_ifvaln([$2],[$2]) break 158 | break; 159 | done 160 | AC_MSG_CHECKING([for stdint u_int32_t]) 161 | ]) 162 | ]) 163 | 164 | AC_DEFUN([AX_CREATE_STDINT_H], 165 | [# ------ AX CREATE STDINT H ------------------------------------- 166 | AC_MSG_CHECKING([for stdint types]) 167 | ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)` 168 | # try to shortcircuit - if the default include path of the compiler 169 | # can find a "stdint.h" header then we assume that all compilers can. 170 | AC_CACHE_VAL([ac_cv_header_stdint_t],[ 171 | old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS="" 172 | old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS="" 173 | old_CFLAGS="$CFLAGS" ; CFLAGS="" 174 | AC_TRY_COMPILE([#include ],[int_least32_t v = 0;], 175 | [ac_cv_stdint_result="(assuming C99 compatible system)" 176 | ac_cv_header_stdint_t="stdint.h"; ], 177 | [ac_cv_header_stdint_t=""]) 178 | if test "$GCC" = "yes" && test ".$ac_cv_header_stdint_t" = "."; then 179 | CFLAGS="-std=c99" 180 | AC_TRY_COMPILE([#include ],[int_least32_t v = 0;], 181 | [AC_MSG_WARN(your GCC compiler has a defunct stdint.h for its default-mode)]) 182 | fi 183 | CXXFLAGS="$old_CXXFLAGS" 184 | CPPFLAGS="$old_CPPFLAGS" 185 | CFLAGS="$old_CFLAGS" ]) 186 | 187 | v="... $ac_cv_header_stdint_h" 188 | if test "$ac_stdint_h" = "stdint.h" ; then 189 | AC_MSG_RESULT([(are you sure you want them in ./stdint.h?)]) 190 | elif test "$ac_stdint_h" = "inttypes.h" ; then 191 | AC_MSG_RESULT([(are you sure you want them in ./inttypes.h?)]) 192 | elif test "_$ac_cv_header_stdint_t" = "_" ; then 193 | AC_MSG_RESULT([(putting them into $ac_stdint_h)$v]) 194 | else 195 | ac_cv_header_stdint="$ac_cv_header_stdint_t" 196 | AC_MSG_RESULT([$ac_cv_header_stdint (shortcircuit)]) 197 | fi 198 | 199 | if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit.. 200 | 201 | dnl .....intro message done, now do a few system checks..... 202 | dnl btw, all old CHECK_TYPE macros do automatically "DEFINE" a type, 203 | dnl therefore we use the autoconf implementation detail CHECK_TYPE_NEW 204 | dnl instead that is triggered with 3 or more arguments (see types.m4) 205 | 206 | inttype_headers=`echo $2 | sed -e 's/,/ /g'` 207 | 208 | ac_cv_stdint_result="(no helpful system typedefs seen)" 209 | AX_CHECK_HEADER_STDINT_X(dnl 210 | stdint.h inttypes.h sys/inttypes.h $inttype_headers, 211 | ac_cv_stdint_result="(seen uintptr_t$and64 in $i)") 212 | 213 | if test "_$ac_cv_header_stdint_x" = "_" ; then 214 | AX_CHECK_HEADER_STDINT_O(dnl, 215 | inttypes.h sys/inttypes.h stdint.h $inttype_headers, 216 | ac_cv_stdint_result="(seen uint32_t$and64 in $i)") 217 | fi 218 | 219 | if test "_$ac_cv_header_stdint_x" = "_" ; then 220 | if test "_$ac_cv_header_stdint_o" = "_" ; then 221 | AX_CHECK_HEADER_STDINT_U(dnl, 222 | sys/types.h inttypes.h sys/inttypes.h $inttype_headers, 223 | ac_cv_stdint_result="(seen u_int32_t$and64 in $i)") 224 | fi fi 225 | 226 | dnl if there was no good C99 header file, do some typedef checks... 227 | if test "_$ac_cv_header_stdint_x" = "_" ; then 228 | AC_MSG_CHECKING([for stdint datatype model]) 229 | AC_MSG_RESULT([(..)]) 230 | AX_CHECK_DATA_MODEL 231 | fi 232 | 233 | if test "_$ac_cv_header_stdint_x" != "_" ; then 234 | ac_cv_header_stdint="$ac_cv_header_stdint_x" 235 | elif test "_$ac_cv_header_stdint_o" != "_" ; then 236 | ac_cv_header_stdint="$ac_cv_header_stdint_o" 237 | elif test "_$ac_cv_header_stdint_u" != "_" ; then 238 | ac_cv_header_stdint="$ac_cv_header_stdint_u" 239 | else 240 | ac_cv_header_stdint="stddef.h" 241 | fi 242 | 243 | AC_MSG_CHECKING([for extra inttypes in chosen header]) 244 | AC_MSG_RESULT([($ac_cv_header_stdint)]) 245 | dnl see if int_least and int_fast types are present in _this_ header. 246 | unset ac_cv_type_int_least32_t 247 | unset ac_cv_type_int_fast32_t 248 | AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>]) 249 | AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>]) 250 | AC_CHECK_TYPE(intmax_t,,,[#include <$ac_cv_header_stdint>]) 251 | 252 | fi # shortcircut to system "stdint.h" 253 | # ------------------ PREPARE VARIABLES ------------------------------ 254 | if test "$GCC" = "yes" ; then 255 | ac_cv_stdint_message="using gnu compiler "`$CC --version | head -1` 256 | else 257 | ac_cv_stdint_message="using $CC" 258 | fi 259 | 260 | AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl 261 | $ac_cv_stdint_result]) 262 | 263 | dnl ----------------------------------------------------------------- 264 | # ----------------- DONE inttypes.h checks START header ------------- 265 | AC_CONFIG_COMMANDS([$ac_stdint_h],[ 266 | AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h) 267 | ac_stdint=$tmp/_stdint.h 268 | 269 | echo "#ifndef" $_ac_stdint_h >$ac_stdint 270 | echo "#define" $_ac_stdint_h "1" >>$ac_stdint 271 | echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint 272 | echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint 273 | echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint 274 | if test "_$ac_cv_header_stdint_t" != "_" ; then 275 | echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint 276 | echo "#include " >>$ac_stdint 277 | echo "#endif" >>$ac_stdint 278 | echo "#endif" >>$ac_stdint 279 | else 280 | 281 | cat >>$ac_stdint < 287 | #else 288 | #include 289 | 290 | /* .................... configured part ............................ */ 291 | 292 | STDINT_EOF 293 | 294 | echo "/* whether we have a C99 compatible stdint header file */" >>$ac_stdint 295 | if test "_$ac_cv_header_stdint_x" != "_" ; then 296 | ac_header="$ac_cv_header_stdint_x" 297 | echo "#define _STDINT_HEADER_INTPTR" '"'"$ac_header"'"' >>$ac_stdint 298 | else 299 | echo "/* #undef _STDINT_HEADER_INTPTR */" >>$ac_stdint 300 | fi 301 | 302 | echo "/* whether we have a C96 compatible inttypes header file */" >>$ac_stdint 303 | if test "_$ac_cv_header_stdint_o" != "_" ; then 304 | ac_header="$ac_cv_header_stdint_o" 305 | echo "#define _STDINT_HEADER_UINT32" '"'"$ac_header"'"' >>$ac_stdint 306 | else 307 | echo "/* #undef _STDINT_HEADER_UINT32 */" >>$ac_stdint 308 | fi 309 | 310 | echo "/* whether we have a BSD compatible inet types header */" >>$ac_stdint 311 | if test "_$ac_cv_header_stdint_u" != "_" ; then 312 | ac_header="$ac_cv_header_stdint_u" 313 | echo "#define _STDINT_HEADER_U_INT32" '"'"$ac_header"'"' >>$ac_stdint 314 | else 315 | echo "/* #undef _STDINT_HEADER_U_INT32 */" >>$ac_stdint 316 | fi 317 | 318 | echo "" >>$ac_stdint 319 | 320 | if test "_$ac_header" != "_" ; then if test "$ac_header" != "stddef.h" ; then 321 | echo "#include <$ac_header>" >>$ac_stdint 322 | echo "" >>$ac_stdint 323 | fi fi 324 | 325 | echo "/* which 64bit typedef has been found */" >>$ac_stdint 326 | if test "$ac_cv_type_uint64_t" = "yes" ; then 327 | echo "#define _STDINT_HAVE_UINT64_T" "1" >>$ac_stdint 328 | else 329 | echo "/* #undef _STDINT_HAVE_UINT64_T */" >>$ac_stdint 330 | fi 331 | if test "$ac_cv_type_u_int64_t" = "yes" ; then 332 | echo "#define _STDINT_HAVE_U_INT64_T" "1" >>$ac_stdint 333 | else 334 | echo "/* #undef _STDINT_HAVE_U_INT64_T */" >>$ac_stdint 335 | fi 336 | echo "" >>$ac_stdint 337 | 338 | echo "/* which type model has been detected */" >>$ac_stdint 339 | if test "_$ac_cv_char_data_model" != "_" ; then 340 | echo "#define _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint 341 | echo "#define _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint 342 | else 343 | echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint 344 | echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint 345 | fi 346 | echo "" >>$ac_stdint 347 | 348 | echo "/* whether int_least types were detected */" >>$ac_stdint 349 | if test "$ac_cv_type_int_least32_t" = "yes"; then 350 | echo "#define _STDINT_HAVE_INT_LEAST32_T" "1" >>$ac_stdint 351 | else 352 | echo "/* #undef _STDINT_HAVE_INT_LEAST32_T */" >>$ac_stdint 353 | fi 354 | echo "/* whether int_fast types were detected */" >>$ac_stdint 355 | if test "$ac_cv_type_int_fast32_t" = "yes"; then 356 | echo "#define _STDINT_HAVE_INT_FAST32_T" "1" >>$ac_stdint 357 | else 358 | echo "/* #undef _STDINT_HAVE_INT_FAST32_T */" >>$ac_stdint 359 | fi 360 | echo "/* whether intmax_t type was detected */" >>$ac_stdint 361 | if test "$ac_cv_type_intmax_t" = "yes"; then 362 | echo "#define _STDINT_HAVE_INTMAX_T" "1" >>$ac_stdint 363 | else 364 | echo "/* #undef _STDINT_HAVE_INTMAX_T */" >>$ac_stdint 365 | fi 366 | echo "" >>$ac_stdint 367 | 368 | cat >>$ac_stdint <= 199901L 425 | #define _HAVE_UINT64_T 426 | #define _HAVE_LONGLONG_UINT64_T 427 | typedef long long int64_t; 428 | typedef unsigned long long uint64_t; 429 | 430 | #elif !defined __STRICT_ANSI__ 431 | #if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ 432 | #define _HAVE_UINT64_T 433 | typedef __int64 int64_t; 434 | typedef unsigned __int64 uint64_t; 435 | 436 | #elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__ 437 | /* note: all ELF-systems seem to have loff-support which needs 64-bit */ 438 | #if !defined _NO_LONGLONG 439 | #define _HAVE_UINT64_T 440 | #define _HAVE_LONGLONG_UINT64_T 441 | typedef long long int64_t; 442 | typedef unsigned long long uint64_t; 443 | #endif 444 | 445 | #elif defined __alpha || (defined __mips && defined _ABIN32) 446 | #if !defined _NO_LONGLONG 447 | typedef long int64_t; 448 | typedef unsigned long uint64_t; 449 | #endif 450 | /* compiler/cpu type to define int64_t */ 451 | #endif 452 | #endif 453 | #endif 454 | 455 | #if defined _STDINT_HAVE_U_INT_TYPES 456 | /* int8_t int16_t int32_t defined by inet code, redeclare the u_intXX types */ 457 | typedef u_int8_t uint8_t; 458 | typedef u_int16_t uint16_t; 459 | typedef u_int32_t uint32_t; 460 | 461 | /* glibc compatibility */ 462 | #ifndef __int8_t_defined 463 | #define __int8_t_defined 464 | #endif 465 | #endif 466 | 467 | #ifdef _STDINT_NEED_INT_MODEL_T 468 | /* we must guess all the basic types. Apart from byte-adressable system, */ 469 | /* there a few 32-bit-only dsp-systems that we guard with BYTE_MODEL 8-} */ 470 | /* (btw, those nibble-addressable systems are way off, or so we assume) */ 471 | 472 | dnl /* have a look at "64bit and data size neutrality" at */ 473 | dnl /* http://unix.org/version2/whatsnew/login_64bit.html */ 474 | dnl /* (the shorthand "ILP" types always have a "P" part) */ 475 | 476 | #if defined _STDINT_BYTE_MODEL 477 | #if _STDINT_LONG_MODEL+0 == 242 478 | /* 2:4:2 = IP16 = a normal 16-bit system */ 479 | typedef unsigned char uint8_t; 480 | typedef unsigned short uint16_t; 481 | typedef unsigned long uint32_t; 482 | #ifndef __int8_t_defined 483 | #define __int8_t_defined 484 | typedef char int8_t; 485 | typedef short int16_t; 486 | typedef long int32_t; 487 | #endif 488 | #elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL == 444 489 | /* 2:4:4 = LP32 = a 32-bit system derived from a 16-bit */ 490 | /* 4:4:4 = ILP32 = a normal 32-bit system */ 491 | typedef unsigned char uint8_t; 492 | typedef unsigned short uint16_t; 493 | typedef unsigned int uint32_t; 494 | #ifndef __int8_t_defined 495 | #define __int8_t_defined 496 | typedef char int8_t; 497 | typedef short int16_t; 498 | typedef int int32_t; 499 | #endif 500 | #elif _STDINT_LONG_MODEL+0 == 484 || _STDINT_LONG_MODEL+0 == 488 501 | /* 4:8:4 = IP32 = a 32-bit system prepared for 64-bit */ 502 | /* 4:8:8 = LP64 = a normal 64-bit system */ 503 | typedef unsigned char uint8_t; 504 | typedef unsigned short uint16_t; 505 | typedef unsigned int uint32_t; 506 | #ifndef __int8_t_defined 507 | #define __int8_t_defined 508 | typedef char int8_t; 509 | typedef short int16_t; 510 | typedef int int32_t; 511 | #endif 512 | /* this system has a "long" of 64bit */ 513 | #ifndef _HAVE_UINT64_T 514 | #define _HAVE_UINT64_T 515 | typedef unsigned long uint64_t; 516 | typedef long int64_t; 517 | #endif 518 | #elif _STDINT_LONG_MODEL+0 == 448 519 | /* LLP64 a 64-bit system derived from a 32-bit system */ 520 | typedef unsigned char uint8_t; 521 | typedef unsigned short uint16_t; 522 | typedef unsigned int uint32_t; 523 | #ifndef __int8_t_defined 524 | #define __int8_t_defined 525 | typedef char int8_t; 526 | typedef short int16_t; 527 | typedef int int32_t; 528 | #endif 529 | /* assuming the system has a "long long" */ 530 | #ifndef _HAVE_UINT64_T 531 | #define _HAVE_UINT64_T 532 | #define _HAVE_LONGLONG_UINT64_T 533 | typedef unsigned long long uint64_t; 534 | typedef long long int64_t; 535 | #endif 536 | #else 537 | #define _STDINT_NO_INT32_T 538 | #endif 539 | #else 540 | #define _STDINT_NO_INT8_T 541 | #define _STDINT_NO_INT32_T 542 | #endif 543 | #endif 544 | 545 | /* 546 | * quote from SunOS-5.8 sys/inttypes.h: 547 | * Use at your own risk. As of February 1996, the committee is squarely 548 | * behind the fixed sized types; the "least" and "fast" types are still being 549 | * discussed. The probability that the "fast" types may be removed before 550 | * the standard is finalized is high enough that they are not currently 551 | * implemented. 552 | */ 553 | 554 | #if defined _STDINT_NEED_INT_LEAST_T 555 | typedef int8_t int_least8_t; 556 | typedef int16_t int_least16_t; 557 | typedef int32_t int_least32_t; 558 | #ifdef _HAVE_UINT64_T 559 | typedef int64_t int_least64_t; 560 | #endif 561 | 562 | typedef uint8_t uint_least8_t; 563 | typedef uint16_t uint_least16_t; 564 | typedef uint32_t uint_least32_t; 565 | #ifdef _HAVE_UINT64_T 566 | typedef uint64_t uint_least64_t; 567 | #endif 568 | /* least types */ 569 | #endif 570 | 571 | #if defined _STDINT_NEED_INT_FAST_T 572 | typedef int8_t int_fast8_t; 573 | typedef int int_fast16_t; 574 | typedef int32_t int_fast32_t; 575 | #ifdef _HAVE_UINT64_T 576 | typedef int64_t int_fast64_t; 577 | #endif 578 | 579 | typedef uint8_t uint_fast8_t; 580 | typedef unsigned uint_fast16_t; 581 | typedef uint32_t uint_fast32_t; 582 | #ifdef _HAVE_UINT64_T 583 | typedef uint64_t uint_fast64_t; 584 | #endif 585 | /* fast types */ 586 | #endif 587 | 588 | #ifdef _STDINT_NEED_INTMAX_T 589 | #ifdef _HAVE_UINT64_T 590 | typedef int64_t intmax_t; 591 | typedef uint64_t uintmax_t; 592 | #else 593 | typedef long intmax_t; 594 | typedef unsigned long uintmax_t; 595 | #endif 596 | #endif 597 | 598 | #ifdef _STDINT_NEED_INTPTR_T 599 | #ifndef __intptr_t_defined 600 | #define __intptr_t_defined 601 | /* we encourage using "long" to store pointer values, never use "int" ! */ 602 | #if _STDINT_LONG_MODEL+0 == 242 || _STDINT_LONG_MODEL+0 == 484 603 | typedef unsigned int uintptr_t; 604 | typedef int intptr_t; 605 | #elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL+0 == 444 606 | typedef unsigned long uintptr_t; 607 | typedef long intptr_t; 608 | #elif _STDINT_LONG_MODEL+0 == 448 && defined _HAVE_UINT64_T 609 | typedef uint64_t uintptr_t; 610 | typedef int64_t intptr_t; 611 | #else /* matches typical system types ILP32 and LP64 - but not IP16 or LLP64 */ 612 | typedef unsigned long uintptr_t; 613 | typedef long intptr_t; 614 | #endif 615 | #endif 616 | #endif 617 | 618 | /* The ISO C99 standard specifies that in C++ implementations these 619 | should only be defined if explicitly requested. */ 620 | #if !defined __cplusplus || defined __STDC_CONSTANT_MACROS 621 | #ifndef UINT32_C 622 | 623 | /* Signed. */ 624 | # define INT8_C(c) c 625 | # define INT16_C(c) c 626 | # define INT32_C(c) c 627 | # ifdef _HAVE_LONGLONG_UINT64_T 628 | # define INT64_C(c) c ## L 629 | # else 630 | # define INT64_C(c) c ## LL 631 | # endif 632 | 633 | /* Unsigned. */ 634 | # define UINT8_C(c) c ## U 635 | # define UINT16_C(c) c ## U 636 | # define UINT32_C(c) c ## U 637 | # ifdef _HAVE_LONGLONG_UINT64_T 638 | # define UINT64_C(c) c ## UL 639 | # else 640 | # define UINT64_C(c) c ## ULL 641 | # endif 642 | 643 | /* Maximal type. */ 644 | # ifdef _HAVE_LONGLONG_UINT64_T 645 | # define INTMAX_C(c) c ## L 646 | # define UINTMAX_C(c) c ## UL 647 | # else 648 | # define INTMAX_C(c) c ## LL 649 | # define UINTMAX_C(c) c ## ULL 650 | # endif 651 | 652 | /* literalnumbers */ 653 | #endif 654 | #endif 655 | 656 | /* These limits are merily those of a two complement byte-oriented system */ 657 | 658 | /* Minimum of signed integral types. */ 659 | # define INT8_MIN (-128) 660 | # define INT16_MIN (-32767-1) 661 | # define INT32_MIN (-2147483647-1) 662 | # define INT64_MIN (-__INT64_C(9223372036854775807)-1) 663 | /* Maximum of signed integral types. */ 664 | # define INT8_MAX (127) 665 | # define INT16_MAX (32767) 666 | # define INT32_MAX (2147483647) 667 | # define INT64_MAX (__INT64_C(9223372036854775807)) 668 | 669 | /* Maximum of unsigned integral types. */ 670 | # define UINT8_MAX (255) 671 | # define UINT16_MAX (65535) 672 | # define UINT32_MAX (4294967295U) 673 | # define UINT64_MAX (__UINT64_C(18446744073709551615)) 674 | 675 | /* Minimum of signed integral types having a minimum size. */ 676 | # define INT_LEAST8_MIN INT8_MIN 677 | # define INT_LEAST16_MIN INT16_MIN 678 | # define INT_LEAST32_MIN INT32_MIN 679 | # define INT_LEAST64_MIN INT64_MIN 680 | /* Maximum of signed integral types having a minimum size. */ 681 | # define INT_LEAST8_MAX INT8_MAX 682 | # define INT_LEAST16_MAX INT16_MAX 683 | # define INT_LEAST32_MAX INT32_MAX 684 | # define INT_LEAST64_MAX INT64_MAX 685 | 686 | /* Maximum of unsigned integral types having a minimum size. */ 687 | # define UINT_LEAST8_MAX UINT8_MAX 688 | # define UINT_LEAST16_MAX UINT16_MAX 689 | # define UINT_LEAST32_MAX UINT32_MAX 690 | # define UINT_LEAST64_MAX UINT64_MAX 691 | 692 | /* shortcircuit*/ 693 | #endif 694 | /* once */ 695 | #endif 696 | #endif 697 | STDINT_EOF 698 | fi 699 | if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then 700 | AC_MSG_NOTICE([$ac_stdint_h is unchanged]) 701 | else 702 | ac_dir=`AS_DIRNAME(["$ac_stdint_h"])` 703 | AS_MKDIR_P(["$ac_dir"]) 704 | rm -f $ac_stdint_h 705 | mv $ac_stdint $ac_stdint_h 706 | fi 707 | ],[# variables for create stdint.h replacement 708 | PACKAGE="$PACKAGE" 709 | VERSION="$VERSION" 710 | ac_stdint_h="$ac_stdint_h" 711 | _ac_stdint_h=AS_TR_CPP(_$PACKAGE-$ac_stdint_h) 712 | ac_cv_stdint_message="$ac_cv_stdint_message" 713 | ac_cv_header_stdint_t="$ac_cv_header_stdint_t" 714 | ac_cv_header_stdint_x="$ac_cv_header_stdint_x" 715 | ac_cv_header_stdint_o="$ac_cv_header_stdint_o" 716 | ac_cv_header_stdint_u="$ac_cv_header_stdint_u" 717 | ac_cv_type_uint64_t="$ac_cv_type_uint64_t" 718 | ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t" 719 | ac_cv_char_data_model="$ac_cv_char_data_model" 720 | ac_cv_long_data_model="$ac_cv_long_data_model" 721 | ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t" 722 | ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t" 723 | ac_cv_type_intmax_t="$ac_cv_type_intmax_t" 724 | ]) 725 | ]) 726 | -------------------------------------------------------------------------------- /snippets/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libsnippets.la 2 | 3 | libsnippets_la_SOURCES = \ 4 | linkedlist.c \ 5 | fnv.c \ 6 | rand.c \ 7 | skiplist.c \ 8 | bloomfilter.c 9 | 10 | libsnippets_la_CFLAGS = \ 11 | -I$(top_srcdir) \ 12 | -I$(top_builddir) 13 | libsnippets_la_LDFLAGS = \ 14 | -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ 15 | -export-symbols-regex '^snippets_.*$$' \ 16 | -no-undefined 17 | libsnippets_la_LIBADD = \ 18 | $(LIBM) 19 | 20 | libsnippetsdir = $(includedir)/snippets 21 | 22 | libsnippets_HEADERS = \ 23 | utils.h \ 24 | snippets-stdint.h \ 25 | linkedlist.h \ 26 | fnv.h \ 27 | rand.h \ 28 | skiplist.h \ 29 | bloomfilter.h 30 | 31 | -------------------------------------------------------------------------------- /snippets/bloomfilter.c: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifdef HAVE_CONFIG_H 21 | #include "config.h" 22 | #endif 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | #ifndef M_LN2 30 | #define M_LN2 0.69314718055994530942 31 | #endif 32 | 33 | #include 34 | 35 | /* This implements a bloom filter, see 36 | * 37 | * http://en.wikipedia.org/wiki/Bloom_filter 38 | * or 39 | * "Space/Time Trade-offs in Hash Coding with Allowable Errors" 40 | * by Burton H. Bloom in Communications of the ACM Volume 13, 41 | * Number 7 (1970). 42 | * 43 | * The hashing implemented here is the enhanced double hashing 44 | * as proposed in "Bloom Filters in Probabilistic Verification" 45 | * by Peter C. Dillinger and Panagiotis Manolios. 46 | * 47 | * The formula for the optimal number of hash functions and 48 | * the false positive probability comes from their paper too. 49 | */ 50 | 51 | struct _SnippetsBloomFilter 52 | { 53 | uint8_t *filter; 54 | uint32_t size; 55 | uint64_t n_elements; 56 | unsigned int n_hash_functions; 57 | unsigned int hash_size; 58 | 59 | void (*hash) (const uint8_t * data, size_t size, uint8_t * hash); 60 | }; 61 | 62 | SnippetsBloomFilter * 63 | snippets_bloom_filter_new (uint32_t size, unsigned int n_hash_functions, 64 | unsigned int hash_size) 65 | { 66 | SnippetsBloomFilter *filter; 67 | 68 | assert (size > 0); 69 | assert (n_hash_functions > 0); 70 | assert (hash_size > 0 && hash_size <= 1024); 71 | 72 | /* Round up to next byte multiple */ 73 | size = (((size) + 7) & ~7); 74 | 75 | filter = calloc (sizeof (SnippetsBloomFilter) + size / 8, 1); 76 | 77 | if (hash_size <= 64) { 78 | filter->hash_size = 64; 79 | filter->hash = snippets_fnv1a_64; 80 | } else if (hash_size <= 128) { 81 | filter->hash_size = 128; 82 | filter->hash = snippets_fnv1a_128; 83 | } else if (hash_size <= 256) { 84 | filter->hash_size = 256; 85 | filter->hash = snippets_fnv1a_256; 86 | } else if (hash_size <= 512) { 87 | filter->hash_size = 512; 88 | filter->hash = snippets_fnv1a_512; 89 | } else if (hash_size <= 1024) { 90 | filter->hash_size = 1024; 91 | filter->hash = snippets_fnv1a_1024; 92 | } 93 | 94 | filter->filter = ((uint8_t *) filter) + sizeof (SnippetsBloomFilter); 95 | filter->size = size; 96 | filter->n_hash_functions = n_hash_functions; 97 | 98 | return filter; 99 | } 100 | 101 | #define SET_BIT(filter, bit) (filter[bit / 8] |= (1 << (bit % 8))) 102 | #define GET_BIT(filter, bit) (filter[bit / 8] & (1 << (bit % 8))) 103 | 104 | static int 105 | snippets_bloom_filter_hash (SnippetsBloomFilter * filter, const uint8_t * data, 106 | size_t length, int set) 107 | { 108 | uint32_t hash[32]; 109 | unsigned int n_hash_functions, first_n_hash_functions; 110 | unsigned int hash_index; 111 | unsigned int hash_values; 112 | unsigned int functions_per_value; 113 | unsigned int last_functions; 114 | uint32_t x, y; 115 | uint32_t size; 116 | int i, j; 117 | 118 | size = filter->size; 119 | 120 | /* The code below is hashing the input data, splitting the hash into 32 bit 121 | * integers and taking pairs of those for implementing the enhanced double 122 | * hashing. This means we can handle up to hash_size/32/2 has functions 123 | * directly without double hashing, and otherwise have to use double hashing 124 | * for remaining ones based on the 32 bit pairs we got */ 125 | n_hash_functions = filter->n_hash_functions; 126 | hash_values = filter->hash_size / 32; 127 | 128 | if (n_hash_functions <= hash_values / 2) { 129 | first_n_hash_functions = n_hash_functions; 130 | functions_per_value = 1; 131 | last_functions = 0; 132 | } else { 133 | functions_per_value = n_hash_functions / (hash_values / 2); 134 | last_functions = functions_per_value + n_hash_functions % (hash_values / 2); 135 | 136 | if (last_functions == functions_per_value) 137 | last_functions = 0; 138 | first_n_hash_functions = n_hash_functions - last_functions; 139 | } 140 | 141 | filter->hash (data, length, (uint8_t *) hash); 142 | 143 | hash_index = 0; 144 | 145 | /* If there are fewer hash functions than hash value pairs 146 | * or the number of hash functions is an integer multiple 147 | * of the number of hash value pairs: Handle all hash 148 | * functions in this loop. 149 | * 150 | * Otherwise handle all hash functions in this loop 151 | * except the ones for the last hash value pair */ 152 | for (i = 0; i < first_n_hash_functions; i += functions_per_value) { 153 | x = hash[hash_index] % size; 154 | y = hash[hash_index + hash_values / 2] % size; 155 | 156 | if (functions_per_value == 1) 157 | x = (x + y) % size; 158 | 159 | if (set) 160 | SET_BIT (filter->filter, x); 161 | else if (!GET_BIT (filter->filter, x)) 162 | return FALSE; 163 | 164 | for (j = 0; j < functions_per_value - 1; j++) { 165 | x = (x + y) % size; 166 | y = (y + j) % size; 167 | 168 | if (set) 169 | SET_BIT (filter->filter, x); 170 | else if (!GET_BIT (filter->filter, x)) 171 | return FALSE; 172 | } 173 | hash_index++; 174 | } 175 | 176 | /* If there are hash functions left handle 177 | * them here 178 | */ 179 | if (last_functions) { 180 | x = hash[hash_index] % size; 181 | y = hash[hash_index + hash_values / 2] % size; 182 | 183 | if (set) 184 | SET_BIT (filter->filter, x); 185 | else if (!GET_BIT (filter->filter, x)) 186 | return FALSE; 187 | 188 | for (j = 0; j < last_functions - 1; j++) { 189 | x = (x + y) % size; 190 | y = (y + j) % size; 191 | 192 | if (set) 193 | SET_BIT (filter->filter, x); 194 | else if (!GET_BIT (filter->filter, x)) 195 | return FALSE; 196 | } 197 | } 198 | 199 | return TRUE; 200 | } 201 | 202 | void 203 | snippets_bloom_filter_insert (SnippetsBloomFilter * filter, 204 | const uint8_t * data, size_t length) 205 | { 206 | assert (filter != NULL); 207 | assert (data != NULL); 208 | 209 | snippets_bloom_filter_hash (filter, data, length, TRUE); 210 | filter->n_elements++; 211 | } 212 | 213 | int 214 | snippets_bloom_filter_contains (SnippetsBloomFilter * filter, 215 | const uint8_t * data, size_t length) 216 | { 217 | assert (filter != NULL); 218 | assert (data != NULL); 219 | 220 | return snippets_bloom_filter_hash (filter, data, length, FALSE); 221 | } 222 | 223 | void 224 | snippets_bloom_filter_free (SnippetsBloomFilter * filter) 225 | { 226 | assert (filter != NULL); 227 | 228 | free (filter); 229 | } 230 | 231 | unsigned int 232 | snippets_bloom_filter_optimal_n_hash_functions (uint32_t filter_size, 233 | uint64_t n_elements) 234 | { 235 | double m, n; 236 | 237 | assert (n_elements != 0); 238 | 239 | m = filter_size; 240 | n = n_elements; 241 | 242 | return (unsigned int) (pow (3.8, 1.0 / (m / n + 4.2)) * (m / n) * M_LN2); 243 | } 244 | 245 | unsigned int 246 | snippets_bloom_filter_n_hash_functions (SnippetsBloomFilter * filter) 247 | { 248 | assert (filter != NULL); 249 | 250 | return filter->n_hash_functions; 251 | } 252 | 253 | uint32_t 254 | snippets_bloom_filter_size (SnippetsBloomFilter * filter) 255 | { 256 | assert (filter != NULL); 257 | 258 | return filter->size; 259 | } 260 | 261 | uint64_t 262 | snippets_bloom_filter_n_elements (SnippetsBloomFilter * filter) 263 | { 264 | assert (filter != NULL); 265 | 266 | return filter->n_elements; 267 | } 268 | 269 | double 270 | snippets_bloom_filter_false_positive_rate (SnippetsBloomFilter * filter) 271 | { 272 | double n_hash_functions; 273 | double n_elements; 274 | double filter_size; 275 | 276 | assert (filter != NULL); 277 | 278 | n_hash_functions = filter->n_hash_functions; 279 | n_elements = filter->n_elements; 280 | filter_size = filter->size; 281 | 282 | return pow (1.0 - pow (M_E, (-n_hash_functions * n_elements) / filter_size), 283 | n_hash_functions); 284 | } 285 | -------------------------------------------------------------------------------- /snippets/bloomfilter.h: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifndef __SNIPPETS_BLOOM_FILTER_H__ 21 | #define __SNIPPETS_BLOOM_FILTER_H__ 22 | 23 | #include 24 | 25 | typedef struct _SnippetsBloomFilter SnippetsBloomFilter; 26 | 27 | SnippetsBloomFilter * snippets_bloom_filter_new (uint32_t size, unsigned int n_hash_functions, unsigned int hash_size); 28 | void snippets_bloom_filter_insert (SnippetsBloomFilter *filter, const uint8_t *data, size_t length); 29 | int snippets_bloom_filter_contains (SnippetsBloomFilter *filter, const uint8_t *data, size_t length); 30 | void snippets_bloom_filter_free (SnippetsBloomFilter *filter); 31 | 32 | unsigned int snippets_bloom_filter_n_hash_functions (SnippetsBloomFilter *filter); 33 | uint32_t snippets_bloom_filter_size (SnippetsBloomFilter *filter); 34 | 35 | uint64_t snippets_bloom_filter_n_elements (SnippetsBloomFilter *filter); 36 | double snippets_bloom_filter_false_positive_rate (SnippetsBloomFilter *filter); 37 | 38 | unsigned int snippets_bloom_filter_optimal_n_hash_functions (uint32_t filter_size, uint64_t n_elements); 39 | 40 | #endif /* __SNIPPETS_BLOOM_FILTER_H__ */ 41 | -------------------------------------------------------------------------------- /snippets/fnv.h: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifndef __SNIPPETS_FNV_H__ 21 | #define __SNIPPETS_FNV_H__ 22 | 23 | #include 24 | 25 | SNIPPETS_BEGIN_DECLS 26 | 27 | /** fnv1_32: 28 | * @data: Data to be hashed 29 | * @len: Length of @data in bytes 30 | * @hash: Pointer to a 4 byte array for the calculated hash 31 | * 32 | * Calculates the FNV1 32 bit hash from @data and puts it 33 | * into @hash. 34 | */ 35 | void snippets_fnv1_32 (const uint8_t *data, size_t len, uint8_t hash[4]); 36 | 37 | /** fnv1a_32: 38 | * @data: Data to be hashed 39 | * @len: Length of @data in bytes 40 | * @hash: Pointer to a 4 byte array for the calculated hash 41 | * 42 | * Calculates the FNV1A 32 bit hash from @data and puts it 43 | * into @hash. 44 | */ 45 | void snippets_fnv1a_32 (const uint8_t *data, size_t len, uint8_t hash[8]); 46 | 47 | /** fnv1_64: 48 | * @data: Data to be hashed 49 | * @len: Length of @data in bytes 50 | * @hash: Pointer to a 8 byte array for the calculated hash 51 | * 52 | * Calculates the FNV1 64 bit hash from @data and puts it 53 | * into @hash. 54 | */ 55 | void snippets_fnv1_64 (const uint8_t *data, size_t len, uint8_t hash[4]); 56 | 57 | /** fnv1a_64: 58 | * @data: Data to be hashed 59 | * @len: Length of @data in bytes 60 | * @hash: Pointer to a 8 byte array for the calculated hash 61 | * 62 | * Calculates the FNV1A 64 bit hash from @data and puts it 63 | * into @hash. 64 | */ 65 | void snippets_fnv1a_64 (const uint8_t *data, size_t len, uint8_t hash[8]); 66 | 67 | /** fnv1_128: 68 | * @data: Data to be hashed 69 | * @len: Length of @data in bytes 70 | * @hash: Pointer to a 16 byte array for the calculated hash 71 | * 72 | * Calculates the FNV1 128 bit hash from @data and puts it 73 | * into @hash. 74 | */ 75 | void snippets_fnv1_128 (const uint8_t *data, size_t len, uint8_t hash[16]); 76 | 77 | /** fnv1a_128: 78 | * @data: Data to be hashed 79 | * @len: Length of @data in bytes 80 | * @hash: Pointer to a 16 byte array for the calculated hash 81 | * 82 | * Calculates the FNV1A 128 bit hash from @data and puts it 83 | * into @hash. 84 | */ 85 | void snippets_fnv1a_128 (const uint8_t *data, size_t len, uint8_t hash[16]); 86 | 87 | /** fnv1_256: 88 | * @data: Data to be hashed 89 | * @len: Length of @data in bytes 90 | * @hash: Pointer to a 32 byte array for the calculated hash 91 | * 92 | * Calculates the FNV1 256 bit hash from @data and puts it 93 | * into @hash. 94 | */ 95 | void snippets_fnv1_256 (const uint8_t *data, size_t len, uint8_t hash[32]); 96 | 97 | /** fnv1a_256: 98 | * @data: Data to be hashed 99 | * @len: Length of @data in bytes 100 | * @hash: Pointer to a 32 byte array for the calculated hash 101 | * 102 | * Calculates the FNV1A 256 bit hash from @data and puts it 103 | * into @hash. 104 | */ 105 | void snippets_fnv1a_256 (const uint8_t *data, size_t len, uint8_t hash[32]); 106 | 107 | /** fnv1_512: 108 | * @data: Data to be hashed 109 | * @len: Length of @data in bytes 110 | * @hash: Pointer to a 64 byte array for the calculated hash 111 | * 112 | * Calculates the FNV1 512 bit hash from @data and puts it 113 | * into @hash. 114 | */ 115 | void snippets_fnv1_512 (const uint8_t *data, size_t len, uint8_t hash[64]); 116 | 117 | /** fnv1a_512: 118 | * @data: Data to be hashed 119 | * @len: Length of @data in bytes 120 | * @hash: Pointer to a 64 byte array for the calculated hash 121 | * 122 | * Calculates the FNV1A 512 bit hash from @data and puts it 123 | * into @hash. 124 | */ 125 | void snippets_fnv1a_512 (const uint8_t *data, size_t len, uint8_t hash[64]); 126 | 127 | /** fnv1_1024: 128 | * @data: Data to be hashed 129 | * @len: Length of @data in bytes 130 | * @hash: Pointer to a 128 byte array for the calculated hash 131 | * 132 | * Calculates the FNV1 1024 bit hash from @data and puts it 133 | * into @hash. 134 | */ 135 | void snippets_fnv1_1024 (const uint8_t *data, size_t len, uint8_t hash[128]); 136 | 137 | /** fnv1a_1024: 138 | * @data: Data to be hashed 139 | * @len: Length of @data in bytes 140 | * @hash: Pointer to a 128 byte array for the calculated hash 141 | * 142 | * Calculates the FNV1A 1024 bit hash from @data and puts it 143 | * into @hash. 144 | */ 145 | void snippets_fnv1a_1024 (const uint8_t *data, size_t len, uint8_t hash[128]); 146 | 147 | SNIPPETS_END_DECLS 148 | 149 | #endif /* __SNIPPETS_FNV_H__ */ 150 | -------------------------------------------------------------------------------- /snippets/linkedlist.c: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifdef HAVE_CONFIG_H 21 | #include "config.h" 22 | #endif 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | struct _SnippetsLinkedList 30 | { 31 | SnippetsLinkedListNode *head, *tail; 32 | size_t length; 33 | int pointer; 34 | 35 | size_t data_size; 36 | SnippetsCopyToFunction copy_func; 37 | SnippetsFreeFunction free_func; 38 | }; 39 | 40 | struct _SnippetsLinkedListNode 41 | { 42 | SnippetsLinkedList *list; 43 | SnippetsLinkedListNode *prev, *next; 44 | void *data; 45 | }; 46 | 47 | #define STRUCT_ALIGNMENT (2 * sizeof (size_t)) 48 | #define STRUCT_ALIGN(offset) \ 49 | ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT) 50 | 51 | static SnippetsLinkedListNode * 52 | snippets_linked_list_node_new (SnippetsLinkedList * list, size_t data_size, 53 | SnippetsCopyToFunction copy_func, void *data) 54 | { 55 | SnippetsLinkedListNode *node; 56 | 57 | if (!list->pointer) { 58 | assert (data != NULL); 59 | 60 | node = 61 | calloc (STRUCT_ALIGN (sizeof (SnippetsLinkedListNode)) + data_size, 1); 62 | node->data = 63 | ((uint8_t *) node) + STRUCT_ALIGN (sizeof (SnippetsLinkedListNode)); 64 | if (copy_func) 65 | copy_func (node->data, data); 66 | else 67 | memcpy (node->data, data, data_size); 68 | } else { 69 | node = calloc (sizeof (SnippetsLinkedListNode), 1); 70 | if (copy_func) 71 | copy_func (&node->data, data); 72 | else 73 | node->data = data; 74 | } 75 | node->list = list; 76 | 77 | return node; 78 | } 79 | 80 | static void 81 | snippets_linked_list_node_free (SnippetsLinkedListNode * node, 82 | SnippetsFreeFunction free_func) 83 | { 84 | if (free_func && node->data) 85 | free_func (node->data); 86 | free (node); 87 | } 88 | 89 | SnippetsLinkedList * 90 | snippets_linked_list_new (size_t data_size, SnippetsCopyToFunction copy_func, 91 | SnippetsFreeFunction free_func) 92 | { 93 | SnippetsLinkedList *list; 94 | 95 | assert (data_size != 0); 96 | 97 | list = calloc (sizeof (SnippetsLinkedList), 1); 98 | 99 | list->data_size = data_size; 100 | list->copy_func = copy_func; 101 | list->free_func = free_func; 102 | list->pointer = FALSE; 103 | 104 | return list; 105 | } 106 | 107 | SnippetsLinkedList * 108 | snippets_linked_list_new_pointer (SnippetsCopyToFunction copy_func, 109 | SnippetsFreeFunction free_func) 110 | { 111 | SnippetsLinkedList *list = calloc (sizeof (SnippetsLinkedList), 1); 112 | 113 | list->data_size = 0; 114 | list->copy_func = copy_func; 115 | list->free_func = free_func; 116 | list->pointer = TRUE; 117 | 118 | return list; 119 | } 120 | 121 | void 122 | snippets_linked_list_free (SnippetsLinkedList * list) 123 | { 124 | SnippetsLinkedListNode *l, *m; 125 | 126 | assert (list != NULL); 127 | 128 | l = list->head; 129 | while (l) { 130 | m = l; 131 | l = l->next; 132 | snippets_linked_list_node_free (m, list->free_func); 133 | } 134 | free (list); 135 | } 136 | 137 | SnippetsLinkedList * 138 | snippets_linked_list_copy (const SnippetsLinkedList * list) 139 | { 140 | SnippetsLinkedList *copy; 141 | SnippetsLinkedListNode *l; 142 | 143 | assert (list != NULL); 144 | 145 | copy = calloc (sizeof (SnippetsLinkedList), 1); 146 | 147 | copy->data_size = list->data_size; 148 | copy->copy_func = list->copy_func; 149 | copy->free_func = list->free_func; 150 | copy->pointer = list->pointer; 151 | 152 | for (l = list->head; l; l = l->next) 153 | snippets_linked_list_append (copy, l->data); 154 | 155 | return copy; 156 | } 157 | 158 | SnippetsLinkedListNode * 159 | snippets_linked_list_append (SnippetsLinkedList * list, void *data) 160 | { 161 | SnippetsLinkedListNode *node; 162 | SnippetsLinkedListNode *prev; 163 | 164 | assert (list != NULL); 165 | 166 | node = 167 | snippets_linked_list_node_new (list, list->data_size, list->copy_func, 168 | data); 169 | 170 | if (!list->head) { 171 | list->head = list->tail = node; 172 | } else { 173 | prev = list->tail; 174 | prev->next = node; 175 | node->prev = prev; 176 | list->tail = node; 177 | } 178 | list->length++; 179 | 180 | return node; 181 | } 182 | 183 | SnippetsLinkedListNode * 184 | snippets_linked_list_prepend (SnippetsLinkedList * list, void *data) 185 | { 186 | SnippetsLinkedListNode *node; 187 | SnippetsLinkedListNode *next; 188 | 189 | assert (list != NULL); 190 | 191 | node = 192 | snippets_linked_list_node_new (list, list->data_size, list->copy_func, 193 | data); 194 | 195 | if (!list->head) { 196 | list->head = list->tail = node; 197 | } else { 198 | next = list->head; 199 | next->prev = node; 200 | node->next = next; 201 | list->head = node; 202 | } 203 | list->length++; 204 | 205 | return node; 206 | } 207 | 208 | SnippetsLinkedListNode * 209 | snippets_linked_list_insert_after (SnippetsLinkedList * list, 210 | SnippetsLinkedListNode * prev, void *data) 211 | { 212 | SnippetsLinkedListNode *node; 213 | SnippetsLinkedListNode *next; 214 | 215 | assert (list != NULL); 216 | 217 | if (!prev) 218 | return snippets_linked_list_append (list, data); 219 | 220 | assert (prev != NULL); 221 | assert (prev->list == list); 222 | 223 | node = 224 | snippets_linked_list_node_new (list, list->data_size, list->copy_func, 225 | data); 226 | next = prev->next; 227 | prev->next = node; 228 | next->prev = node; 229 | node->prev = prev; 230 | node->next = next; 231 | 232 | list->length++; 233 | 234 | return node; 235 | } 236 | 237 | SnippetsLinkedListNode * 238 | snippets_linked_list_insert_before (SnippetsLinkedList * list, 239 | SnippetsLinkedListNode * next, void *data) 240 | { 241 | SnippetsLinkedListNode *node; 242 | SnippetsLinkedListNode *prev; 243 | 244 | assert (list != NULL); 245 | 246 | if (!next) 247 | return snippets_linked_list_prepend (list, data); 248 | 249 | assert (next != NULL); 250 | assert (next->list == list); 251 | 252 | node = 253 | snippets_linked_list_node_new (list, list->data_size, list->copy_func, 254 | data); 255 | prev = next->prev; 256 | next->prev = node; 257 | prev->next = node; 258 | node->prev = prev; 259 | node->next = next; 260 | 261 | list->length++; 262 | 263 | return node; 264 | } 265 | 266 | void 267 | snippets_linked_list_remove (SnippetsLinkedList * list, 268 | SnippetsLinkedListNode * node) 269 | { 270 | SnippetsLinkedListNode *prev, *next; 271 | 272 | assert (list != NULL); 273 | assert (node != NULL); 274 | assert (node->list == list); 275 | 276 | if (node == list->head) { 277 | next = node->next; 278 | if (next) 279 | next->prev = NULL; 280 | else 281 | list->tail = NULL; 282 | list->head = next; 283 | } else if (node == list->tail) { 284 | prev = node->prev; 285 | if (prev) 286 | prev->next = NULL; 287 | list->tail = prev; 288 | } else { 289 | prev = node->prev; 290 | next = node->next; 291 | 292 | prev->next = next; 293 | next->prev = prev; 294 | } 295 | list->length--; 296 | snippets_linked_list_node_free (node, list->free_func); 297 | } 298 | 299 | SnippetsLinkedListNode * 300 | snippets_linked_list_find (SnippetsLinkedList * list, const void *data, 301 | SnippetsCompareFunction compare_func, void *user_data) 302 | { 303 | SnippetsLinkedListNode *l; 304 | 305 | assert (list != NULL); 306 | assert (data != NULL); 307 | assert (compare_func != NULL); 308 | 309 | for (l = list->head; l; l = l->next) { 310 | if (compare_func (l->data, data, user_data) == 0) 311 | return l; 312 | } 313 | return NULL; 314 | } 315 | 316 | SnippetsLinkedListNode * 317 | snippets_linked_list_head (SnippetsLinkedList * list) 318 | { 319 | assert (list != NULL); 320 | return list->head; 321 | } 322 | 323 | SnippetsLinkedListNode * 324 | snippets_linked_list_tail (SnippetsLinkedList * list) 325 | { 326 | assert (list != NULL); 327 | return list->tail; 328 | } 329 | 330 | size_t 331 | snippets_linked_list_length (SnippetsLinkedList * list) 332 | { 333 | assert (list != NULL); 334 | return list->length; 335 | } 336 | 337 | SnippetsLinkedListNode * 338 | snippets_linked_list_node_next (SnippetsLinkedListNode * node) 339 | { 340 | assert (node != NULL); 341 | return node->next; 342 | } 343 | 344 | SnippetsLinkedListNode * 345 | snippets_linked_list_node_prev (SnippetsLinkedListNode * node) 346 | { 347 | assert (node != NULL); 348 | return node->prev; 349 | } 350 | 351 | void * 352 | snippets_linked_list_node_get_ (SnippetsLinkedListNode * node) 353 | { 354 | assert (node != NULL); 355 | 356 | if (node->list->pointer) 357 | return &node->data; 358 | else 359 | return node->data; 360 | } 361 | -------------------------------------------------------------------------------- /snippets/linkedlist.h: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifndef __SNIPPETS_LINKED_LIST_H__ 21 | #define __SNIPPETS_LINKED_LIST_H__ 22 | 23 | #include 24 | 25 | SNIPPETS_BEGIN_DECLS 26 | 27 | typedef struct _SnippetsLinkedList SnippetsLinkedList; 28 | typedef struct _SnippetsLinkedListNode SnippetsLinkedListNode; 29 | 30 | SnippetsLinkedList * snippets_linked_list_new (size_t data_size, SnippetsCopyToFunction copy_func, SnippetsFreeFunction free_func); 31 | SnippetsLinkedList * snippets_linked_list_new_pointer (SnippetsCopyToFunction copy_func, SnippetsFreeFunction free_func); 32 | void snippets_linked_list_free (SnippetsLinkedList *list); 33 | 34 | SnippetsLinkedList * snippets_linked_list_copy (const SnippetsLinkedList *list); 35 | 36 | SnippetsLinkedListNode * snippets_linked_list_append (SnippetsLinkedList *list, void *data); 37 | SnippetsLinkedListNode * snippets_linked_list_prepend (SnippetsLinkedList *list, void *data); 38 | SnippetsLinkedListNode * snippets_linked_list_insert_after (SnippetsLinkedList *list, SnippetsLinkedListNode *prev, void *data); 39 | SnippetsLinkedListNode * snippets_linked_list_insert_before (SnippetsLinkedList *list, SnippetsLinkedListNode *next, void *data); 40 | void snippets_linked_list_remove (SnippetsLinkedList *list, SnippetsLinkedListNode *node); 41 | 42 | SnippetsLinkedListNode * snippets_linked_list_find (SnippetsLinkedList *list, const void *data, SnippetsCompareFunction compare_func, void *user_data); 43 | 44 | SnippetsLinkedListNode * snippets_linked_list_head (SnippetsLinkedList *list); 45 | SnippetsLinkedListNode * snippets_linked_list_tail (SnippetsLinkedList *list); 46 | size_t snippets_linked_list_length (SnippetsLinkedList *list); 47 | 48 | SnippetsLinkedListNode * snippets_linked_list_node_next (SnippetsLinkedListNode *node); 49 | SnippetsLinkedListNode * snippets_linked_list_node_prev (SnippetsLinkedListNode *node); 50 | 51 | #define snippets_linked_list_node_get(node, __type) \ 52 | ((__type *) snippets_linked_list_node_get_ (node)); 53 | void * snippets_linked_list_node_get_ (SnippetsLinkedListNode *node); 54 | 55 | SNIPPETS_END_DECLS 56 | 57 | #endif /* __SNIPPETS_LINKED_LIST_H__ */ 58 | -------------------------------------------------------------------------------- /snippets/mt19937.c: -------------------------------------------------------------------------------- 1 | /* 2 | A C-program for MT19937, with initialization improved 2002/1/26. 3 | Coded by Takuji Nishimura and Makoto Matsumoto. 4 | 5 | Before using, initialize the state by using init_genrand(seed) 6 | or init_by_array(init_key, key_length). 7 | 8 | Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions 13 | are met: 14 | 15 | 1. Redistributions of source code must retain the above copyright 16 | notice, this list of conditions and the following disclaimer. 17 | 18 | 2. Redistributions in binary form must reproduce the above copyright 19 | notice, this list of conditions and the following disclaimer in the 20 | documentation and/or other materials provided with the distribution. 21 | 22 | 3. The names of its contributors may not be used to endorse or promote 23 | products derived from this software without specific prior written 24 | permission. 25 | 26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 30 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 31 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 32 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 33 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 34 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 35 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | 38 | 39 | Any feedback is very welcome. 40 | http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html 41 | email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) 42 | */ 43 | 44 | /* Period parameters */ 45 | #define M 397 46 | #define MATRIX_A 0x9908b0dfUL /* constant vector a */ 47 | #define UPPER_MASK 0x80000000UL /* most significant w-r bits */ 48 | #define LOWER_MASK 0x7fffffffUL /* least significant r bits */ 49 | 50 | /* initializes mt[N] with a seed */ 51 | static void 52 | mt19937_init (SnippetsRand * rand, uint32_t s) 53 | { 54 | uint32_t *mt = rand->mt; 55 | unsigned int mti; 56 | 57 | mt[0] = s & 0xffffffffUL; 58 | for (mti = 1; mti < N; mti++) { 59 | mt[mti] = (1812433253UL * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti); 60 | /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ 61 | /* In the previous versions, MSBs of the seed affect */ 62 | /* only MSBs of the array mt[]. */ 63 | /* 2002/01/09 modified by Makoto Matsumoto */ 64 | mt[mti] &= 0xffffffffUL; 65 | /* for >32 bit machines */ 66 | } 67 | rand->mti = mti; 68 | } 69 | 70 | /* generates a random number on [0,0xffffffff]-interval */ 71 | static uint32_t 72 | mt19937_genrand_uint32 (SnippetsRand * rand) 73 | { 74 | static const uint32_t mag01[2] = { 0x0UL, MATRIX_A }; 75 | uint32_t y; 76 | uint32_t *mt = rand->mt; 77 | unsigned int mti = rand->mti; 78 | 79 | /* mag01[x] = x * MATRIX_A for x=0,1 */ 80 | 81 | if (mti >= N) { /* generate N words at one time */ 82 | int kk; 83 | 84 | for (kk = 0; kk < N - M; kk++) { 85 | y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK); 86 | mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1UL]; 87 | } 88 | for (; kk < N - 1; kk++) { 89 | y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK); 90 | mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; 91 | } 92 | y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK); 93 | mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1UL]; 94 | 95 | mti = 0; 96 | } 97 | 98 | y = mt[mti++]; 99 | 100 | /* Tempering */ 101 | y ^= (y >> 11); 102 | y ^= (y << 7) & 0x9d2c5680UL; 103 | y ^= (y << 15) & 0xefc60000UL; 104 | y ^= (y >> 18); 105 | 106 | rand->mti = mti; 107 | 108 | return y; 109 | } 110 | -------------------------------------------------------------------------------- /snippets/rand.c: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifdef HAVE_CONFIG_H 21 | #include "config.h" 22 | #endif 23 | 24 | #include 25 | 26 | #include 27 | 28 | #define N 624 29 | 30 | struct _SnippetsRand 31 | { 32 | uint32_t mt[N]; 33 | unsigned int mti; 34 | }; 35 | 36 | #include "mt19937.c" 37 | 38 | SnippetsRand * 39 | snippets_rand_new (uint32_t seed) 40 | { 41 | SnippetsRand *rand = calloc (sizeof (SnippetsRand), 1); 42 | 43 | mt19937_init (rand, seed); 44 | 45 | return rand; 46 | } 47 | 48 | void 49 | snippets_rand_free (SnippetsRand * rand) 50 | { 51 | assert (rand != NULL); 52 | free (rand); 53 | } 54 | 55 | uint32_t 56 | snippets_rand_uint32 (SnippetsRand * rand) 57 | { 58 | assert (rand != NULL); 59 | 60 | return mt19937_genrand_uint32 (rand); 61 | } 62 | 63 | uint32_t 64 | snippets_rand_uint32_range (SnippetsRand * rand, uint32_t min, uint32_t max) 65 | { 66 | uint64_t a; 67 | 68 | assert (rand != NULL); 69 | 70 | a = mt19937_genrand_uint32 (rand); 71 | a = (a * (max - min)) / 0xffffffff + min; 72 | 73 | return (uint32_t) a; 74 | } 75 | 76 | #define DOUBLE_TRANSFORM 2.3283064365386962890625e-10 77 | double 78 | snippets_rand_double (SnippetsRand * rand) 79 | { 80 | double a; 81 | 82 | assert (rand != NULL); 83 | 84 | a = mt19937_genrand_uint32 (rand) * DOUBLE_TRANSFORM; 85 | a = (a + mt19937_genrand_uint32 (rand)) * DOUBLE_TRANSFORM; 86 | 87 | /* a >= 1.0 might happen due to rare rounding errors */ 88 | return (a >= 1.0) ? snippets_rand_double (rand) : a; 89 | } 90 | 91 | double 92 | snippets_rand_double_range (SnippetsRand * rand, double min, double max) 93 | { 94 | assert (rand != NULL); 95 | 96 | return snippets_rand_double (rand) * (max - min) + min; 97 | } 98 | -------------------------------------------------------------------------------- /snippets/rand.h: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifndef __SNIPPETS_RAND_H__ 21 | #define __SNIPPETS_RAND_H__ 22 | 23 | #include 24 | 25 | SNIPPETS_BEGIN_DECLS 26 | 27 | typedef struct _SnippetsRand SnippetsRand; 28 | 29 | SnippetsRand * snippets_rand_new (uint32_t seed); 30 | void snippets_rand_free (SnippetsRand *rand); 31 | 32 | uint32_t snippets_rand_uint32 (SnippetsRand *rand); 33 | uint32_t snippets_rand_uint32_range (SnippetsRand *rand, uint32_t min, uint32_t max); 34 | double snippets_rand_double (SnippetsRand *rand); 35 | double snippets_rand_double_range (SnippetsRand *rand, double min, double max); 36 | 37 | SNIPPETS_END_DECLS 38 | 39 | #endif /* __SNIPPETS_RAND_H__ */ 40 | -------------------------------------------------------------------------------- /snippets/skiplist.c: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifdef HAVE_CONFIG_H 21 | #include "config.h" 22 | #endif 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | #define MAX_LEVELS 32 34 | 35 | struct _SnippetsSkipList 36 | { 37 | SnippetsSkipListNode *head, *tail; 38 | size_t length; 39 | int pointer; 40 | 41 | unsigned int max_level; 42 | uint32_t p; /* p * 0xffffffff */ 43 | 44 | SnippetsRand *rand; 45 | 46 | size_t data_size; 47 | SnippetsCompareFunction compare_func; 48 | SnippetsCopyToFunction copy_func; 49 | SnippetsFreeFunction free_func; 50 | 51 | void *user_data; 52 | SnippetsCopyFunction user_data_copy; 53 | SnippetsFreeFunction user_data_free; 54 | }; 55 | 56 | struct _SnippetsSkipListNode 57 | { 58 | SnippetsSkipList *list; 59 | SnippetsSkipListNode *prev, *next; 60 | unsigned int level; 61 | SnippetsSkipListNode **skip_links; /* level > 1 */ 62 | void *data; 63 | }; 64 | 65 | #define STRUCT_ALIGNMENT (2 * sizeof (size_t)) 66 | #define STRUCT_ALIGN(offset) \ 67 | ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT) 68 | 69 | static unsigned int 70 | snippets_skip_list_get_random_level (SnippetsRand * rand, 71 | unsigned int max_level, uint32_t p) 72 | { 73 | unsigned int level = 1; 74 | uint32_t r; 75 | 76 | while ((r = snippets_rand_uint32 (rand)) <= p && level < max_level) 77 | level++; 78 | 79 | return level; 80 | } 81 | 82 | static SnippetsSkipListNode * 83 | snippets_skip_list_node_new (SnippetsSkipList * list, size_t data_size, 84 | SnippetsCopyToFunction copy_func, void *data, int level) 85 | { 86 | SnippetsSkipListNode *node; 87 | 88 | if (!list->pointer) { 89 | node = 90 | calloc (STRUCT_ALIGN (sizeof (SnippetsSkipListNode)) + 91 | STRUCT_ALIGN ((level - 1) * sizeof (SnippetsSkipListNode *)) + 92 | data_size, 1); 93 | node->skip_links = 94 | (SnippetsSkipListNode **) (void *) (((uint8_t *) node) + 95 | STRUCT_ALIGN (sizeof (SnippetsSkipListNode))); 96 | node->data = 97 | ((uint8_t *) node) + STRUCT_ALIGN (sizeof (SnippetsSkipListNode)) + 98 | STRUCT_ALIGN ((level - 1) * sizeof (SnippetsSkipListNode *)); 99 | 100 | if (data && copy_func) 101 | copy_func (node->data, data); 102 | else if (data) 103 | memcpy (node->data, data, data_size); 104 | } else { 105 | node = 106 | calloc (STRUCT_ALIGN (sizeof (SnippetsSkipListNode)) + (level - 107 | 1) * sizeof (SnippetsSkipListNode *), 1); 108 | node->skip_links = 109 | (SnippetsSkipListNode **) (void *) (((uint8_t *) node) + 110 | STRUCT_ALIGN (sizeof (SnippetsSkipListNode))); 111 | if (copy_func) 112 | copy_func (&node->data, data); 113 | else 114 | node->data = data; 115 | } 116 | node->list = list; 117 | node->level = level; 118 | 119 | return node; 120 | } 121 | 122 | static void 123 | snippets_skip_list_node_free (SnippetsSkipListNode * node, 124 | SnippetsFreeFunction free_func) 125 | { 126 | if (free_func && node->data) 127 | free_func (node->data); 128 | free (node); 129 | } 130 | 131 | SnippetsSkipList * 132 | snippets_skip_list_new (unsigned int max_level, double p, size_t data_size, 133 | SnippetsCopyToFunction copy_func, SnippetsFreeFunction free_func, 134 | SnippetsCompareFunction compare_func, void *user_data, 135 | SnippetsCopyFunction user_data_copy, SnippetsFreeFunction user_data_free) 136 | { 137 | SnippetsSkipList *list; 138 | 139 | assert (max_level >= 2 && max_level <= MAX_LEVELS); 140 | assert (data_size != 0); 141 | assert (p > 0 && p < 1.0); 142 | assert (compare_func != NULL); 143 | 144 | list = calloc (sizeof (SnippetsSkipList), 1); 145 | 146 | list->max_level = max_level; 147 | list->p = 0xffffffff * p; 148 | list->data_size = data_size; 149 | list->copy_func = copy_func; 150 | list->free_func = free_func; 151 | list->compare_func = compare_func; 152 | list->pointer = FALSE; 153 | 154 | list->user_data = user_data; 155 | list->user_data_copy = user_data_copy; 156 | list->user_data_free = user_data_free; 157 | 158 | list->rand = snippets_rand_new (time (0)); 159 | 160 | list->head = 161 | snippets_skip_list_node_new (list, list->data_size, NULL, NULL, 162 | max_level); 163 | 164 | return list; 165 | } 166 | 167 | SnippetsSkipList * 168 | snippets_skip_list_new_pointer (unsigned int max_level, double p, 169 | SnippetsCopyToFunction copy_func, SnippetsFreeFunction free_func, 170 | SnippetsCompareFunction compare_func, void *user_data, 171 | SnippetsCopyFunction user_data_copy, SnippetsFreeFunction user_data_free) 172 | { 173 | SnippetsSkipList *list = calloc (sizeof (SnippetsSkipList), 1); 174 | 175 | assert (max_level >= 2 && max_level <= MAX_LEVELS); 176 | assert (p > 0 && p < 1.0); 177 | assert (compare_func != NULL); 178 | 179 | list->max_level = max_level; 180 | list->p = 0xffffffff * p; 181 | list->data_size = 0; 182 | list->copy_func = copy_func; 183 | list->free_func = free_func; 184 | list->compare_func = compare_func; 185 | list->pointer = TRUE; 186 | 187 | list->user_data = user_data; 188 | list->user_data_copy = user_data_copy; 189 | list->user_data_free = user_data_free; 190 | 191 | list->rand = snippets_rand_new (time (0)); 192 | 193 | list->head = 194 | snippets_skip_list_node_new (list, list->data_size, NULL, NULL, 195 | max_level); 196 | 197 | return list; 198 | } 199 | 200 | void 201 | snippets_skip_list_free (SnippetsSkipList * list) 202 | { 203 | SnippetsSkipListNode *l, *m; 204 | 205 | assert (list != NULL); 206 | 207 | l = list->head; 208 | while (l) { 209 | m = l; 210 | l = l->next; 211 | snippets_skip_list_node_free (m, list->free_func); 212 | } 213 | snippets_rand_free (list->rand); 214 | 215 | if (list->user_data && list->user_data_free) 216 | list->user_data_free (list->user_data); 217 | 218 | free (list); 219 | } 220 | 221 | SnippetsSkipList * 222 | snippets_skip_list_copy (const SnippetsSkipList * list) 223 | { 224 | SnippetsSkipList *copy; 225 | SnippetsSkipListNode *l; 226 | 227 | assert (list != NULL); 228 | 229 | copy = calloc (sizeof (SnippetsSkipList), 1); 230 | 231 | copy->max_level = list->max_level; 232 | copy->p = list->p; 233 | copy->data_size = list->data_size; 234 | copy->copy_func = list->copy_func; 235 | copy->free_func = list->free_func; 236 | copy->compare_func = list->compare_func; 237 | copy->pointer = list->pointer; 238 | 239 | if (list->user_data && list->user_data_copy) { 240 | copy->user_data = list->user_data_copy (list->user_data); 241 | copy->user_data_copy = list->user_data_copy; 242 | copy->user_data_free = list->user_data_free; 243 | } 244 | 245 | copy->rand = snippets_rand_new (time (0)); 246 | 247 | /* TODO: Could build perfect skip list here by 248 | * choosing the optimal levels 249 | */ 250 | copy->head = 251 | snippets_skip_list_node_new (copy, copy->data_size, NULL, NULL, 252 | copy->max_level); 253 | for (l = list->head->next; l; l = l->next) 254 | snippets_skip_list_insert (copy, l->data); 255 | 256 | return copy; 257 | } 258 | 259 | static int 260 | snippets_skip_list_find_internal (SnippetsSkipList * list, const void *data, 261 | SnippetsSkipListNode * nodes[MAX_LEVELS]) 262 | { 263 | SnippetsSkipListNode *l; 264 | int i, tmp, res = -1; 265 | 266 | /* Nodes must be emptied! */ 267 | 268 | l = list->head; 269 | 270 | /* Look at level max-1 to 1 */ 271 | for (i = list->max_level - 2; i >= 0; i--) { 272 | while (l->skip_links[i] 273 | && (tmp = list->compare_func (l->skip_links[i]->data, data, 274 | list->user_data)) < 0) { 275 | l = l->skip_links[i]; 276 | res = tmp; 277 | } 278 | nodes[i + 1] = l; 279 | } 280 | 281 | /* level 0 */ 282 | while (l->next 283 | && (tmp = 284 | list->compare_func (l->next->data, data, list->user_data)) <= 0) { 285 | l = l->next; 286 | res = tmp; 287 | } 288 | nodes[0] = l; 289 | 290 | return (l == list->head) ? -1 : res; 291 | } 292 | 293 | SnippetsSkipListNode * 294 | snippets_skip_list_insert (SnippetsSkipList * list, void *data) 295 | { 296 | SnippetsSkipListNode *nodes[MAX_LEVELS] = { NULL, }; 297 | int i, res, level; 298 | SnippetsSkipListNode *node; 299 | 300 | assert (list != NULL); 301 | assert (data != NULL); 302 | 303 | res = snippets_skip_list_find_internal (list, data, nodes); 304 | if (res == 0) 305 | return nodes[0]; 306 | 307 | level = 308 | snippets_skip_list_get_random_level (list->rand, list->max_level, 309 | list->p); 310 | node = 311 | snippets_skip_list_node_new (list, list->data_size, list->copy_func, data, 312 | level); 313 | 314 | node->prev = nodes[0]; 315 | node->next = nodes[0]->next; 316 | if (nodes[0]->next) 317 | nodes[0]->next->prev = node; 318 | nodes[0]->next = node; 319 | 320 | if (!node->next) 321 | list->tail = node; 322 | 323 | for (i = 0; i < level - 1; i++) { 324 | node->skip_links[i] = nodes[i + 1]->skip_links[i]; 325 | nodes[i + 1]->skip_links[i] = node; 326 | } 327 | 328 | list->length++; 329 | 330 | return node; 331 | } 332 | 333 | void 334 | snippets_skip_list_remove (SnippetsSkipList * list, SnippetsSkipListNode * node) 335 | { 336 | SnippetsSkipListNode *nodes[MAX_LEVELS] = { NULL, }; 337 | SnippetsSkipListNode *n; 338 | int i, j; 339 | 340 | assert (list != NULL); 341 | assert (node != NULL); 342 | assert (node->list == list); 343 | 344 | /* Expected distance to the previous node of level at least node->level */ 345 | i = pow (1.0 / snippets_skip_list_probability (list), node->level - 1); 346 | /* Expected worst case search path length from head to this node */ 347 | j = log (list->length) / log (1.0 / snippets_skip_list_probability (list)) + 348 | 1.0 / (1.0 - snippets_skip_list_probability (list)); 349 | /* If a search and remove is probably faster than stepping back 350 | * do this instead */ 351 | if (j < i) { 352 | snippets_skip_list_remove_value (list, node->data); 353 | return; 354 | } 355 | 356 | nodes[0] = node->prev; 357 | n = node->prev; 358 | 359 | if (node == list->tail) 360 | list->tail = n; 361 | 362 | i = 1; 363 | while (i < node->level) { 364 | assert (n); 365 | 366 | if (n->level > i) { 367 | for (j = i; j < n->level && j < node->level; j++) 368 | nodes[i++] = n; 369 | } 370 | n = n->prev; 371 | } 372 | 373 | nodes[0]->next = node->next; 374 | if (node->next) 375 | node->next->prev = nodes[0]; 376 | 377 | for (i = 0; i + 1 < node->level; i++) { 378 | assert (nodes[i + 1]->skip_links[i] == node); 379 | nodes[i + 1]->skip_links[i] = node->skip_links[i]; 380 | } 381 | 382 | list->length--; 383 | snippets_skip_list_node_free (node, list->free_func); 384 | } 385 | 386 | void 387 | snippets_skip_list_remove_value (SnippetsSkipList * list, const void *data) 388 | { 389 | SnippetsSkipListNode *nodes[MAX_LEVELS] = { NULL, }; 390 | int i, res; 391 | 392 | assert (list != NULL); 393 | assert (data != NULL); 394 | 395 | res = snippets_skip_list_find_internal (list, data, nodes); 396 | if (res != 0) 397 | return; 398 | assert (nodes[0] != NULL); 399 | 400 | if (nodes[0] == list->tail) 401 | list->tail = nodes[0]->prev; 402 | 403 | nodes[0]->prev->next = nodes[0]->next; 404 | if (nodes[0]->next) 405 | nodes[0]->next->prev = nodes[0]->prev; 406 | 407 | for (i = 0; i + 1 < nodes[0]->level; i++) { 408 | assert (nodes[i + 1]->skip_links[i] == nodes[0]); 409 | nodes[i + 1]->skip_links[i] = nodes[0]->skip_links[i]; 410 | } 411 | 412 | list->length--; 413 | snippets_skip_list_node_free (nodes[0], list->free_func); 414 | } 415 | 416 | SnippetsSkipListNode * 417 | snippets_skip_list_find (SnippetsSkipList * list, const void *data, int exact) 418 | { 419 | SnippetsSkipListNode *nodes[MAX_LEVELS] = { NULL, }; 420 | int res; 421 | 422 | assert (list != NULL); 423 | assert (data != NULL); 424 | 425 | res = snippets_skip_list_find_internal (list, data, nodes); 426 | 427 | if (exact) 428 | return (res == 0) ? nodes[0] : NULL; 429 | return (nodes[0] == list->head) ? NULL : nodes[0]; 430 | } 431 | 432 | SnippetsSkipListNode * 433 | snippets_skip_list_head (SnippetsSkipList * list) 434 | { 435 | assert (list != NULL); 436 | return list->head->next; 437 | } 438 | 439 | SnippetsSkipListNode * 440 | snippets_skip_list_tail (SnippetsSkipList * list) 441 | { 442 | assert (list != NULL); 443 | return list->tail; 444 | } 445 | 446 | size_t 447 | snippets_skip_list_length (SnippetsSkipList * list) 448 | { 449 | assert (list != NULL); 450 | return list->length; 451 | } 452 | 453 | SnippetsSkipListNode * 454 | snippets_skip_list_node_next (SnippetsSkipListNode * node) 455 | { 456 | assert (node != NULL); 457 | return node->next; 458 | } 459 | 460 | SnippetsSkipListNode * 461 | snippets_skip_list_node_prev (SnippetsSkipListNode * node) 462 | { 463 | assert (node != NULL); 464 | return (node->prev == node->list->head) ? NULL : node->prev; 465 | } 466 | 467 | void * 468 | snippets_skip_list_node_get_ (SnippetsSkipListNode * node) 469 | { 470 | assert (node != NULL); 471 | 472 | if (node->list->pointer) 473 | return &node->data; 474 | else 475 | return node->data; 476 | } 477 | 478 | unsigned int 479 | snippets_skip_list_max_level (SnippetsSkipList * list) 480 | { 481 | assert (list != NULL); 482 | 483 | return list->max_level; 484 | } 485 | 486 | double 487 | snippets_skip_list_probability (SnippetsSkipList * list) 488 | { 489 | assert (list != NULL); 490 | 491 | return ((double) list->p) / ((double) 0xffffffff); 492 | } 493 | -------------------------------------------------------------------------------- /snippets/skiplist.h: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifndef __SNIPPETS_SKIP_LIST_H__ 21 | #define __SNIPPETS_SKIP_LIST_H__ 22 | 23 | #include 24 | 25 | SNIPPETS_BEGIN_DECLS 26 | 27 | typedef struct _SnippetsSkipList SnippetsSkipList; 28 | typedef struct _SnippetsSkipListNode SnippetsSkipListNode; 29 | 30 | SnippetsSkipList * snippets_skip_list_new (unsigned int max_level, double p, size_t data_size, SnippetsCopyToFunction copy_func, SnippetsFreeFunction free_func, SnippetsCompareFunction compare_func, void *user_data, SnippetsCopyFunction user_data_copy, SnippetsFreeFunction user_data_free); 31 | SnippetsSkipList * snippets_skip_list_new_pointer (unsigned int max_level, double p, SnippetsCopyToFunction copy_func, SnippetsFreeFunction free_func, SnippetsCompareFunction compare_func, void *user_data, SnippetsCopyFunction user_data_copy, SnippetsFreeFunction user_data_free); 32 | void snippets_skip_list_free (SnippetsSkipList *list); 33 | 34 | SnippetsSkipList * snippets_skip_list_copy (const SnippetsSkipList *list); 35 | 36 | SnippetsSkipListNode * snippets_skip_list_insert (SnippetsSkipList *list, void *data); 37 | void snippets_skip_list_remove (SnippetsSkipList *list, SnippetsSkipListNode *node); 38 | void snippets_skip_list_remove_value (SnippetsSkipList *list, const void *data); 39 | SnippetsSkipListNode * snippets_skip_list_find (SnippetsSkipList *list, const void *data, int exact); 40 | 41 | SnippetsSkipListNode * snippets_skip_list_head (SnippetsSkipList *list); 42 | SnippetsSkipListNode * snippets_skip_list_tail (SnippetsSkipList *list); 43 | 44 | size_t snippets_skip_list_length (SnippetsSkipList *list); 45 | unsigned int snippets_skip_list_max_level (SnippetsSkipList *list); 46 | double snippets_skip_list_probability (SnippetsSkipList *list); 47 | 48 | SnippetsSkipListNode * snippets_skip_list_node_next (SnippetsSkipListNode *node); 49 | SnippetsSkipListNode * snippets_skip_list_node_prev (SnippetsSkipListNode *node); 50 | 51 | #define snippets_skip_list_node_get(node, __type) \ 52 | ((__type *) snippets_skip_list_node_get_ (node)); 53 | void * snippets_skip_list_node_get_ (SnippetsSkipListNode *node); 54 | 55 | SNIPPETS_END_DECLS 56 | 57 | #endif /* __SNIPPETS_SKIP_LIST_H__ */ 58 | -------------------------------------------------------------------------------- /snippets/utils.h: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifndef __UTILS_H__ 21 | #define __UTILS_H__ 22 | 23 | #include 24 | 25 | #include 26 | 27 | #ifndef NULL 28 | #define NULL ((void *) 0) 29 | #endif 30 | 31 | #ifndef FALSE 32 | #define FALSE (0) 33 | #endif 34 | 35 | #ifndef TRUE 36 | #define TRUE (!FALSE) 37 | #endif 38 | 39 | #ifdef __cplusplus 40 | # define SNIPPETS_BEGIN_DECLS extern "C" { 41 | # define SNIPPETS_END_DECLS } 42 | #else 43 | # define SNIPPETS_BEGIN_DECLS 44 | # define SNIPPETS_END_DECLS 45 | #endif 46 | 47 | SNIPPETS_BEGIN_DECLS 48 | 49 | typedef void * (*SnippetsCopyFunction) (const void *o); 50 | typedef void (*SnippetsCopyToFunction) (void *dest, const void *src); 51 | typedef void (*SnippetsFreeFunction) (void *o); 52 | typedef int (*SnippetsCompareFunction) (const void *a, const void *b, void *user_data); 53 | 54 | SNIPPETS_END_DECLS 55 | 56 | #endif /* __UTILS_H__ */ 57 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | TESTS = \ 2 | test-fnv \ 3 | test-rand \ 4 | test-linkedlist \ 5 | test-skiplist \ 6 | test-bloomfilter 7 | 8 | noinst_PROGRAMS = $(TESTS) 9 | 10 | TESTS_CFLAGS = \ 11 | $(CHECK_CFLAGS) \ 12 | -I$(top_srcdir) \ 13 | -I$(top_builddir) 14 | TESTS_LDADD = \ 15 | $(CHECK_LIBS) \ 16 | $(top_builddir)/snippets/libsnippets.la 17 | 18 | test_fnv_SOURCES = fnv.c 19 | test_fnv_CFLAGS = $(TESTS_CFLAGS) 20 | test_fnv_LDADD = $(TESTS_LDADD) 21 | 22 | test_rand_SOURCES = rand.c 23 | test_rand_CFLAGS = $(TESTS_CFLAGS) 24 | test_rand_LDADD = $(TESTS_LDADD) 25 | 26 | test_linkedlist_SOURCES = linkedlist.c 27 | test_linkedlist_CFLAGS = $(TESTS_CFLAGS) 28 | test_linkedlist_LDADD = $(TESTS_LDADD) 29 | 30 | test_skiplist_SOURCES = skiplist.c 31 | test_skiplist_CFLAGS = $(TESTS_CFLAGS) 32 | test_skiplist_LDADD = $(TESTS_LDADD) 33 | 34 | test_bloomfilter_SOURCES = bloomfilter.c 35 | test_bloomfilter_CFLAGS = $(TESTS_CFLAGS) 36 | test_bloomfilter_LDADD = $(TESTS_LDADD) 37 | 38 | include $(top_srcdir)/check.mk 39 | 40 | -------------------------------------------------------------------------------- /tests/bloomfilter.c: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifdef HAVE_CONFIG_H 21 | #include "config.h" 22 | #endif 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | typedef struct _TestData TestData; 31 | struct _TestData 32 | { 33 | uint32_t data[16]; 34 | }; 35 | 36 | static int 37 | compare_data (const void *o1, const void *o2, void *user_data) 38 | { 39 | int i; 40 | const TestData *a = o1; 41 | const TestData *b = o2; 42 | 43 | for (i = 0; i < 16; i++) { 44 | if (a->data[i] < b->data[i]) 45 | return -1; 46 | else if (a->data[i] > b->data[i]) 47 | return 1; 48 | } 49 | 50 | return 0; 51 | } 52 | 53 | START_TEST (test_general) 54 | { 55 | SnippetsBloomFilter *filter = 56 | snippets_bloom_filter_new (100 * 1000 * 8, 16, 64); 57 | SnippetsRand *rand = snippets_rand_new (0xdeadbeef); 58 | SnippetsSkipList *list = 59 | snippets_skip_list_new (8, 0.25, sizeof (TestData), NULL, NULL, 60 | compare_data, NULL, NULL, NULL); 61 | const int N = 10000; 62 | TestData data, *data2; 63 | int i, j; 64 | SnippetsSkipListNode *n; 65 | 66 | fail_unless (snippets_bloom_filter_n_hash_functions (filter) == 16); 67 | fail_unless (snippets_bloom_filter_size (filter) == 100 * 1000 * 8); 68 | fail_unless (snippets_bloom_filter_n_elements (filter) == 0); 69 | fail_unless (snippets_bloom_filter_false_positive_rate (filter) == 0); 70 | 71 | for (i = 0; i < N; i++) { 72 | for (j = 0; j < 16; j++) 73 | data.data[j] = snippets_rand_uint32 (rand); 74 | 75 | snippets_skip_list_insert (list, &data); 76 | } 77 | 78 | /* There are no false positives in this example! */ 79 | for (n = snippets_skip_list_head (list); n; 80 | n = snippets_skip_list_node_next (n)) { 81 | data2 = snippets_skip_list_node_get (n, TestData); 82 | fail_if (snippets_bloom_filter_contains (filter, (uint8_t *) data2->data, 83 | sizeof (TestData))); 84 | snippets_bloom_filter_insert (filter, (uint8_t *) data2->data, 85 | sizeof (TestData)); 86 | fail_unless (snippets_bloom_filter_contains (filter, 87 | (uint8_t *) data2->data, sizeof (TestData))); 88 | } 89 | 90 | fail_unless (snippets_bloom_filter_n_elements (filter) == 91 | snippets_skip_list_length (list)); 92 | 93 | snippets_skip_list_free (list); 94 | snippets_rand_free (rand); 95 | snippets_bloom_filter_free (filter); 96 | } 97 | 98 | END_TEST; 99 | 100 | #define CREATE_TEST(filter_size, n_hash_functions, hash_size, elements) \ 101 | START_TEST (test_##filter_size##_##n_hash_functions##_##hash_size##_##elements) \ 102 | { \ 103 | SnippetsBloomFilter *filter = snippets_bloom_filter_new (filter_size, n_hash_functions, hash_size); \ 104 | SnippetsRand *rand = snippets_rand_new (0xdeadbeef); \ 105 | SnippetsSkipList *list = snippets_skip_list_new (8, 0.25, sizeof (TestData), NULL, NULL, compare_data, NULL, NULL, NULL); \ 106 | const int N = elements; \ 107 | const int N2 = 500000; \ 108 | TestData data, *data2; \ 109 | int i, j; \ 110 | SnippetsSkipListNode *n; \ 111 | double false_positives = 0; \ 112 | double max_fp_rate; \ 113 | \ 114 | for (i = 0; i < N; i++) { \ 115 | for (j = 0; j < 16; j++) \ 116 | data.data[j] = snippets_rand_uint32 (rand); \ 117 | \ 118 | snippets_skip_list_insert (list, &data); \ 119 | } \ 120 | \ 121 | for (n = snippets_skip_list_head (list); n; n = snippets_skip_list_node_next (n)) { \ 122 | data2 = snippets_skip_list_node_get (n, TestData); \ 123 | snippets_bloom_filter_insert (filter, (uint8_t *) data2->data, sizeof (TestData)); \ 124 | } \ 125 | \ 126 | fail_unless (snippets_bloom_filter_n_elements (filter) == snippets_skip_list_length (list)); \ 127 | max_fp_rate = snippets_bloom_filter_false_positive_rate (filter); \ 128 | \ 129 | for (n = snippets_skip_list_head (list); n; n = snippets_skip_list_node_next (n)) { \ 130 | data2 = snippets_skip_list_node_get (n, TestData); \ 131 | fail_unless (snippets_bloom_filter_contains (filter, (uint8_t *) data2->data, sizeof (TestData))); \ 132 | } \ 133 | \ 134 | for (i = 0; i < N2; i++) { \ 135 | while (TRUE) { \ 136 | for (j = 0; j < 16; j++) \ 137 | data.data[j] = snippets_rand_uint32 (rand); \ 138 | if (snippets_skip_list_find (list, &data, TRUE) == NULL) \ 139 | break; \ 140 | } \ 141 | \ 142 | if (snippets_bloom_filter_contains (filter, (uint8_t *) data.data, sizeof (TestData))) \ 143 | false_positives++; \ 144 | } \ 145 | \ 146 | fail_unless (false_positives / N2 <= max_fp_rate * 1.08, \ 147 | "expected: %lf was: %lf", max_fp_rate * 1.08, \ 148 | false_positives / N2); \ 149 | \ 150 | snippets_skip_list_free (list); \ 151 | snippets_rand_free (rand); \ 152 | snippets_bloom_filter_free (filter); \ 153 | } \ 154 | \ 155 | END_TEST; 156 | 157 | CREATE_TEST (15000, 5, 64, 2000); 158 | CREATE_TEST (15000, 5, 128, 2000); 159 | CREATE_TEST (150000, 11, 128, 10000); 160 | CREATE_TEST (150000, 11, 256, 10000); 161 | CREATE_TEST (150000, 11, 512, 10000); 162 | CREATE_TEST (150000, 11, 1024, 1000); 163 | CREATE_TEST (100000, 70, 1024, 1000); 164 | 165 | START_TEST (test_optimal_n_hash_functions) 166 | { 167 | fail_unless (snippets_bloom_filter_optimal_n_hash_functions (15000, 168 | 2000) == 5); 169 | fail_unless (snippets_bloom_filter_optimal_n_hash_functions (150000, 170 | 10000) == 11); 171 | fail_unless (snippets_bloom_filter_optimal_n_hash_functions (100000, 172 | 1000) == 70); 173 | } 174 | 175 | END_TEST; 176 | 177 | static Suite * 178 | bloomfilter_suite (void) 179 | { 180 | Suite *s = suite_create ("BloomFilter"); 181 | 182 | /* Core test case */ 183 | TCase *tc_general = tcase_create ("general"); 184 | tcase_add_test (tc_general, test_general); 185 | tcase_add_test (tc_general, test_15000_5_64_2000); 186 | tcase_add_test (tc_general, test_15000_5_128_2000); 187 | tcase_add_test (tc_general, test_150000_11_128_10000); 188 | tcase_add_test (tc_general, test_150000_11_256_10000); 189 | tcase_add_test (tc_general, test_150000_11_512_10000); 190 | tcase_add_test (tc_general, test_150000_11_1024_1000); 191 | tcase_add_test (tc_general, test_100000_70_1024_1000); 192 | tcase_add_test (tc_general, test_optimal_n_hash_functions); 193 | suite_add_tcase (s, tc_general); 194 | 195 | return s; 196 | } 197 | 198 | int 199 | main (void) 200 | { 201 | int number_failed; 202 | Suite *s = bloomfilter_suite (); 203 | SRunner *sr = srunner_create (s); 204 | srunner_run_all (sr, CK_NORMAL); 205 | number_failed = srunner_ntests_failed (sr); 206 | srunner_free (sr); 207 | return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 208 | } 209 | -------------------------------------------------------------------------------- /tests/fnv.c: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifdef HAVE_CONFIG_H 21 | #include "config.h" 22 | #endif 23 | 24 | #include 25 | 26 | #include 27 | 28 | START_TEST (test_1_32) 29 | { 30 | const char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 31 | uint8_t hash[4]; 32 | 33 | snippets_fnv1_32 ((const uint8_t *) str, strlen (str), hash); 34 | fail_unless (hash[0] == 0x94); 35 | fail_unless (hash[1] == 0x41); 36 | fail_unless (hash[2] == 0x79); 37 | fail_unless (hash[3] == 0xf9); 38 | } 39 | 40 | END_TEST; 41 | 42 | START_TEST (test_1a_32) 43 | { 44 | const char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 45 | uint8_t hash[4]; 46 | 47 | snippets_fnv1a_32 ((const uint8_t *) str, strlen (str), hash); 48 | fail_unless (hash[0] == 0x3e); 49 | fail_unless (hash[1] == 0xda); 50 | fail_unless (hash[2] == 0x61); 51 | fail_unless (hash[3] == 0xcd); 52 | } 53 | 54 | END_TEST; 55 | 56 | START_TEST (test_1_64) 57 | { 58 | const char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 59 | uint8_t hash[8]; 60 | 61 | snippets_fnv1_64 ((const uint8_t *) str, strlen (str), hash); 62 | fail_unless (hash[0] == 0x94); 63 | fail_unless (hash[1] == 0xd9); 64 | fail_unless (hash[2] == 0x0d); 65 | fail_unless (hash[3] == 0x92); 66 | fail_unless (hash[4] == 0x6c); 67 | fail_unless (hash[5] == 0x9d); 68 | fail_unless (hash[6] == 0xe7); 69 | fail_unless (hash[7] == 0x79); 70 | } 71 | 72 | END_TEST; 73 | 74 | START_TEST (test_1a_64) 75 | { 76 | const char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 77 | uint8_t hash[8]; 78 | 79 | snippets_fnv1a_64 ((const uint8_t *) str, strlen (str), hash); 80 | fail_unless (hash[0] == 0x37); 81 | fail_unless (hash[1] == 0x22); 82 | fail_unless (hash[2] == 0xd9); 83 | fail_unless (hash[3] == 0x2f); 84 | fail_unless (hash[4] == 0x94); 85 | fail_unless (hash[5] == 0xba); 86 | fail_unless (hash[6] == 0x1e); 87 | fail_unless (hash[7] == 0x8d); 88 | } 89 | 90 | END_TEST; 91 | 92 | START_TEST (test_1_128) 93 | { 94 | const char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 95 | uint8_t hash[16]; 96 | 97 | snippets_fnv1_128 ((const uint8_t *) str, strlen (str), hash); 98 | fail_unless (hash[0] == 0xa5); 99 | fail_unless (hash[1] == 0xfe); 100 | fail_unless (hash[2] == 0xd2); 101 | fail_unless (hash[3] == 0x7e); 102 | fail_unless (hash[4] == 0x13); 103 | fail_unless (hash[5] == 0x09); 104 | fail_unless (hash[6] == 0x0b); 105 | fail_unless (hash[7] == 0x4e); 106 | fail_unless (hash[8] == 0x6f); 107 | fail_unless (hash[9] == 0x62); 108 | fail_unless (hash[10] == 0x3a); 109 | fail_unless (hash[11] == 0xd0); 110 | fail_unless (hash[12] == 0x29); 111 | fail_unless (hash[13] == 0xaf); 112 | fail_unless (hash[14] == 0x7d); 113 | fail_unless (hash[15] == 0xd9); 114 | } 115 | 116 | END_TEST; 117 | 118 | START_TEST (test_1a_128) 119 | { 120 | const char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 121 | uint8_t hash[16]; 122 | 123 | snippets_fnv1a_128 ((const uint8_t *) str, strlen (str), hash); 124 | fail_unless (hash[0] == 0x6f); 125 | fail_unless (hash[1] == 0x36); 126 | fail_unless (hash[2] == 0x56); 127 | fail_unless (hash[3] == 0xc6); 128 | fail_unless (hash[4] == 0x0d); 129 | fail_unless (hash[5] == 0xf8); 130 | fail_unless (hash[6] == 0x43); 131 | fail_unless (hash[7] == 0x48); 132 | fail_unless (hash[8] == 0x2c); 133 | fail_unless (hash[9] == 0xaf); 134 | fail_unless (hash[10] == 0xae); 135 | fail_unless (hash[11] == 0x3d); 136 | fail_unless (hash[12] == 0x95); 137 | fail_unless (hash[13] == 0x63); 138 | fail_unless (hash[14] == 0x4d); 139 | fail_unless (hash[15] == 0xad); 140 | } 141 | 142 | END_TEST; 143 | 144 | START_TEST (test_1_256) 145 | { 146 | const char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 147 | uint8_t hash[32]; 148 | 149 | snippets_fnv1_256 ((const uint8_t *) str, strlen (str), hash); 150 | fail_unless (hash[0] == 0x73); 151 | fail_unless (hash[1] == 0x5a); 152 | fail_unless (hash[2] == 0x7c); 153 | fail_unless (hash[3] == 0x96); 154 | fail_unless (hash[4] == 0x69); 155 | fail_unless (hash[5] == 0x33); 156 | fail_unless (hash[6] == 0x79); 157 | fail_unless (hash[7] == 0x25); 158 | fail_unless (hash[8] == 0xdd); 159 | fail_unless (hash[9] == 0x4a); 160 | fail_unless (hash[10] == 0xa3); 161 | fail_unless (hash[11] == 0xbc); 162 | fail_unless (hash[12] == 0x1f); 163 | fail_unless (hash[13] == 0xae); 164 | fail_unless (hash[14] == 0xde); 165 | fail_unless (hash[15] == 0xc3); 166 | fail_unless (hash[16] == 0x3d); 167 | fail_unless (hash[17] == 0x6b); 168 | fail_unless (hash[18] == 0x2a); 169 | fail_unless (hash[19] == 0xe9); 170 | fail_unless (hash[20] == 0xb0); 171 | fail_unless (hash[21] == 0x28); 172 | fail_unless (hash[22] == 0x71); 173 | fail_unless (hash[23] == 0x6d); 174 | fail_unless (hash[24] == 0xe7); 175 | fail_unless (hash[25] == 0x65); 176 | fail_unless (hash[26] == 0x2a); 177 | fail_unless (hash[27] == 0x29); 178 | fail_unless (hash[28] == 0xbf); 179 | fail_unless (hash[29] == 0xb6); 180 | fail_unless (hash[30] == 0x99); 181 | fail_unless (hash[31] == 0x19); 182 | } 183 | 184 | END_TEST; 185 | 186 | START_TEST (test_1a_256) 187 | { 188 | const char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 189 | uint8_t hash[32]; 190 | 191 | snippets_fnv1a_256 ((const uint8_t *) str, strlen (str), hash); 192 | fail_unless (hash[0] == 0xc2); 193 | fail_unless (hash[1] == 0x5f); 194 | fail_unless (hash[2] == 0xb3); 195 | fail_unless (hash[3] == 0xfd); 196 | fail_unless (hash[4] == 0x87); 197 | fail_unless (hash[5] == 0xc6); 198 | fail_unless (hash[6] == 0x79); 199 | fail_unless (hash[7] == 0xaf); 200 | fail_unless (hash[8] == 0x4b); 201 | fail_unless (hash[9] == 0x26); 202 | fail_unless (hash[10] == 0x16); 203 | fail_unless (hash[11] == 0x29); 204 | fail_unless (hash[12] == 0x02); 205 | fail_unless (hash[13] == 0xc6); 206 | fail_unless (hash[14] == 0xef); 207 | fail_unless (hash[15] == 0x4f); 208 | fail_unless (hash[16] == 0x3d); 209 | fail_unless (hash[17] == 0x23); 210 | fail_unless (hash[18] == 0x65); 211 | fail_unless (hash[19] == 0x92); 212 | fail_unless (hash[20] == 0x57); 213 | fail_unless (hash[21] == 0x71); 214 | fail_unless (hash[22] == 0xab); 215 | fail_unless (hash[23] == 0x30); 216 | fail_unless (hash[24] == 0xe3); 217 | fail_unless (hash[25] == 0x73); 218 | fail_unless (hash[26] == 0x9f); 219 | fail_unless (hash[27] == 0x47); 220 | fail_unless (hash[28] == 0x42); 221 | fail_unless (hash[29] == 0x53); 222 | fail_unless (hash[30] == 0x9b); 223 | fail_unless (hash[31] == 0x2d); 224 | } 225 | 226 | END_TEST; 227 | 228 | START_TEST (test_1_512) 229 | { 230 | const char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 231 | uint8_t hash[64]; 232 | 233 | snippets_fnv1_512 ((const uint8_t *) str, strlen (str), hash); 234 | fail_unless (hash[0] == 0x31); 235 | fail_unless (hash[1] == 0xd6); 236 | fail_unless (hash[2] == 0x3b); 237 | fail_unless (hash[3] == 0x43); 238 | fail_unless (hash[4] == 0x3c); 239 | fail_unless (hash[5] == 0x2e); 240 | fail_unless (hash[6] == 0x8d); 241 | fail_unless (hash[7] == 0xb9); 242 | fail_unless (hash[8] == 0x43); 243 | fail_unless (hash[9] == 0x7b); 244 | fail_unless (hash[10] == 0xb7); 245 | fail_unless (hash[11] == 0x96); 246 | fail_unless (hash[12] == 0x95); 247 | fail_unless (hash[13] == 0xd1); 248 | fail_unless (hash[14] == 0x95); 249 | fail_unless (hash[15] == 0xb0); 250 | fail_unless (hash[16] == 0xc9); 251 | fail_unless (hash[17] == 0x91); 252 | fail_unless (hash[18] == 0x38); 253 | fail_unless (hash[19] == 0xaf); 254 | fail_unless (hash[20] == 0xe4); 255 | fail_unless (hash[21] == 0x43); 256 | fail_unless (hash[22] == 0xa1); 257 | fail_unless (hash[23] == 0x8e); 258 | fail_unless (hash[24] == 0xbc); 259 | fail_unless (hash[25] == 0x7b); 260 | fail_unless (hash[26] == 0xf3); 261 | fail_unless (hash[27] == 0x79); 262 | fail_unless (hash[28] == 0xee); 263 | fail_unless (hash[29] == 0x8f); 264 | fail_unless (hash[30] == 0xf4); 265 | fail_unless (hash[31] == 0xe6); 266 | fail_unless (hash[32] == 0xbb); 267 | fail_unless (hash[33] == 0xe8); 268 | fail_unless (hash[34] == 0xbf); 269 | fail_unless (hash[35] == 0xcf); 270 | fail_unless (hash[36] == 0xc9); 271 | fail_unless (hash[37] == 0x25); 272 | fail_unless (hash[38] == 0xfa); 273 | fail_unless (hash[39] == 0xd7); 274 | fail_unless (hash[40] == 0x5f); 275 | fail_unless (hash[41] == 0x3d); 276 | fail_unless (hash[42] == 0x2b); 277 | fail_unless (hash[43] == 0xff); 278 | fail_unless (hash[44] == 0x43); 279 | fail_unless (hash[45] == 0x28); 280 | fail_unless (hash[46] == 0xcb); 281 | fail_unless (hash[47] == 0x72); 282 | fail_unless (hash[48] == 0x97); 283 | fail_unless (hash[49] == 0xba); 284 | fail_unless (hash[50] == 0xdc); 285 | fail_unless (hash[51] == 0x4f); 286 | fail_unless (hash[52] == 0x3b); 287 | fail_unless (hash[53] == 0x4a); 288 | fail_unless (hash[54] == 0x60); 289 | fail_unless (hash[55] == 0xe3); 290 | fail_unless (hash[56] == 0x83); 291 | fail_unless (hash[57] == 0xdb); 292 | fail_unless (hash[58] == 0x49); 293 | fail_unless (hash[59] == 0xfe); 294 | fail_unless (hash[60] == 0xab); 295 | fail_unless (hash[61] == 0xc5); 296 | fail_unless (hash[62] == 0x6c); 297 | fail_unless (hash[63] == 0x51); 298 | } 299 | 300 | END_TEST; 301 | 302 | START_TEST (test_1a_512) 303 | { 304 | const char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 305 | uint8_t hash[64]; 306 | 307 | snippets_fnv1a_512 ((const uint8_t *) str, strlen (str), hash); 308 | fail_unless (hash[0] == 0x13); 309 | fail_unless (hash[1] == 0x92); 310 | fail_unless (hash[2] == 0x20); 311 | fail_unless (hash[3] == 0xfc); 312 | fail_unless (hash[4] == 0x4c); 313 | fail_unless (hash[5] == 0xd6); 314 | fail_unless (hash[6] == 0x48); 315 | fail_unless (hash[7] == 0x3d); 316 | fail_unless (hash[8] == 0xd3); 317 | fail_unless (hash[9] == 0x15); 318 | fail_unless (hash[10] == 0x39); 319 | fail_unless (hash[11] == 0x42); 320 | fail_unless (hash[12] == 0xb7); 321 | fail_unless (hash[13] == 0x1a); 322 | fail_unless (hash[14] == 0x92); 323 | fail_unless (hash[15] == 0x0d); 324 | fail_unless (hash[16] == 0xb5); 325 | fail_unless (hash[17] == 0x63); 326 | fail_unless (hash[18] == 0xe3); 327 | fail_unless (hash[19] == 0x0e); 328 | fail_unless (hash[20] == 0xca); 329 | fail_unless (hash[21] == 0x43); 330 | fail_unless (hash[22] == 0xa1); 331 | fail_unless (hash[23] == 0x8e); 332 | fail_unless (hash[24] == 0xbc); 333 | fail_unless (hash[25] == 0x56); 334 | fail_unless (hash[26] == 0xc5); 335 | fail_unless (hash[27] == 0x39); 336 | fail_unless (hash[28] == 0x75); 337 | fail_unless (hash[29] == 0x3c); 338 | fail_unless (hash[30] == 0x7d); 339 | fail_unless (hash[31] == 0x71); 340 | fail_unless (hash[32] == 0x1d); 341 | fail_unless (hash[33] == 0x74); 342 | fail_unless (hash[34] == 0xd7); 343 | fail_unless (hash[35] == 0x6e); 344 | fail_unless (hash[36] == 0xd2); 345 | fail_unless (hash[37] == 0x15); 346 | fail_unless (hash[38] == 0x9c); 347 | fail_unless (hash[39] == 0x76); 348 | fail_unless (hash[40] == 0xd1); 349 | fail_unless (hash[41] == 0x8f); 350 | fail_unless (hash[42] == 0x91); 351 | fail_unless (hash[43] == 0x30); 352 | fail_unless (hash[44] == 0xf0); 353 | fail_unless (hash[45] == 0xf3); 354 | fail_unless (hash[46] == 0x76); 355 | fail_unless (hash[47] == 0x18); 356 | fail_unless (hash[48] == 0xf1); 357 | fail_unless (hash[49] == 0x29); 358 | fail_unless (hash[50] == 0xb6); 359 | fail_unless (hash[51] == 0x94); 360 | fail_unless (hash[52] == 0x5b); 361 | fail_unless (hash[53] == 0x9f); 362 | fail_unless (hash[54] == 0x82); 363 | fail_unless (hash[55] == 0xef); 364 | fail_unless (hash[56] == 0x26); 365 | fail_unless (hash[57] == 0xba); 366 | fail_unless (hash[58] == 0xcd); 367 | fail_unless (hash[59] == 0xf6); 368 | fail_unless (hash[60] == 0x66); 369 | fail_unless (hash[61] == 0xaa); 370 | fail_unless (hash[62] == 0xc2); 371 | fail_unless (hash[63] == 0x1d); 372 | } 373 | 374 | END_TEST; 375 | 376 | START_TEST (test_1_1024) 377 | { 378 | const char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 379 | uint8_t hash[128]; 380 | 381 | snippets_fnv1_1024 ((const uint8_t *) str, strlen (str), hash); 382 | fail_unless (hash[0] == 0x0c); 383 | fail_unless (hash[1] == 0x3e); 384 | fail_unless (hash[2] == 0x0e); 385 | fail_unless (hash[3] == 0x60); 386 | fail_unless (hash[4] == 0x57); 387 | fail_unless (hash[5] == 0xaa); 388 | fail_unless (hash[6] == 0x2b); 389 | fail_unless (hash[7] == 0xdb); 390 | fail_unless (hash[8] == 0xcd); 391 | fail_unless (hash[9] == 0x42); 392 | fail_unless (hash[10] == 0xd9); 393 | fail_unless (hash[11] == 0x23); 394 | fail_unless (hash[12] == 0x4c); 395 | fail_unless (hash[13] == 0x69); 396 | fail_unless (hash[14] == 0x81); 397 | fail_unless (hash[15] == 0x2f); 398 | fail_unless (hash[16] == 0x37); 399 | fail_unless (hash[17] == 0x0f); 400 | fail_unless (hash[18] == 0x5e); 401 | fail_unless (hash[19] == 0x93); 402 | fail_unless (hash[20] == 0xfe); 403 | fail_unless (hash[21] == 0x9c); 404 | fail_unless (hash[22] == 0x74); 405 | fail_unless (hash[23] == 0xbd); 406 | fail_unless (hash[24] == 0xce); 407 | fail_unless (hash[25] == 0x4c); 408 | fail_unless (hash[26] == 0x59); 409 | fail_unless (hash[27] == 0x3d); 410 | fail_unless (hash[28] == 0xea); 411 | fail_unless (hash[29] == 0xc4); 412 | fail_unless (hash[30] == 0x77); 413 | fail_unless (hash[31] == 0x96); 414 | fail_unless (hash[32] == 0x75); 415 | fail_unless (hash[33] == 0x28); 416 | fail_unless (hash[34] == 0xab); 417 | fail_unless (hash[35] == 0x3c); 418 | fail_unless (hash[36] == 0xf2); 419 | fail_unless (hash[37] == 0x91); 420 | fail_unless (hash[38] == 0x39); 421 | fail_unless (hash[39] == 0x26); 422 | fail_unless (hash[40] == 0x67); 423 | fail_unless (hash[41] == 0xfa); 424 | fail_unless (hash[42] == 0x56); 425 | fail_unless (hash[43] == 0x00); 426 | fail_unless (hash[44] == 0x00); 427 | fail_unless (hash[45] == 0x00); 428 | fail_unless (hash[46] == 0x00); 429 | fail_unless (hash[47] == 0x00); 430 | fail_unless (hash[48] == 0x00); 431 | fail_unless (hash[49] == 0x00); 432 | fail_unless (hash[50] == 0x00); 433 | fail_unless (hash[51] == 0x00); 434 | fail_unless (hash[52] == 0x00); 435 | fail_unless (hash[53] == 0x00); 436 | fail_unless (hash[54] == 0x02); 437 | fail_unless (hash[55] == 0x0f); 438 | fail_unless (hash[56] == 0xcd); 439 | fail_unless (hash[57] == 0x21); 440 | fail_unless (hash[58] == 0xcb); 441 | fail_unless (hash[59] == 0x9c); 442 | fail_unless (hash[60] == 0xd4); 443 | fail_unless (hash[61] == 0x92); 444 | fail_unless (hash[62] == 0x58); 445 | fail_unless (hash[63] == 0x07); 446 | fail_unless (hash[64] == 0xef); 447 | fail_unless (hash[65] == 0x0d); 448 | fail_unless (hash[66] == 0x26); 449 | fail_unless (hash[67] == 0xff); 450 | fail_unless (hash[68] == 0x2d); 451 | fail_unless (hash[69] == 0x78); 452 | fail_unless (hash[70] == 0x6d); 453 | fail_unless (hash[71] == 0x73); 454 | fail_unless (hash[72] == 0xe8); 455 | fail_unless (hash[73] == 0x31); 456 | fail_unless (hash[74] == 0x4b); 457 | fail_unless (hash[75] == 0x48); 458 | fail_unless (hash[76] == 0xca); 459 | fail_unless (hash[77] == 0x33); 460 | fail_unless (hash[78] == 0xe7); 461 | fail_unless (hash[79] == 0x92); 462 | fail_unless (hash[80] == 0xdd); 463 | fail_unless (hash[81] == 0x1e); 464 | fail_unless (hash[82] == 0xb2); 465 | fail_unless (hash[83] == 0xb9); 466 | fail_unless (hash[84] == 0xae); 467 | fail_unless (hash[85] == 0x79); 468 | fail_unless (hash[86] == 0x54); 469 | fail_unless (hash[87] == 0xf0); 470 | fail_unless (hash[88] == 0x79); 471 | fail_unless (hash[89] == 0x72); 472 | fail_unless (hash[90] == 0x90); 473 | fail_unless (hash[91] == 0xcd); 474 | fail_unless (hash[92] == 0x89); 475 | fail_unless (hash[93] == 0x4d); 476 | fail_unless (hash[94] == 0x11); 477 | fail_unless (hash[95] == 0xcd); 478 | fail_unless (hash[96] == 0xca); 479 | fail_unless (hash[97] == 0xe9); 480 | fail_unless (hash[98] == 0xf9); 481 | fail_unless (hash[99] == 0x7c); 482 | fail_unless (hash[100] == 0x39); 483 | fail_unless (hash[101] == 0x2a); 484 | fail_unless (hash[102] == 0xdc); 485 | fail_unless (hash[103] == 0x16); 486 | fail_unless (hash[104] == 0x2a); 487 | fail_unless (hash[105] == 0x42); 488 | fail_unless (hash[106] == 0xac); 489 | fail_unless (hash[107] == 0x74); 490 | fail_unless (hash[108] == 0x21); 491 | fail_unless (hash[109] == 0x70); 492 | fail_unless (hash[110] == 0x96); 493 | fail_unless (hash[111] == 0x48); 494 | fail_unless (hash[112] == 0x8b); 495 | fail_unless (hash[113] == 0xd5); 496 | fail_unless (hash[114] == 0x3e); 497 | fail_unless (hash[115] == 0x8e); 498 | fail_unless (hash[116] == 0x30); 499 | fail_unless (hash[117] == 0x91); 500 | fail_unless (hash[118] == 0x6e); 501 | fail_unless (hash[119] == 0x4f); 502 | fail_unless (hash[120] == 0xa5); 503 | fail_unless (hash[121] == 0x07); 504 | fail_unless (hash[122] == 0x6d); 505 | fail_unless (hash[123] == 0xf5); 506 | fail_unless (hash[124] == 0x20); 507 | fail_unless (hash[125] == 0xff); 508 | fail_unless (hash[126] == 0xb6); 509 | fail_unless (hash[127] == 0x25); 510 | } 511 | 512 | END_TEST; 513 | 514 | START_TEST (test_1a_1024) 515 | { 516 | const char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 517 | uint8_t hash[128]; 518 | 519 | snippets_fnv1a_1024 ((const uint8_t *) str, strlen (str), hash); 520 | fail_unless (hash[0] == 0x0c); 521 | fail_unless (hash[1] == 0x3e); 522 | fail_unless (hash[2] == 0x0e); 523 | fail_unless (hash[3] == 0x62); 524 | fail_unless (hash[4] == 0xba); 525 | fail_unless (hash[5] == 0x3f); 526 | fail_unless (hash[6] == 0x8e); 527 | fail_unless (hash[7] == 0xca); 528 | fail_unless (hash[8] == 0xda); 529 | fail_unless (hash[9] == 0x92); 530 | fail_unless (hash[10] == 0xa7); 531 | fail_unless (hash[11] == 0xd1); 532 | fail_unless (hash[12] == 0xbf); 533 | fail_unless (hash[13] == 0xfe); 534 | fail_unless (hash[14] == 0x47); 535 | fail_unless (hash[15] == 0x12); 536 | fail_unless (hash[16] == 0x4a); 537 | fail_unless (hash[17] == 0xdf); 538 | fail_unless (hash[18] == 0xb2); 539 | fail_unless (hash[19] == 0x8c); 540 | fail_unless (hash[20] == 0x65); 541 | fail_unless (hash[21] == 0x6b); 542 | fail_unless (hash[22] == 0xd8); 543 | fail_unless (hash[23] == 0x7c); 544 | fail_unless (hash[24] == 0x9f); 545 | fail_unless (hash[25] == 0xcb); 546 | fail_unless (hash[26] == 0x78); 547 | fail_unless (hash[27] == 0xc6); 548 | fail_unless (hash[28] == 0x25); 549 | fail_unless (hash[29] == 0x28); 550 | fail_unless (hash[30] == 0x5d); 551 | fail_unless (hash[31] == 0x26); 552 | fail_unless (hash[32] == 0xa5); 553 | fail_unless (hash[33] == 0x5d); 554 | fail_unless (hash[34] == 0xe9); 555 | fail_unless (hash[35] == 0x87); 556 | fail_unless (hash[36] == 0x91); 557 | fail_unless (hash[37] == 0x6e); 558 | fail_unless (hash[38] == 0x74); 559 | fail_unless (hash[39] == 0x2d); 560 | fail_unless (hash[40] == 0x91); 561 | fail_unless (hash[41] == 0xfe); 562 | fail_unless (hash[42] == 0x12); 563 | fail_unless (hash[43] == 0x00); 564 | fail_unless (hash[44] == 0x00); 565 | fail_unless (hash[45] == 0x00); 566 | fail_unless (hash[46] == 0x00); 567 | fail_unless (hash[47] == 0x00); 568 | fail_unless (hash[48] == 0x00); 569 | fail_unless (hash[49] == 0x00); 570 | fail_unless (hash[50] == 0x00); 571 | fail_unless (hash[51] == 0x00); 572 | fail_unless (hash[52] == 0x00); 573 | fail_unless (hash[53] == 0x00); 574 | fail_unless (hash[54] == 0x02); 575 | fail_unless (hash[55] == 0x0f); 576 | fail_unless (hash[56] == 0xcd); 577 | fail_unless (hash[57] == 0x21); 578 | fail_unless (hash[58] == 0xcb); 579 | fail_unless (hash[59] == 0x9c); 580 | fail_unless (hash[60] == 0xd4); 581 | fail_unless (hash[61] == 0x92); 582 | fail_unless (hash[62] == 0x58); 583 | fail_unless (hash[63] == 0x07); 584 | fail_unless (hash[64] == 0xef); 585 | fail_unless (hash[65] == 0x0d); 586 | fail_unless (hash[66] == 0x26); 587 | fail_unless (hash[67] == 0xff); 588 | fail_unless (hash[68] == 0x2d); 589 | fail_unless (hash[69] == 0x78); 590 | fail_unless (hash[70] == 0x6d); 591 | fail_unless (hash[71] == 0x73); 592 | fail_unless (hash[72] == 0xe8); 593 | fail_unless (hash[73] == 0x31); 594 | fail_unless (hash[74] == 0x4b); 595 | fail_unless (hash[75] == 0x48); 596 | fail_unless (hash[76] == 0xca); 597 | fail_unless (hash[77] == 0x33); 598 | fail_unless (hash[78] == 0xe7); 599 | fail_unless (hash[79] == 0x92); 600 | fail_unless (hash[80] == 0xdd); 601 | fail_unless (hash[81] == 0x1e); 602 | fail_unless (hash[82] == 0xb2); 603 | fail_unless (hash[83] == 0xb9); 604 | fail_unless (hash[84] == 0xae); 605 | fail_unless (hash[85] == 0x79); 606 | fail_unless (hash[86] == 0x54); 607 | fail_unless (hash[87] == 0xf0); 608 | fail_unless (hash[88] == 0x94); 609 | fail_unless (hash[89] == 0x7f); 610 | fail_unless (hash[90] == 0xcd); 611 | fail_unless (hash[91] == 0x33); 612 | fail_unless (hash[92] == 0xaf); 613 | fail_unless (hash[93] == 0x6b); 614 | fail_unless (hash[94] == 0x16); 615 | fail_unless (hash[95] == 0x2f); 616 | fail_unless (hash[96] == 0xd7); 617 | fail_unless (hash[97] == 0x87); 618 | fail_unless (hash[98] == 0x4c); 619 | fail_unless (hash[99] == 0x62); 620 | fail_unless (hash[100] == 0x73); 621 | fail_unless (hash[101] == 0x61); 622 | fail_unless (hash[102] == 0x07); 623 | fail_unless (hash[103] == 0x64); 624 | fail_unless (hash[104] == 0xfa); 625 | fail_unless (hash[105] == 0x49); 626 | fail_unless (hash[106] == 0xd3); 627 | fail_unless (hash[107] == 0x1b); 628 | fail_unless (hash[108] == 0xe3); 629 | fail_unless (hash[109] == 0xc5); 630 | fail_unless (hash[110] == 0x65); 631 | fail_unless (hash[111] == 0xae); 632 | fail_unless (hash[112] == 0xa8); 633 | fail_unless (hash[113] == 0xf9); 634 | fail_unless (hash[114] == 0x61); 635 | fail_unless (hash[115] == 0x62); 636 | fail_unless (hash[116] == 0xc6); 637 | fail_unless (hash[117] == 0xd1); 638 | fail_unless (hash[118] == 0x0a); 639 | fail_unless (hash[119] == 0xfd); 640 | fail_unless (hash[120] == 0xef); 641 | fail_unless (hash[121] == 0x57); 642 | fail_unless (hash[122] == 0xac); 643 | fail_unless (hash[123] == 0x03); 644 | fail_unless (hash[124] == 0x2b); 645 | fail_unless (hash[125] == 0x8e); 646 | fail_unless (hash[126] == 0x85); 647 | fail_unless (hash[127] == 0x2d); 648 | } 649 | 650 | END_TEST; 651 | 652 | static Suite * 653 | fnv_suite (void) 654 | { 655 | Suite *s = suite_create ("FNV"); 656 | 657 | /* Core test case */ 658 | TCase *tc_general = tcase_create ("general"); 659 | tcase_add_test (tc_general, test_1_32); 660 | tcase_add_test (tc_general, test_1a_32); 661 | tcase_add_test (tc_general, test_1_64); 662 | tcase_add_test (tc_general, test_1a_64); 663 | tcase_add_test (tc_general, test_1_128); 664 | tcase_add_test (tc_general, test_1a_128); 665 | tcase_add_test (tc_general, test_1_256); 666 | tcase_add_test (tc_general, test_1a_256); 667 | tcase_add_test (tc_general, test_1_512); 668 | tcase_add_test (tc_general, test_1a_512); 669 | tcase_add_test (tc_general, test_1_1024); 670 | tcase_add_test (tc_general, test_1a_1024); 671 | suite_add_tcase (s, tc_general); 672 | 673 | return s; 674 | } 675 | 676 | int 677 | main (void) 678 | { 679 | int number_failed; 680 | Suite *s = fnv_suite (); 681 | SRunner *sr = srunner_create (s); 682 | srunner_run_all (sr, CK_NORMAL); 683 | number_failed = srunner_ntests_failed (sr); 684 | srunner_free (sr); 685 | return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 686 | } 687 | -------------------------------------------------------------------------------- /tests/linkedlist.c: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifdef HAVE_CONFIG_H 21 | #include "config.h" 22 | #endif 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | static void 29 | copy_string (void *dest, const void *src) 30 | { 31 | char **d = dest; 32 | const char *s = src; 33 | 34 | *d = strdup (s); 35 | } 36 | 37 | static int 38 | compare_string (const void *a, const void *b, void *user_data) 39 | { 40 | return strcmp (a, b); 41 | } 42 | 43 | static const char *string_a = "abc"; 44 | static const char *string_b = "def"; 45 | static const char *string_c = "ghi"; 46 | static const char *string_d = "jkl"; 47 | 48 | START_TEST (test_string_copy) 49 | { 50 | SnippetsLinkedList *list, *copy; 51 | SnippetsLinkedListNode *n1, *n2, *n3, *n4, *l; 52 | char **str, **str2; 53 | 54 | list = snippets_linked_list_new_pointer (copy_string, free); 55 | 56 | fail_unless (snippets_linked_list_length (list) == 0); 57 | n1 = snippets_linked_list_append (list, (void *) string_a); 58 | fail_unless (n1 != NULL); 59 | fail_unless (snippets_linked_list_length (list) == 1); 60 | n2 = snippets_linked_list_append (list, (void *) string_b); 61 | fail_unless (n2 != NULL); 62 | fail_unless (snippets_linked_list_length (list) == 2); 63 | n3 = snippets_linked_list_append (list, (void *) string_c); 64 | fail_unless (n3 != NULL); 65 | fail_unless (snippets_linked_list_length (list) == 3); 66 | n4 = snippets_linked_list_append (list, (void *) string_d); 67 | fail_unless (n4 != NULL); 68 | fail_unless (snippets_linked_list_length (list) == 4); 69 | 70 | fail_unless (snippets_linked_list_head (list) == n1); 71 | fail_unless (snippets_linked_list_node_prev (n1) == NULL); 72 | fail_unless (snippets_linked_list_node_next (n1) == n2); 73 | fail_unless (snippets_linked_list_node_prev (n2) == n1); 74 | fail_unless (snippets_linked_list_node_next (n2) == n3); 75 | fail_unless (snippets_linked_list_node_prev (n3) == n2); 76 | fail_unless (snippets_linked_list_node_next (n3) == n4); 77 | fail_unless (snippets_linked_list_node_prev (n4) == n3); 78 | fail_unless (snippets_linked_list_node_next (n4) == NULL); 79 | fail_unless (snippets_linked_list_tail (list) == n4); 80 | 81 | str = snippets_linked_list_node_get (n1, char *); 82 | fail_unless (str != NULL); 83 | fail_if (*str == string_a); 84 | fail_unless (strcmp (*str, string_a) == 0); 85 | 86 | str = snippets_linked_list_node_get (n2, char *); 87 | fail_unless (str != NULL); 88 | fail_if (*str == string_b); 89 | fail_unless (strcmp (*str, string_b) == 0); 90 | 91 | str = snippets_linked_list_node_get (n3, char *); 92 | fail_unless (str != NULL); 93 | fail_if (*str == string_c); 94 | fail_unless (strcmp (*str, string_c) == 0); 95 | 96 | str = snippets_linked_list_node_get (n4, char *); 97 | fail_unless (str != NULL); 98 | fail_if (*str == string_d); 99 | fail_unless (strcmp (*str, string_d) == 0); 100 | 101 | l = snippets_linked_list_find (list, string_a, compare_string, NULL); 102 | fail_unless (l != NULL); 103 | fail_unless (l != n3); 104 | 105 | l = snippets_linked_list_find (list, "test", compare_string, NULL); 106 | fail_unless (l == NULL); 107 | 108 | copy = snippets_linked_list_copy (list); 109 | fail_unless (copy != NULL); 110 | fail_unless (snippets_linked_list_length (copy) == 111 | snippets_linked_list_length (list)); 112 | 113 | l = snippets_linked_list_head (copy); 114 | fail_unless (l != NULL); 115 | str = snippets_linked_list_node_get (n1, char *); 116 | fail_unless (str != NULL && *str != NULL); 117 | str2 = snippets_linked_list_node_get (l, char *); 118 | fail_unless (str2 != NULL && *str2 != NULL); 119 | fail_unless (str != str2); 120 | fail_if (*str2 == *str); 121 | fail_unless (strcmp (*str, *str2) == 0); 122 | 123 | l = snippets_linked_list_node_next (l); 124 | fail_unless (l != NULL); 125 | str = snippets_linked_list_node_get (n2, char *); 126 | fail_unless (str != NULL && *str != NULL); 127 | str2 = snippets_linked_list_node_get (l, char *); 128 | fail_unless (str2 != NULL && *str2 != NULL); 129 | fail_unless (str != str2); 130 | fail_if (*str2 == *str); 131 | fail_unless (strcmp (*str, *str2) == 0); 132 | 133 | l = snippets_linked_list_node_next (l); 134 | fail_unless (l != NULL); 135 | str = snippets_linked_list_node_get (n3, char *); 136 | fail_unless (str != NULL && *str != NULL); 137 | str2 = snippets_linked_list_node_get (l, char *); 138 | fail_unless (str2 != NULL && *str2 != NULL); 139 | fail_unless (str != str2); 140 | fail_if (*str2 == *str); 141 | fail_unless (strcmp (*str, *str2) == 0); 142 | 143 | l = snippets_linked_list_node_next (l); 144 | fail_unless (l != NULL); 145 | fail_unless (snippets_linked_list_tail (copy) == l); 146 | str = snippets_linked_list_node_get (n4, char *); 147 | fail_unless (str != NULL && *str != NULL); 148 | str2 = snippets_linked_list_node_get (l, char *); 149 | fail_unless (str2 != NULL && *str2 != NULL); 150 | fail_unless (str != str2); 151 | fail_if (*str2 == *str); 152 | fail_unless (strcmp (*str, *str2) == 0); 153 | 154 | l = snippets_linked_list_node_next (l); 155 | fail_unless (l == NULL); 156 | 157 | snippets_linked_list_free (list); 158 | snippets_linked_list_free (copy); 159 | } 160 | 161 | END_TEST; 162 | 163 | START_TEST (test_string_nocopy) 164 | { 165 | SnippetsLinkedList *list, *copy; 166 | SnippetsLinkedListNode *n1, *n2, *n3, *n4, *l; 167 | char **str, **str2; 168 | 169 | list = snippets_linked_list_new_pointer (NULL, NULL); 170 | 171 | fail_unless (snippets_linked_list_length (list) == 0); 172 | n1 = snippets_linked_list_append (list, (void *) string_a); 173 | fail_unless (n1 != NULL); 174 | fail_unless (snippets_linked_list_length (list) == 1); 175 | n2 = snippets_linked_list_append (list, (void *) string_b); 176 | fail_unless (n2 != NULL); 177 | fail_unless (snippets_linked_list_length (list) == 2); 178 | n3 = snippets_linked_list_append (list, (void *) string_c); 179 | fail_unless (n3 != NULL); 180 | fail_unless (snippets_linked_list_length (list) == 3); 181 | n4 = snippets_linked_list_append (list, (void *) string_d); 182 | fail_unless (n4 != NULL); 183 | fail_unless (snippets_linked_list_length (list) == 4); 184 | 185 | fail_unless (snippets_linked_list_head (list) == n1); 186 | fail_unless (snippets_linked_list_node_prev (n1) == NULL); 187 | fail_unless (snippets_linked_list_node_next (n1) == n2); 188 | fail_unless (snippets_linked_list_node_prev (n2) == n1); 189 | fail_unless (snippets_linked_list_node_next (n2) == n3); 190 | fail_unless (snippets_linked_list_node_prev (n3) == n2); 191 | fail_unless (snippets_linked_list_node_next (n3) == n4); 192 | fail_unless (snippets_linked_list_node_prev (n4) == n3); 193 | fail_unless (snippets_linked_list_node_next (n4) == NULL); 194 | fail_unless (snippets_linked_list_tail (list) == n4); 195 | 196 | str = snippets_linked_list_node_get (n1, char *); 197 | fail_unless (str != NULL); 198 | fail_unless (*str == string_a); 199 | fail_unless (strcmp (*str, string_a) == 0); 200 | 201 | str = snippets_linked_list_node_get (n2, char *); 202 | fail_unless (str != NULL); 203 | fail_unless (*str == string_b); 204 | fail_unless (strcmp (*str, string_b) == 0); 205 | 206 | str = snippets_linked_list_node_get (n3, char *); 207 | fail_unless (str != NULL); 208 | fail_unless (*str == string_c); 209 | fail_unless (strcmp (*str, string_c) == 0); 210 | 211 | str = snippets_linked_list_node_get (n4, char *); 212 | fail_unless (str != NULL); 213 | fail_unless (*str == string_d); 214 | fail_unless (strcmp (*str, string_d) == 0); 215 | 216 | l = snippets_linked_list_find (list, string_a, compare_string, NULL); 217 | fail_unless (l != NULL); 218 | fail_unless (l != n3); 219 | 220 | l = snippets_linked_list_find (list, "test", compare_string, NULL); 221 | fail_unless (l == NULL); 222 | 223 | copy = snippets_linked_list_copy (list); 224 | fail_unless (copy != NULL); 225 | fail_unless (snippets_linked_list_length (copy) == 226 | snippets_linked_list_length (list)); 227 | 228 | l = snippets_linked_list_head (copy); 229 | fail_unless (l != NULL); 230 | str = snippets_linked_list_node_get (n1, char *); 231 | fail_unless (str != NULL && *str != NULL); 232 | str2 = snippets_linked_list_node_get (l, char *); 233 | fail_unless (str2 != NULL && *str2 != NULL); 234 | fail_unless (str != str2); 235 | fail_unless (*str2 == *str); 236 | 237 | l = snippets_linked_list_node_next (l); 238 | fail_unless (l != NULL); 239 | str = snippets_linked_list_node_get (n2, char *); 240 | fail_unless (str != NULL && *str != NULL); 241 | str2 = snippets_linked_list_node_get (l, char *); 242 | fail_unless (str2 != NULL && *str2 != NULL); 243 | fail_unless (str != str2); 244 | fail_unless (*str2 == *str); 245 | 246 | l = snippets_linked_list_node_next (l); 247 | fail_unless (l != NULL); 248 | str = snippets_linked_list_node_get (n3, char *); 249 | fail_unless (str != NULL && *str != NULL); 250 | str2 = snippets_linked_list_node_get (l, char *); 251 | fail_unless (str2 != NULL && *str2 != NULL); 252 | fail_unless (str != str2); 253 | fail_unless (*str2 == *str); 254 | 255 | l = snippets_linked_list_node_next (l); 256 | fail_unless (l != NULL); 257 | fail_unless (snippets_linked_list_tail (copy) == l); 258 | str = snippets_linked_list_node_get (n4, char *); 259 | fail_unless (str != NULL && *str != NULL); 260 | str2 = snippets_linked_list_node_get (l, char *); 261 | fail_unless (str2 != NULL && *str2 != NULL); 262 | fail_unless (str != str2); 263 | fail_unless (*str2 == *str); 264 | 265 | l = snippets_linked_list_node_next (l); 266 | fail_unless (l == NULL); 267 | 268 | snippets_linked_list_free (list); 269 | snippets_linked_list_free (copy); 270 | } 271 | 272 | END_TEST; 273 | 274 | typedef struct _TestData TestData; 275 | struct _TestData 276 | { 277 | int x, y; 278 | char *str; 279 | }; 280 | 281 | static void 282 | copy_struct (void *dest, const void *src) 283 | { 284 | TestData *d = dest; 285 | const TestData *s = src; 286 | 287 | d->x = s->x; 288 | d->y = s->y; 289 | d->str = strdup (s->str); 290 | } 291 | 292 | static void 293 | free_struct (void *o) 294 | { 295 | TestData *d = o; 296 | 297 | free (d->str); 298 | } 299 | 300 | START_TEST (test_struct_deep_copy) 301 | { 302 | SnippetsLinkedList *list, *copy; 303 | SnippetsLinkedListNode *n1, *n2, *n3, *n4, *l; 304 | TestData d1 = { 1, 4, (char *) "1:4" }; 305 | TestData d2 = { 2, 3, (char *) "2:3" }; 306 | TestData d3 = { 3, 2, (char *) "3:2" }; 307 | TestData d4 = { 4, 1, (char *) "4:1" }; 308 | TestData *d, *dd; 309 | 310 | list = snippets_linked_list_new (sizeof (TestData), copy_struct, free_struct); 311 | 312 | fail_unless (snippets_linked_list_length (list) == 0); 313 | n1 = snippets_linked_list_append (list, &d1); 314 | fail_unless (n1 != NULL); 315 | fail_unless (snippets_linked_list_length (list) == 1); 316 | n2 = snippets_linked_list_append (list, &d2); 317 | fail_unless (n2 != NULL); 318 | fail_unless (snippets_linked_list_length (list) == 2); 319 | n3 = snippets_linked_list_append (list, &d3); 320 | fail_unless (n3 != NULL); 321 | fail_unless (snippets_linked_list_length (list) == 3); 322 | n4 = snippets_linked_list_append (list, &d4); 323 | fail_unless (n4 != NULL); 324 | fail_unless (snippets_linked_list_length (list) == 4); 325 | 326 | fail_unless (snippets_linked_list_head (list) == n1); 327 | fail_unless (snippets_linked_list_node_prev (n1) == NULL); 328 | fail_unless (snippets_linked_list_node_next (n1) == n2); 329 | fail_unless (snippets_linked_list_node_prev (n2) == n1); 330 | fail_unless (snippets_linked_list_node_next (n2) == n3); 331 | fail_unless (snippets_linked_list_node_prev (n3) == n2); 332 | fail_unless (snippets_linked_list_node_next (n3) == n4); 333 | fail_unless (snippets_linked_list_node_prev (n4) == n3); 334 | fail_unless (snippets_linked_list_node_next (n4) == NULL); 335 | fail_unless (snippets_linked_list_tail (list) == n4); 336 | 337 | d = snippets_linked_list_node_get (n1, TestData); 338 | fail_unless (d != NULL); 339 | fail_if (d == &d1); 340 | fail_unless (d->x == d1.x); 341 | fail_unless (d->y == d1.y); 342 | fail_if (d->str == d1.str); 343 | fail_unless (strcmp (d->str, d1.str) == 0); 344 | 345 | d = snippets_linked_list_node_get (n2, TestData); 346 | fail_unless (d != NULL); 347 | fail_if (d == &d2); 348 | fail_unless (d->x == d2.x); 349 | fail_unless (d->y == d2.y); 350 | fail_if (d->str == d2.str); 351 | fail_unless (strcmp (d->str, d2.str) == 0); 352 | 353 | d = snippets_linked_list_node_get (n3, TestData); 354 | fail_unless (d != NULL); 355 | fail_if (d == &d3); 356 | fail_unless (d->x == d3.x); 357 | fail_unless (d->y == d3.y); 358 | fail_if (d->str == d3.str); 359 | fail_unless (strcmp (d->str, d3.str) == 0); 360 | 361 | d = snippets_linked_list_node_get (n4, TestData); 362 | fail_unless (d != NULL); 363 | fail_if (d == &d4); 364 | fail_unless (d->x == d4.x); 365 | fail_unless (d->y == d4.y); 366 | fail_if (d->str == d4.str); 367 | fail_unless (strcmp (d->str, d4.str) == 0); 368 | 369 | copy = snippets_linked_list_copy (list); 370 | fail_unless (copy != NULL); 371 | fail_unless (snippets_linked_list_length (copy) == 372 | snippets_linked_list_length (list)); 373 | 374 | l = snippets_linked_list_head (copy); 375 | fail_unless (l != NULL); 376 | d = snippets_linked_list_node_get (n1, TestData); 377 | dd = snippets_linked_list_node_get (l, TestData); 378 | fail_unless (d != dd); 379 | fail_unless (d->x == dd->x); 380 | fail_unless (d->y == dd->y); 381 | fail_if (d->str == dd->str); 382 | fail_unless (strcmp (d->str, dd->str) == 0); 383 | 384 | l = snippets_linked_list_node_next (l); 385 | fail_unless (l != NULL); 386 | d = snippets_linked_list_node_get (n2, TestData); 387 | dd = snippets_linked_list_node_get (l, TestData); 388 | fail_unless (d != dd); 389 | fail_unless (d->x == dd->x); 390 | fail_unless (d->y == dd->y); 391 | fail_if (d->str == dd->str); 392 | fail_unless (strcmp (d->str, dd->str) == 0); 393 | 394 | l = snippets_linked_list_node_next (l); 395 | fail_unless (l != NULL); 396 | d = snippets_linked_list_node_get (n3, TestData); 397 | dd = snippets_linked_list_node_get (l, TestData); 398 | fail_unless (d != dd); 399 | fail_unless (d->x == dd->x); 400 | fail_unless (d->y == dd->y); 401 | fail_if (d->str == dd->str); 402 | fail_unless (strcmp (d->str, dd->str) == 0); 403 | 404 | l = snippets_linked_list_node_next (l); 405 | fail_unless (l != NULL); 406 | fail_unless (snippets_linked_list_tail (copy) == l); 407 | d = snippets_linked_list_node_get (n4, TestData); 408 | dd = snippets_linked_list_node_get (l, TestData); 409 | fail_unless (d != dd); 410 | fail_unless (d->x == dd->x); 411 | fail_unless (d->y == dd->y); 412 | fail_if (d->str == dd->str); 413 | fail_unless (strcmp (d->str, dd->str) == 0); 414 | 415 | l = snippets_linked_list_node_next (l); 416 | fail_unless (l == NULL); 417 | 418 | snippets_linked_list_free (list); 419 | snippets_linked_list_free (copy); 420 | } 421 | 422 | END_TEST; 423 | 424 | START_TEST (test_struct) 425 | { 426 | SnippetsLinkedList *list, *copy; 427 | SnippetsLinkedListNode *n1, *n2, *n3, *n4, *l; 428 | TestData d1 = { 1, 4, (char *) "1:4" }; 429 | TestData d2 = { 2, 3, (char *) "2:3" }; 430 | TestData d3 = { 3, 2, (char *) "3:2" }; 431 | TestData d4 = { 4, 1, (char *) "4:1" }; 432 | TestData *d, *dd; 433 | 434 | list = snippets_linked_list_new (sizeof (TestData), NULL, NULL); 435 | 436 | fail_unless (snippets_linked_list_length (list) == 0); 437 | n1 = snippets_linked_list_append (list, &d1); 438 | fail_unless (n1 != NULL); 439 | fail_unless (snippets_linked_list_length (list) == 1); 440 | n2 = snippets_linked_list_append (list, &d2); 441 | fail_unless (n2 != NULL); 442 | fail_unless (snippets_linked_list_length (list) == 2); 443 | n3 = snippets_linked_list_append (list, &d3); 444 | fail_unless (n3 != NULL); 445 | fail_unless (snippets_linked_list_length (list) == 3); 446 | n4 = snippets_linked_list_append (list, &d4); 447 | fail_unless (n4 != NULL); 448 | fail_unless (snippets_linked_list_length (list) == 4); 449 | 450 | fail_unless (snippets_linked_list_head (list) == n1); 451 | fail_unless (snippets_linked_list_node_prev (n1) == NULL); 452 | fail_unless (snippets_linked_list_node_next (n1) == n2); 453 | fail_unless (snippets_linked_list_node_prev (n2) == n1); 454 | fail_unless (snippets_linked_list_node_next (n2) == n3); 455 | fail_unless (snippets_linked_list_node_prev (n3) == n2); 456 | fail_unless (snippets_linked_list_node_next (n3) == n4); 457 | fail_unless (snippets_linked_list_node_prev (n4) == n3); 458 | fail_unless (snippets_linked_list_node_next (n4) == NULL); 459 | fail_unless (snippets_linked_list_tail (list) == n4); 460 | 461 | d = snippets_linked_list_node_get (n1, TestData); 462 | fail_unless (d != NULL); 463 | fail_unless (memcmp (d, &d1, sizeof (TestData)) == 0); 464 | 465 | d = snippets_linked_list_node_get (n2, TestData); 466 | fail_unless (d != NULL); 467 | fail_unless (memcmp (d, &d2, sizeof (TestData)) == 0); 468 | 469 | d = snippets_linked_list_node_get (n3, TestData); 470 | fail_unless (d != NULL); 471 | fail_unless (memcmp (d, &d3, sizeof (TestData)) == 0); 472 | 473 | d = snippets_linked_list_node_get (n4, TestData); 474 | fail_unless (d != NULL); 475 | fail_unless (memcmp (d, &d4, sizeof (TestData)) == 0); 476 | 477 | copy = snippets_linked_list_copy (list); 478 | fail_unless (copy != NULL); 479 | fail_unless (snippets_linked_list_length (copy) == 480 | snippets_linked_list_length (list)); 481 | 482 | l = snippets_linked_list_head (copy); 483 | fail_unless (l != NULL); 484 | d = snippets_linked_list_node_get (n1, TestData); 485 | dd = snippets_linked_list_node_get (l, TestData); 486 | fail_unless (d != dd); 487 | fail_unless (d->x == dd->x); 488 | fail_unless (d->y == dd->y); 489 | fail_unless (d->str == dd->str); 490 | 491 | l = snippets_linked_list_node_next (l); 492 | fail_unless (l != NULL); 493 | d = snippets_linked_list_node_get (n2, TestData); 494 | dd = snippets_linked_list_node_get (l, TestData); 495 | fail_unless (d != dd); 496 | fail_unless (d->x == dd->x); 497 | fail_unless (d->y == dd->y); 498 | fail_unless (d->str == dd->str); 499 | 500 | l = snippets_linked_list_node_next (l); 501 | fail_unless (l != NULL); 502 | d = snippets_linked_list_node_get (n3, TestData); 503 | dd = snippets_linked_list_node_get (l, TestData); 504 | fail_unless (d != dd); 505 | fail_unless (d->x == dd->x); 506 | fail_unless (d->y == dd->y); 507 | fail_unless (d->str == dd->str); 508 | 509 | l = snippets_linked_list_node_next (l); 510 | fail_unless (l != NULL); 511 | fail_unless (snippets_linked_list_tail (copy) == l); 512 | d = snippets_linked_list_node_get (n4, TestData); 513 | dd = snippets_linked_list_node_get (l, TestData); 514 | fail_unless (d != dd); 515 | fail_unless (d->x == dd->x); 516 | fail_unless (d->y == dd->y); 517 | fail_unless (d->str == dd->str); 518 | 519 | l = snippets_linked_list_node_next (l); 520 | fail_unless (l == NULL); 521 | 522 | snippets_linked_list_free (list); 523 | snippets_linked_list_free (copy); 524 | } 525 | 526 | END_TEST; 527 | 528 | START_TEST (test_append_prepend_remove) 529 | { 530 | SnippetsLinkedList *list; 531 | SnippetsLinkedListNode *n1, *n2, *n3, *n4; 532 | void **p; 533 | 534 | list = snippets_linked_list_new_pointer (NULL, NULL); 535 | 536 | fail_unless (snippets_linked_list_length (list) == 0); 537 | n1 = snippets_linked_list_append (list, (void *) 0); 538 | fail_unless (n1 != NULL); 539 | fail_unless (snippets_linked_list_length (list) == 1); 540 | 541 | n2 = snippets_linked_list_prepend (list, (void *) 1); 542 | fail_unless (n2 != NULL); 543 | fail_unless (snippets_linked_list_length (list) == 2); 544 | 545 | p = snippets_linked_list_node_get (snippets_linked_list_head (list), void *); 546 | fail_unless (*p == (void *) 1); 547 | 548 | p = snippets_linked_list_node_get (snippets_linked_list_tail (list), void *); 549 | fail_unless (*p == (void *) 0); 550 | 551 | fail_unless (snippets_linked_list_node_prev (n1) == n2); 552 | fail_unless (snippets_linked_list_node_next (n1) == NULL); 553 | fail_unless (snippets_linked_list_node_prev (n2) == NULL); 554 | fail_unless (snippets_linked_list_node_next (n2) == n1); 555 | 556 | fail_unless (snippets_linked_list_length (list) == 2); 557 | n3 = snippets_linked_list_insert_after (list, n2, (void *) 3); 558 | fail_unless (n3 != NULL); 559 | fail_unless (snippets_linked_list_length (list) == 3); 560 | 561 | fail_unless (snippets_linked_list_node_prev (n1) == n3); 562 | fail_unless (snippets_linked_list_node_next (n1) == NULL); 563 | fail_unless (snippets_linked_list_node_prev (n2) == NULL); 564 | fail_unless (snippets_linked_list_node_next (n2) == n3); 565 | fail_unless (snippets_linked_list_node_prev (n3) == n2); 566 | fail_unless (snippets_linked_list_node_next (n3) == n1); 567 | 568 | fail_unless (snippets_linked_list_length (list) == 3); 569 | n4 = snippets_linked_list_insert_before (list, n3, (void *) 4); 570 | fail_unless (n4 != NULL); 571 | fail_unless (snippets_linked_list_length (list) == 4); 572 | 573 | fail_unless (snippets_linked_list_node_prev (n1) == n3); 574 | fail_unless (snippets_linked_list_node_next (n1) == NULL); 575 | fail_unless (snippets_linked_list_node_prev (n2) == NULL); 576 | fail_unless (snippets_linked_list_node_next (n2) == n4); 577 | fail_unless (snippets_linked_list_node_prev (n3) == n4); 578 | fail_unless (snippets_linked_list_node_next (n3) == n1); 579 | fail_unless (snippets_linked_list_node_prev (n4) == n2); 580 | fail_unless (snippets_linked_list_node_next (n4) == n3); 581 | 582 | fail_unless (snippets_linked_list_length (list) == 4); 583 | snippets_linked_list_remove (list, n4); 584 | fail_unless (snippets_linked_list_length (list) == 3); 585 | 586 | fail_unless (snippets_linked_list_node_prev (n1) == n3); 587 | fail_unless (snippets_linked_list_node_next (n1) == NULL); 588 | fail_unless (snippets_linked_list_node_prev (n2) == NULL); 589 | fail_unless (snippets_linked_list_node_next (n2) == n3); 590 | fail_unless (snippets_linked_list_node_prev (n3) == n2); 591 | fail_unless (snippets_linked_list_node_next (n3) == n1); 592 | 593 | fail_unless (snippets_linked_list_length (list) == 3); 594 | snippets_linked_list_remove (list, n1); 595 | fail_unless (snippets_linked_list_length (list) == 2); 596 | 597 | fail_unless (snippets_linked_list_node_prev (n2) == NULL); 598 | fail_unless (snippets_linked_list_node_next (n2) == n3); 599 | fail_unless (snippets_linked_list_node_prev (n3) == n2); 600 | fail_unless (snippets_linked_list_node_next (n3) == NULL); 601 | 602 | fail_unless (snippets_linked_list_length (list) == 2); 603 | snippets_linked_list_remove (list, n2); 604 | fail_unless (snippets_linked_list_length (list) == 1); 605 | 606 | fail_unless (snippets_linked_list_node_prev (n3) == NULL); 607 | fail_unless (snippets_linked_list_node_next (n3) == NULL); 608 | fail_unless (snippets_linked_list_head (list) == n3); 609 | fail_unless (snippets_linked_list_tail (list) == n3); 610 | 611 | fail_unless (snippets_linked_list_length (list) == 1); 612 | snippets_linked_list_remove (list, n3); 613 | fail_unless (snippets_linked_list_length (list) == 0); 614 | 615 | fail_unless (snippets_linked_list_head (list) == NULL); 616 | fail_unless (snippets_linked_list_tail (list) == NULL); 617 | 618 | fail_unless (snippets_linked_list_length (list) == 0); 619 | 620 | snippets_linked_list_free (list); 621 | } 622 | 623 | END_TEST; 624 | 625 | static Suite * 626 | linkedlist_suite (void) 627 | { 628 | Suite *s = suite_create ("LinkedList"); 629 | 630 | /* Core test case */ 631 | TCase *tc_general = tcase_create ("general"); 632 | tcase_add_test (tc_general, test_string_copy); 633 | tcase_add_test (tc_general, test_string_nocopy); 634 | tcase_add_test (tc_general, test_struct_deep_copy); 635 | tcase_add_test (tc_general, test_struct); 636 | tcase_add_test (tc_general, test_append_prepend_remove); 637 | suite_add_tcase (s, tc_general); 638 | 639 | return s; 640 | } 641 | 642 | int 643 | main (void) 644 | { 645 | int number_failed; 646 | Suite *s = linkedlist_suite (); 647 | SRunner *sr = srunner_create (s); 648 | srunner_run_all (sr, CK_NORMAL); 649 | number_failed = srunner_ntests_failed (sr); 650 | srunner_free (sr); 651 | return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 652 | } 653 | -------------------------------------------------------------------------------- /tests/rand.c: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifdef HAVE_CONFIG_H 21 | #include "config.h" 22 | #endif 23 | 24 | #include 25 | #include 26 | 27 | START_TEST (test_rand_mt_uint32) 28 | { 29 | SnippetsRand *rand = snippets_rand_new (0xdeadbeef); 30 | unsigned int i; 31 | 32 | for (i = 0; i < 2048; i++) 33 | snippets_rand_uint32 (rand); 34 | 35 | /* Not testing much here... */ 36 | 37 | snippets_rand_free (rand); 38 | } 39 | 40 | END_TEST; 41 | 42 | START_TEST (test_rand_mt_double) 43 | { 44 | SnippetsRand *rand = snippets_rand_new (0xdeadbeef); 45 | double vals[2048]; 46 | unsigned int i; 47 | 48 | for (i = 0; i < 2048; i++) { 49 | vals[i] = snippets_rand_double (rand); 50 | fail_unless (vals[i] < 1.0 && vals[i] >= 0.0); 51 | } 52 | 53 | /* Not testing much here... */ 54 | 55 | snippets_rand_free (rand); 56 | } 57 | 58 | END_TEST; 59 | 60 | START_TEST (test_rand_mt_uint32_range_20_100) 61 | { 62 | SnippetsRand *rand = snippets_rand_new (0xdeadbeef); 63 | uint32_t vals[2048]; 64 | unsigned int i; 65 | 66 | for (i = 0; i < 2048; i++) { 67 | vals[i] = snippets_rand_uint32_range (rand, 20, 100); 68 | fail_unless (vals[i] >= 20 && vals[i] < 100); 69 | } 70 | 71 | /* Not testing much here... */ 72 | 73 | snippets_rand_free (rand); 74 | } 75 | 76 | END_TEST; 77 | 78 | START_TEST (test_rand_mt_double_range_20_100) 79 | { 80 | SnippetsRand *rand = snippets_rand_new (0xdeadbeef); 81 | double vals[2048]; 82 | unsigned int i; 83 | 84 | for (i = 0; i < 2048; i++) { 85 | vals[i] = snippets_rand_double_range (rand, 20, 100); 86 | fail_unless (vals[i] >= 20 && vals[i] < 100); 87 | } 88 | 89 | /* Not testing much here... */ 90 | 91 | snippets_rand_free (rand); 92 | } 93 | 94 | END_TEST; 95 | 96 | static Suite * 97 | rand_suite (void) 98 | { 99 | Suite *s = suite_create ("Rand"); 100 | 101 | /* Core test case */ 102 | TCase *tc_general = tcase_create ("general"); 103 | tcase_add_test (tc_general, test_rand_mt_uint32); 104 | tcase_add_test (tc_general, test_rand_mt_double); 105 | tcase_add_test (tc_general, test_rand_mt_uint32_range_20_100); 106 | tcase_add_test (tc_general, test_rand_mt_double_range_20_100); 107 | suite_add_tcase (s, tc_general); 108 | 109 | return s; 110 | } 111 | 112 | int 113 | main (void) 114 | { 115 | int number_failed; 116 | Suite *s = rand_suite (); 117 | SRunner *sr = srunner_create (s); 118 | srunner_run_all (sr, CK_NORMAL); 119 | number_failed = srunner_ntests_failed (sr); 120 | srunner_free (sr); 121 | return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 122 | } 123 | -------------------------------------------------------------------------------- /tests/skiplist.c: -------------------------------------------------------------------------------- 1 | /* This file is part of libsnippets 2 | * 3 | * Copyright (C) 2010 Sebastian Dröge 4 | * 5 | * This library is free software: you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library. 17 | * If not, see . 18 | */ 19 | 20 | #ifdef HAVE_CONFIG_H 21 | #include "config.h" 22 | #endif 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | static void 32 | copy_string (void *dest, const void *src) 33 | { 34 | char **d = dest; 35 | const char *s = src; 36 | 37 | *d = strdup (s); 38 | } 39 | 40 | static int 41 | compare_string (const void *a, const void *b, void *user_data) 42 | { 43 | return strcmp (a, b); 44 | } 45 | 46 | START_TEST (test_insert_remove_find) 47 | { 48 | SnippetsSkipList *list; 49 | SnippetsSkipListNode *node; 50 | char **str, **str2; 51 | 52 | list = 53 | snippets_skip_list_new_pointer (10, 0.5, copy_string, free, 54 | compare_string, NULL, NULL, NULL); 55 | 56 | fail_unless (snippets_skip_list_max_level (list) == 10); 57 | fail_unless (abs (snippets_skip_list_probability (list) - 0.5) < 1e-10); 58 | 59 | snippets_skip_list_insert (list, (void *) "abc"); 60 | snippets_skip_list_insert (list, (void *) "bcd"); 61 | snippets_skip_list_insert (list, (void *) "cde"); 62 | snippets_skip_list_insert (list, (void *) "aaa"); 63 | snippets_skip_list_insert (list, (void *) "xyz"); 64 | snippets_skip_list_insert (list, (void *) "jkl"); 65 | snippets_skip_list_insert (list, (void *) "uvw"); 66 | snippets_skip_list_insert (list, (void *) "bcc"); 67 | 68 | fail_unless (snippets_skip_list_length (list) == 8); 69 | 70 | node = snippets_skip_list_head (list); 71 | fail_unless (node != NULL); 72 | str = snippets_skip_list_node_get (node, char *); 73 | fail_unless (str && *str && strcmp (*str, "aaa") == 0); 74 | 75 | node = snippets_skip_list_node_next (node); 76 | fail_unless (node != NULL); 77 | str = snippets_skip_list_node_get (node, char *); 78 | fail_unless (str && *str && strcmp (*str, "abc") == 0); 79 | 80 | node = snippets_skip_list_node_next (node); 81 | fail_unless (node != NULL); 82 | str = snippets_skip_list_node_get (node, char *); 83 | fail_unless (str && *str && strcmp (*str, "bcc") == 0); 84 | 85 | node = snippets_skip_list_node_next (node); 86 | fail_unless (node != NULL); 87 | str = snippets_skip_list_node_get (node, char *); 88 | fail_unless (str && *str && strcmp (*str, "bcd") == 0); 89 | 90 | node = snippets_skip_list_node_next (node); 91 | fail_unless (node != NULL); 92 | str = snippets_skip_list_node_get (node, char *); 93 | fail_unless (str && *str && strcmp (*str, "cde") == 0); 94 | 95 | node = snippets_skip_list_node_next (node); 96 | fail_unless (node != NULL); 97 | str = snippets_skip_list_node_get (node, char *); 98 | fail_unless (str && *str && strcmp (*str, "jkl") == 0); 99 | 100 | node = snippets_skip_list_node_next (node); 101 | fail_unless (node != NULL); 102 | str = snippets_skip_list_node_get (node, char *); 103 | fail_unless (str && *str && strcmp (*str, "uvw") == 0); 104 | 105 | node = snippets_skip_list_node_next (node); 106 | fail_unless (node != NULL); 107 | str = snippets_skip_list_node_get (node, char *); 108 | fail_unless (str && *str && strcmp (*str, "xyz") == 0); 109 | 110 | 111 | node = snippets_skip_list_find (list, "cde", FALSE); 112 | fail_unless (node != NULL); 113 | str = snippets_skip_list_node_get (node, char *); 114 | fail_unless (str && *str && strcmp (*str, "cde") == 0); 115 | 116 | node = snippets_skip_list_find (list, "cdd", FALSE); 117 | fail_unless (node != NULL); 118 | str = snippets_skip_list_node_get (node, char *); 119 | fail_unless (str && *str && strcmp (*str, "bcd") == 0); 120 | 121 | node = snippets_skip_list_find (list, "cde", TRUE); 122 | fail_unless (node != NULL); 123 | str = snippets_skip_list_node_get (node, char *); 124 | fail_unless (str && *str && strcmp (*str, "cde") == 0); 125 | 126 | node = snippets_skip_list_find (list, "cdd", TRUE); 127 | fail_unless (node == NULL); 128 | 129 | snippets_skip_list_remove_value (list, "cde"); 130 | fail_unless (snippets_skip_list_length (list) == 7); 131 | node = snippets_skip_list_find (list, "cde", TRUE); 132 | fail_unless (node == NULL); 133 | 134 | node = snippets_skip_list_find (list, "abc", TRUE); 135 | fail_unless (node != NULL); 136 | snippets_skip_list_remove (list, node); 137 | fail_unless (snippets_skip_list_length (list) == 6); 138 | node = snippets_skip_list_find (list, "abc", TRUE); 139 | fail_unless (node == NULL); 140 | 141 | str = NULL; 142 | for (node = snippets_skip_list_head (list); node; 143 | node = snippets_skip_list_node_next (node)) { 144 | str2 = snippets_skip_list_node_get (node, char *); 145 | fail_unless (str2 != NULL); 146 | if (str) { 147 | fail_unless (strcmp (*str, *str2) < 0); 148 | } 149 | str = str2; 150 | } 151 | 152 | str = NULL; 153 | for (node = snippets_skip_list_tail (list); node; 154 | node = snippets_skip_list_node_prev (node)) { 155 | str2 = snippets_skip_list_node_get (node, char *); 156 | fail_unless (str2 != NULL); 157 | if (str) { 158 | fail_unless (strcmp (*str, *str2) > 0); 159 | } 160 | str = str2; 161 | } 162 | 163 | snippets_skip_list_remove_value (list, "jkl"); 164 | fail_unless (snippets_skip_list_length (list) == 5); 165 | node = snippets_skip_list_find (list, "jkl", TRUE); 166 | fail_unless (node == NULL); 167 | 168 | node = snippets_skip_list_find (list, "uvw", TRUE); 169 | fail_unless (node != NULL); 170 | snippets_skip_list_remove (list, node); 171 | fail_unless (snippets_skip_list_length (list) == 4); 172 | node = snippets_skip_list_find (list, "uvw", TRUE); 173 | fail_unless (node == NULL); 174 | 175 | snippets_skip_list_remove_value (list, "bcc"); 176 | fail_unless (snippets_skip_list_length (list) == 3); 177 | node = snippets_skip_list_find (list, "bcc", TRUE); 178 | fail_unless (node == NULL); 179 | 180 | node = snippets_skip_list_find (list, "aaa", TRUE); 181 | fail_unless (node != NULL); 182 | snippets_skip_list_remove (list, node); 183 | fail_unless (snippets_skip_list_length (list) == 2); 184 | node = snippets_skip_list_find (list, "aaa", TRUE); 185 | fail_unless (node == NULL); 186 | 187 | node = snippets_skip_list_find (list, "xyz", FALSE); 188 | fail_unless (node != NULL); 189 | str = snippets_skip_list_node_get (node, char *); 190 | fail_unless (str && *str && strcmp (*str, "xyz") == 0); 191 | 192 | node = snippets_skip_list_find (list, "bcd", FALSE); 193 | fail_unless (node != NULL); 194 | str = snippets_skip_list_node_get (node, char *); 195 | fail_unless (str && *str && strcmp (*str, "bcd") == 0); 196 | 197 | snippets_skip_list_free (list); 198 | } 199 | 200 | END_TEST; 201 | 202 | START_TEST (test_copy) 203 | { 204 | SnippetsSkipList *list, *copy; 205 | SnippetsSkipListNode *node, *node2; 206 | char **str, **str2; 207 | 208 | list = 209 | snippets_skip_list_new_pointer (10, 0.5, copy_string, free, 210 | compare_string, NULL, NULL, NULL); 211 | 212 | snippets_skip_list_insert (list, (void *) "abc"); 213 | snippets_skip_list_insert (list, (void *) "bcd"); 214 | snippets_skip_list_insert (list, (void *) "cde"); 215 | snippets_skip_list_insert (list, (void *) "aaa"); 216 | snippets_skip_list_insert (list, (void *) "abc"); 217 | snippets_skip_list_insert (list, (void *) "xyz"); 218 | snippets_skip_list_insert (list, (void *) "jkl"); 219 | snippets_skip_list_insert (list, (void *) "uvw"); 220 | snippets_skip_list_insert (list, (void *) "bcc"); 221 | 222 | copy = snippets_skip_list_copy (list); 223 | 224 | fail_unless (snippets_skip_list_length (list) == 8); 225 | fail_unless (snippets_skip_list_length (copy) == 8); 226 | 227 | for (node = snippets_skip_list_head (list), node2 = 228 | snippets_skip_list_head (copy); node || node2; 229 | node = snippets_skip_list_node_next (node), node2 = 230 | snippets_skip_list_node_next (node2)) { 231 | fail_unless (node != NULL && node2 != NULL); 232 | 233 | str = snippets_skip_list_node_get (node, char *); 234 | str2 = snippets_skip_list_node_get (node2, char *); 235 | 236 | fail_unless (str != NULL && str2 != NULL); 237 | fail_unless (str != str2); 238 | fail_unless (*str != NULL && *str2 != NULL); 239 | fail_unless (*str != *str2); 240 | fail_unless (strcmp (*str, *str2) == 0); 241 | } 242 | 243 | snippets_skip_list_free (list); 244 | snippets_skip_list_free (copy); 245 | } 246 | 247 | END_TEST; 248 | 249 | typedef struct _TestData TestData; 250 | struct _TestData 251 | { 252 | uint32_t val[4]; 253 | }; 254 | 255 | static int 256 | compare_data (const void *o1, const void *o2, void *user_data) 257 | { 258 | const uint32_t *a = ((TestData *) o1)->val; 259 | const uint32_t *b = ((TestData *) o2)->val; 260 | uint64_t *calls = (uint64_t *) user_data; 261 | 262 | if (calls) 263 | *calls = *calls + 1; 264 | 265 | if (a[0] < b[0]) 266 | return -1; 267 | if (a[0] > b[0]) 268 | return 1; 269 | if (a[1] < b[1]) 270 | return -1; 271 | if (a[1] > b[1]) 272 | return 1; 273 | if (a[2] < b[2]) 274 | return -1; 275 | if (a[2] > b[2]) 276 | return 1; 277 | if (a[3] < b[3]) 278 | return -1; 279 | if (a[3] > b[3]) 280 | return 1; 281 | return 0; 282 | } 283 | 284 | START_TEST (test_non_pointer) 285 | { 286 | SnippetsSkipList *list; 287 | SnippetsSkipListNode *node; 288 | TestData test_data = { {0,} 289 | }; 290 | TestData *data1, *data2; 291 | 292 | list = 293 | snippets_skip_list_new (10, 0.5, sizeof (TestData), NULL, NULL, 294 | compare_data, NULL, NULL, NULL); 295 | 296 | test_data.val[0] = 1; 297 | snippets_skip_list_insert (list, &test_data); 298 | 299 | test_data.val[0] = 2; 300 | snippets_skip_list_insert (list, &test_data); 301 | 302 | test_data.val[0] = 3; 303 | snippets_skip_list_insert (list, &test_data); 304 | 305 | test_data.val[0] = 4; 306 | snippets_skip_list_insert (list, &test_data); 307 | 308 | fail_unless (snippets_skip_list_length (list) == 4); 309 | 310 | data1 = NULL; 311 | for (node = snippets_skip_list_head (list); node; 312 | node = snippets_skip_list_node_next (node)) { 313 | data2 = snippets_skip_list_node_get (node, TestData); 314 | fail_unless (data2 != NULL); 315 | if (data1) 316 | fail_unless (compare_data (data1, data2, NULL) < 0); 317 | data1 = data2; 318 | } 319 | 320 | snippets_skip_list_free (list); 321 | } 322 | 323 | END_TEST; 324 | 325 | START_TEST (test_find_performance) 326 | { 327 | SnippetsRand *rand; 328 | SnippetsSkipList *list; 329 | SnippetsSkipListNode *node; 330 | TestData *test_data; 331 | static const int N = 32000; 332 | static const int M = 16000; 333 | int i; 334 | uint64_t calls; 335 | TestData **data1, **data2; 336 | 337 | rand = snippets_rand_new (time (0)); 338 | 339 | test_data = malloc (N * sizeof (TestData)); 340 | for (i = 0; i < N; i++) { 341 | test_data[i].val[0] = snippets_rand_uint32 (rand); 342 | test_data[i].val[1] = snippets_rand_uint32 (rand); 343 | test_data[i].val[2] = snippets_rand_uint32 (rand); 344 | test_data[i].val[3] = snippets_rand_uint32 (rand); 345 | } 346 | 347 | list = 348 | snippets_skip_list_new_pointer (10, 0.5, NULL, NULL, compare_data, &calls, 349 | NULL, NULL); 350 | 351 | calls = 0; 352 | for (i = 0; i < N; i++) 353 | snippets_skip_list_insert (list, &test_data[i]); 354 | fail_unless (((double) calls) / ((double) N) <= 48); 355 | 356 | data1 = NULL; 357 | for (node = snippets_skip_list_head (list); node; 358 | node = snippets_skip_list_node_next (node)) { 359 | data2 = snippets_skip_list_node_get (node, TestData *); 360 | fail_unless (data2 != NULL); 361 | if (data1) 362 | fail_unless (compare_data (*data1, *data2, NULL) < 0); 363 | data1 = data2; 364 | } 365 | 366 | calls = 0; 367 | for (i = 0; i < M; i++) { 368 | uint32_t r = snippets_rand_uint32_range (rand, 0, N); 369 | 370 | node = snippets_skip_list_find (list, &test_data[r], TRUE); 371 | fail_unless (node != NULL); 372 | data1 = snippets_skip_list_node_get (node, TestData *); 373 | fail_unless (compare_data (*data1, &test_data[r], NULL) == 0); 374 | } 375 | fail_unless (((double) calls) / ((double) N) <= 48); 376 | 377 | snippets_skip_list_free (list); 378 | free (test_data); 379 | snippets_rand_free (rand); 380 | } 381 | 382 | END_TEST; 383 | 384 | static Suite * 385 | skiplist_suite (void) 386 | { 387 | Suite *s = suite_create ("SkipList"); 388 | 389 | /* Core test case */ 390 | TCase *tc_general = tcase_create ("general"); 391 | tcase_set_timeout (tc_general, 60); 392 | tcase_add_test (tc_general, test_insert_remove_find); 393 | tcase_add_test (tc_general, test_copy); 394 | tcase_add_test (tc_general, test_non_pointer); 395 | tcase_add_test (tc_general, test_find_performance); 396 | suite_add_tcase (s, tc_general); 397 | 398 | return s; 399 | } 400 | 401 | int 402 | main (void) 403 | { 404 | int number_failed; 405 | Suite *s = skiplist_suite (); 406 | SRunner *sr = srunner_create (s); 407 | srunner_run_all (sr, CK_NORMAL); 408 | number_failed = srunner_ntests_failed (sr); 409 | srunner_free (sr); 410 | return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 411 | } 412 | --------------------------------------------------------------------------------