diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2020-12-01 13:33:34 +0100 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2020-12-01 13:33:34 +0100 |
commit | c8bf38e5fb717d40635a2a89b22ed71b0de4266b (patch) | |
tree | 63751b2f5497c6f99e1c6a78f23a8e6e5c49833f /tests |
Squashed 'dependencies/uthash/' content from commit 8e67ced
git-subtree-dir: dependencies/uthash
git-subtree-split: 8e67ced1d1c5bd8141c542a22630e6de78aa6b90
Diffstat (limited to 'tests')
219 files changed, 12921 insertions, 0 deletions
diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 000000000..fcb751984 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,120 @@ +#CC=clang +HASHDIR = ../src +UTILS = emit_keys +PROGS = test1 test2 test3 test4 test5 test6 test7 test8 test9 \ + test10 test11 test12 test13 test14 test15 test16 test17 \ + test18 test19 test20 test21 test22 test23 test24 test25 \ + test26 test27 test28 test29 test30 test31 test32 test33 \ + test34 test35 test36 test37 test38 test39 test40 test41 \ + test42 test43 test44 test45 test46 test47 test48 test49 \ + test50 test51 test52 test53 test54 test55 test56 test57 \ + test58 test59 test60 test61 test62 test63 test64 test65 \ + test66 test67 test68 test69 test70 test71 test72 test73 \ + test74 test75 test76 test77 test78 test79 test80 test81 \ + test82 test83 test84 test85 test86 test87 test88 test89 \ + test90 test91 test92 test93 test94 test95 +CFLAGS += -I$(HASHDIR) +#CFLAGS += -DHASH_BLOOM=16 +#CFLAGS += -O2 +CFLAGS += -g +#CFLAGS += -Wstrict-aliasing=2 +CFLAGS += -Wall +#CFLAGS += -Wextra +#CFLAGS += -std=c89 +CFLAGS += ${EXTRA_CFLAGS} + +ifeq ($(HASH_DEBUG),1) +CFLAGS += -DHASH_DEBUG=1 +endif + +ifeq ($(HASH_PEDANTIC),1) +CFLAGS += -pedantic +endif + +TEST_TARGET=run_tests +TESTS=./do_tests + +# detect Cygwin +ifneq ($(strip $(shell $(CC) -v 2>&1 |grep "cygwin")),) + TESTS=./do_tests.cygwin +endif + +# detect MinGW +ifneq ($(strip $(shell $(CC) -v 2>&1 |grep "mingw")),) + TEST_TARGET=run_tests_mingw + TESTS=./do_tests.mingw +endif + +#detect Linux (platform specific utilities) +ifneq ($(strip $(shell $(CC) -v 2>&1 |grep "linux")),) + PLAT_UTILS = hashscan sleep_test +endif + +#detect FreeBSD (platform specific utilities) +ifeq ($(strip $(shell uname -s)), FreeBSD) + ifeq ($(shell if [ `sysctl -n kern.osreldate` -ge 0801000 ]; then echo "ok"; fi), ok) + PLAT_UTILS = hashscan sleep_test + endif +endif + +all: $(PROGS) $(UTILS) $(PLAT_UTILS) keystat $(TEST_TARGET) + +tests_only: $(PROGS) $(TEST_TARGET) + +GITIGN = .gitignore +MKGITIGN = [ -f "$(GITIGN)" ] || echo "$(GITIGN)" > $(GITIGN); grep -q '^\$@$$' $(GITIGN) || echo "$@" >> $(GITIGN) + +debug: + $(MAKE) all HASH_DEBUG=1 + +pedantic: + $(MAKE) all HASH_PEDANTIC=1 + +cplusplus: + CC="$(CXX) -x c++" $(MAKE) all + +thorough: + $(MAKE) clean && $(MAKE) all EXTRA_CFLAGS='-pedantic' + $(MAKE) clean && $(MAKE) all EXTRA_CFLAGS='-pedantic -DHASH_BLOOM=16' + $(MAKE) clean && $(MAKE) tests_only EXTRA_CFLAGS='-pedantic -DHASH_BLOOM=16 -DHASH_DEBUG -DNO_DECLTYPE' + $(MAKE) clean && CC="$(CXX) -x c++" $(MAKE) all EXTRA_CFLAGS='-pedantic' + $(MAKE) clean && CC="$(CXX) -x c++" $(MAKE) all EXTRA_CFLAGS='-pedantic -DHASH_BLOOM=16' + $(MAKE) clean && CC="$(CXX) -x c++" $(MAKE) tests_only EXTRA_CFLAGS='-pedantic -DHASH_BLOOM=16 -DHASH_DEBUG -DNO_DECLTYPE' + +example: example.c $(HASHDIR)/uthash.h + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(@).c + +$(PROGS) $(UTILS) : $(HASHDIR)/uthash.h + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(@).c + @$(MKGITIGN) + +hashscan : $(HASHDIR)/uthash.h + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(@).c + @$(MKGITIGN) + +sleep_test : $(HASHDIR)/uthash.h + $(CC) $(CPPFLAGS) $(CFLAGS) -DHASH_BLOOM=16 $(LDFLAGS) -o $@ $(@).c + @$(MKGITIGN) + +keystat : $(HASHDIR)/uthash.h + $(CC) $(CPPFLAGS) $(CFLAGS) -DHASH_FUNCTION=HASH_BER $(LDFLAGS) -o keystat.BER keystat.c + $(CC) $(CPPFLAGS) $(CFLAGS) -DHASH_FUNCTION=HASH_FNV $(LDFLAGS) -o keystat.FNV keystat.c + $(CC) $(CPPFLAGS) $(CFLAGS) -DHASH_FUNCTION=HASH_JEN $(LDFLAGS) -o keystat.JEN keystat.c + $(CC) $(CPPFLAGS) $(CFLAGS) -DHASH_FUNCTION=HASH_OAT $(LDFLAGS) -o keystat.OAT keystat.c + $(CC) $(CPPFLAGS) $(CFLAGS) -DHASH_FUNCTION=HASH_SAX $(LDFLAGS) -o keystat.SAX keystat.c + $(CC) $(CPPFLAGS) $(CFLAGS) -DHASH_FUNCTION=HASH_SFH $(LDFLAGS) -o keystat.SFH keystat.c + +run_tests: $(PROGS) + perl $(TESTS) + +run_tests_mingw: $(PROGS) + /bin/bash do_tests.mingw + +astyle: + astyle -n --style=kr --indent-switches --add-brackets *.c + +.PHONY: clean astyle + +clean: + rm -f $(UTILS) $(PLAT_UTILS) $(PROGS) test*.out keystat.??? example hashscan sleep_test *.exe $(GITIGN) + rm -rf *.dSYM diff --git a/tests/README b/tests/README new file mode 100644 index 000000000..fc25b9b41 --- /dev/null +++ b/tests/README @@ -0,0 +1,127 @@ +Automated tests for uthash +============================================================================== +Run "make" in this directory to build the tests and run them. + +test1: make 10-item hash, iterate and print each one +test2: make 10-item hash, lookup items with even keys, print +test3: make 10-item hash, delete items with even keys, print others +test4: 10 structs have dual hash handles, separate keys +test5: 10 structs have dual hash handles, lookup evens by alt key +test6: test alt malloc macros (and alt memcmp macro) +test7: test alt malloc macros with 1000 structs so bucket expansion occurs +test8: test num_items counter in UT_hash_handle +test9: test "find" after bucket expansion +test10: dual-hash handle test, bucket expansion on one and not the other +test11: read dat file of names into hash, sort them and print +test12: create hash with string keys, add 10 items, lookup each item +test13: make 10-item hash, delete items with even keys, reverse print others +test14: read dat file of names into hash, read file again and lookup each one +test15: build string-keyed hash of 3 items, lookup one item (c.f. test40.c) +test16: hash on aggregate key, iterate, lookup, using generalized macros +test17: sort, add more items, sort again +test18: test pathological HASH_DEL(a,a) scenario (single head,deletee variable) +test19: sort two hash tables with shared elements using HASH_SRT +test20: test a 5-byte "binary" key +test21: test a structure key (userguide) +test22: test multi-field key using flexible array member (userguide utf32) +test23: test whether delete in iteration works +test24: make 10-item hash and confirm item count (HASH_COUNT) +test25: CDL / DL / LL tests +test26: test the linked list sort macros in utlist.h +test27: LL_APPEND, SORT +test28: CDL / DL / LL tests +test29: DL_APPEND, SORT +test30: CDL_PREPEND, SORT +test31: CDL_PREPEND, SORT +test32: DL_PREPEND +test33: LL_PREPEND +test34: CDL_PREPEND +test35: CDL_PREPEND +test36: HASH_SELECT +test37: HASH_CLEAR +test38: find-or-add test on integer keys in short loop +test39: HASH_ADD_KEYPTR then HASH_FIND using array element as key pointer +test40: HASH_ADD_KEYPTR on string keys; pointer equivalent to test15.c +test41: test LL_FOREACH_SAFE,DL_FOREACH_SAFE,CDL_FOREACH_SAFE +test42: test LL_SEARCH, LL_SEARCH_SCALAR, and DL and CDL counterparts +test43: test utarray with intpair objects +test44: test utarray with int objects +test45: test utarray with int objects +test46: test utarray with char* objects +test47: test utstring +test48: test utarray of int +test49: test utarray of str +test50: test utarray of long +test51: test utarray of intpair +test52: test utarray of intchar +test53: test utstring +test54: test utstring +test55: test utstring +test56: test uthash, utlist and utstring together for #define conflicts etc +test57: test uthash HASH_ADD_PTR and HASH_FIND_PTR +test58: test HASH_ITER macro +test59: sample of multi-level hash +test60: sample of multi-level hash that also does HASH_DEL and free +test61: test utarray_find +test62: test macros used in safe unaligned reads on non-Intel type platforms +test63: LL_CONCAT test +test64: DL_CONCAT test +test65: LRU cache example courtesy of jehiah.cz with modifications +test66: test example where output variable to HASH_FIND needs extra parens +test67: test utarray_prev +test68: test DL_REPLACE_ELEM (Zoltán Lajos Kis) +test69: test DL_PREPEND_ELEM (Zoltán Lajos Kis) +test70: test LL_REPLACE_ELEM (Zoltán Lajos Kis) +test71: test LL_PREPEND_ELEM (Zoltán Lajos Kis) +test72: test CDL_REPLACE_ELEM (Zoltán Lajos Kis) +test73: test CDL_PREPEND_ELEM (Zoltán Lajos Kis) +test74: test utstring with utstring_find (Joe Wei) +test75: test utstring with utstring_findR (Joe Wei) +test76: test utstring with _utstring_find (Joe Wei) +test77: test utstring with _utstring_findR (Joe Wei) +test78: test utlist "2" family with flexible Prev/Next naming eg. DL_DELETE2 +test79: test HASH_REPLACE +test80: test utarray_insert past end of array +test81: test utarray_insert past end of array +test82: test utarray_inserta past end of array +test83: test HASH_REPLACE_STR with char[] key +test84: test HASH_REPLACE_STR with char* key +test85: test HASH_OVERHEAD on null and non null hash +test86: test *_APPEND_ELEM / *_PREPEND_ELEM (Thilo Schulz) +test87: test HASH_ADD_INORDER() macro (Thilo Schulz) +test88: test alt memcmp and strlen macros +test89: test code from the tinydtls project +test90: regression-test HASH_ADD_KEYPTR_INORDER (IronBug) +test91: test LL_INSERT_INORDER etc. + +Other Make targets +================================================================================ +pedantic: makes the tests with extra CFLAGS for pedantic compiling +cplusplus: compiles all the C tests using the C++ compiler to test compatibility +debug: makes the tests with debugging symbols and no optimization +example: builds the 'example' program from the user guide +================================================================================ + +Testing a specific hash function +-------------------------------- +Set EXTRA_CFLAGS with this Makefile to use a specific hash function: + EXTRA_CFLAGS=-DHASH_FUNCTION=HASH_BER make + +Other files +================================================================================ +keystats: key statistics analyzer. See the uthash User Guide. +emit_keys: reads a data file of unique strings, emits as keys w/HASH_EMIT_KEYS=1 +all_funcs: a script which executes the test suite with every hash function +win32tests:builds and runs the test suite under Microsoft Visual Studio + +LINUX/FREEBSD +------------- +hashscan: tool to examine a running process and get info on its hash tables +test_sleep:used as a subject for inspection by hashscan + +Manual performance testing +================================================================================ + # test performance characteristics on keys that are English dictionary words + emit_keys /usr/share/dict/words > words.keys + ./keystats words.keys + diff --git a/tests/all_funcs b/tests/all_funcs new file mode 100755 index 000000000..f61a410c6 --- /dev/null +++ b/tests/all_funcs @@ -0,0 +1,13 @@ +#!/bin/bash + +function proceed { + read -p "proceed ? [n] " response + if [ "$response" != "y" ]; then exit -1; fi +} + +make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_BER'; proceed +make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_FNV'; proceed +make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_JEN'; proceed +make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_OAT'; proceed +make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_SAX'; proceed +make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_SFH'; proceed diff --git a/tests/bloom_perf.c b/tests/bloom_perf.c new file mode 100644 index 000000000..6a9abf19f --- /dev/null +++ b/tests/bloom_perf.c @@ -0,0 +1,82 @@ +#include <stdlib.h> /* malloc */ +#include <sys/time.h> /* gettimeofday */ +#include <errno.h> /* perror */ +#include <stdio.h> /* printf */ +#include "uthash.h" + +#define BUFLEN 20 +#if 0 +#undef uthash_expand_fyi +#define uthash_expand_fyi(tbl) printf("expanding to %d buckets\n", tbl->num_buckets) +#endif + +typedef struct name_rec { + char boy_name[BUFLEN]; + UT_hash_handle hh; +} name_rec; + +int main(int argc,char *argv[]) +{ + name_rec *name, *names=NULL; + char linebuf[BUFLEN]; + FILE *file; + int i=0,j,nloops=3,loopnum=0,miss; + struct timeval tv1,tv2; + long elapsed_usec; + if (argc > 1) { + nloops = atoi(argv[1]); + } + + if ( (file = fopen( "test14.dat", "r" )) == NULL ) { + perror("can't open: "); + exit(-1); + } + + while (fgets(linebuf,BUFLEN,file) != NULL) { + i++; + if ( (name = (name_rec*)malloc(sizeof(name_rec))) == NULL) { + exit(-1); + } + strcpy(name->boy_name, linebuf); + HASH_ADD_STR(names,boy_name,name); + } + +again: + if (fseek(file,0,SEEK_SET) == -1) { + fprintf(stderr,"fseek failed: %s\n", strerror(errno)); + } + j=0; + + if (gettimeofday(&tv1,NULL) == -1) { + perror("gettimeofday: "); + } + while (fgets(linebuf,BUFLEN,file) != NULL) { + /* if we do 10 loops, the first has a 0% miss rate, + * the second has a 10% miss rate, etc */ + miss = ((rand()*1.0/RAND_MAX) < (loopnum*1.0/nloops)) ? 1 : 0; + /* generate a miss if we want one */ + if (miss) { + linebuf[0]++; + if (linebuf[1] != '\0') { + linebuf[1]++; + } + } + HASH_FIND_STR(names,linebuf,name); + if (name) { + j++; + } + } + if (gettimeofday(&tv2,NULL) == -1) { + perror("gettimeofday: "); + } + elapsed_usec = ((tv2.tv_sec - tv1.tv_sec) * 1000000) + (tv2.tv_usec - tv1.tv_usec); + printf("lookup on %d of %d (%.2f%%) names succeeded (%.2f usec)\n", j, i, + j*100.0/i, (double)(elapsed_usec)); + if (++loopnum < nloops) { + goto again; + } + fclose(file); + + return 0; +} + diff --git a/tests/bloom_perf.sh b/tests/bloom_perf.sh new file mode 100755 index 000000000..0a04f230a --- /dev/null +++ b/tests/bloom_perf.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +BITS="16" + +cc -I../src -O3 -Wall -m64 bloom_perf.c -o bloom_perf.none +for bits in $BITS +do +cc -I../src -DHASH_BLOOM=$bits -O3 -Wall -m64 bloom_perf.c -o bloom_perf.$bits +done + +for bits in none $BITS +do +echo +echo "using $bits-bit filter:" +./bloom_perf.$bits 10 +done + diff --git a/tests/do_tests b/tests/do_tests new file mode 100755 index 000000000..574403f2d --- /dev/null +++ b/tests/do_tests @@ -0,0 +1,21 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +my @tests; +for (glob "test*[0-9]") { + push @tests, $_ if -e "$_.ans"; +} + +my $num_failed=0; + +for my $test (@tests) { + `./$test > $test.out`; + `diff $test.out $test.ans`; + print "$test failed\n" if $?; + $num_failed++ if $?; +} + +print scalar @tests . " tests conducted, $num_failed failed.\n"; +exit $num_failed; diff --git a/tests/do_tests.cygwin b/tests/do_tests.cygwin new file mode 100755 index 000000000..0c01ebee0 --- /dev/null +++ b/tests/do_tests.cygwin @@ -0,0 +1,22 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +my @tests; +for (glob "test*[0-9].exe") { + push @tests, "$_" if -e substr($_, 0, - 4).".ans"; +} + +my $num_failed=0; + +for my $test (@tests) { + `./$test > $test.out`; + my $ansfile = substr($test, 0, - 4).".ans"; + `diff $test.out $ansfile`; + print "$test failed\n" if $?; + $num_failed++ if $?; +} + +print scalar @tests . " tests conducted, $num_failed failed.\n"; +exit $num_failed; diff --git a/tests/do_tests.mingw b/tests/do_tests.mingw new file mode 100644 index 000000000..4dcf49834 --- /dev/null +++ b/tests/do_tests.mingw @@ -0,0 +1,20 @@ +#!/bin/bash + +echo "MinGW test script starting" + +for f in test*.exe +do + t=`echo $f | sed s/.exe//` + "./$f" > "$t.out" + diff -qb "$t.out" "$t.ans" + if [ $? -eq 1 ] + then + echo "$f failed" + else + true # can't have empty else + #echo "$f passed" + fi +done + +echo +echo "All tests complete" diff --git a/tests/do_tests_win32.cmd b/tests/do_tests_win32.cmd new file mode 100644 index 000000000..be8930170 --- /dev/null +++ b/tests/do_tests_win32.cmd @@ -0,0 +1,16 @@ +:: this compiles and runs the test suite under Visual Studio 2008 +::@echo off +call "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat" > vc.out +::call "C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat" > vc.out +set "COMPILE=cl.exe /I ..\src /EHsc /nologo" +echo compiling... +%COMPILE% tdiff.cpp > compile.out +::for %%f in (test*.c) do %COMPILE% /Tp %%f >> compile.out +for %%f in (test*.c) do %COMPILE% /Tc %%f >> compile.out +echo running tests... +for %%f in (test*.exe) do %%f > %%~nf.out +echo scanning for failures... +for %%f in (test*.out) do tdiff %%f %%~nf.ans +echo tests completed +::for %%f in (test*.out test*.obj test*.exe vc.out compile.out tdiff.obj tdiff.exe) do del %%f +pause diff --git a/tests/emit_keys.c b/tests/emit_keys.c new file mode 100644 index 000000000..0b98689eb --- /dev/null +++ b/tests/emit_keys.c @@ -0,0 +1,48 @@ +#include <stdlib.h> /* malloc */ +#include <errno.h> /* perror */ +#include <stdio.h> /* printf */ +#include <unistd.h> /* write */ + +/* this define must precede uthash.h */ +#define HASH_EMIT_KEYS 1 +#include "uthash.h" + +#define BUFLEN 30 + +typedef struct name_rec { + char boy_name[BUFLEN]; + UT_hash_handle hh; +} name_rec; + +int main(int argc,char *argv[]) +{ + name_rec *name, *names=NULL; + char linebuf[BUFLEN]; + FILE *file; + int i=0; + + if (argc != 2) { + fprintf(stderr,"usage: %s file\n", argv[0]); + exit(-1); + } + + if ( (file = fopen( argv[1], "r" )) == NULL ) { + perror("can't open: "); + exit(-1); + } + + while (fgets(linebuf,BUFLEN,file) != NULL) { + name = (name_rec*)malloc(sizeof(name_rec)); + if (name == NULL) { + exit(-1); + } + strcpy(name->boy_name, linebuf); + HASH_ADD_STR(names,boy_name,name); + i++; + } + + fprintf(stderr,"%d keys emitted.\n", i); + fclose(file); + return 0; +} + diff --git a/tests/example.c b/tests/example.c new file mode 100644 index 000000000..a85f422d4 --- /dev/null +++ b/tests/example.c @@ -0,0 +1,149 @@ +#include <stdio.h> /* gets */ +#include <stdlib.h> /* atoi, malloc */ +#include <string.h> /* strcpy */ +#include "uthash.h" + +struct my_struct { + int id; /* key */ + char name[10]; + UT_hash_handle hh; /* makes this structure hashable */ +}; + +struct my_struct *users = NULL; + +void add_user(int user_id, char *name) +{ + struct my_struct *s; + + HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */ + if (s==NULL) { + s = (struct my_struct*)malloc(sizeof(struct my_struct)); + s->id = user_id; + HASH_ADD_INT( users, id, s ); /* id: name of key field */ + } + strcpy(s->name, name); +} + +struct my_struct *find_user(int user_id) +{ + struct my_struct *s; + + HASH_FIND_INT( users, &user_id, s ); /* s: output pointer */ + return s; +} + +void delete_user(struct my_struct *user) +{ + HASH_DEL( users, user); /* user: pointer to deletee */ + free(user); +} + +void delete_all() +{ + struct my_struct *current_user, *tmp; + + HASH_ITER(hh, users, current_user, tmp) { + HASH_DEL(users,current_user); /* delete it (users advances to next) */ + free(current_user); /* free it */ + } +} + +void print_users() +{ + struct my_struct *s; + + for(s=users; s != NULL; s=(struct my_struct*)(s->hh.next)) { + printf("user id %d: name %s\n", s->id, s->name); + } +} + +int name_sort(struct my_struct *a, struct my_struct *b) +{ + return strcmp(a->name,b->name); +} + +int id_sort(struct my_struct *a, struct my_struct *b) +{ + return (a->id - b->id); +} + +void sort_by_name() +{ + HASH_SORT(users, name_sort); +} + +void sort_by_id() +{ + HASH_SORT(users, id_sort); +} + +int main() +{ + char in[10]; + int id=1, running=1; + struct my_struct *s; + unsigned num_users; + + while (running) { + printf(" 1. add user\n"); + printf(" 2. add/rename user by id\n"); + printf(" 3. find user\n"); + printf(" 4. delete user\n"); + printf(" 5. delete all users\n"); + printf(" 6. sort items by name\n"); + printf(" 7. sort items by id\n"); + printf(" 8. print users\n"); + printf(" 9. count users\n"); + printf("10. quit\n"); + gets(in); + switch(atoi(in)) { + case 1: + printf("name?\n"); + add_user(id++, gets(in)); + break; + case 2: + printf("id?\n"); + gets(in); + id = atoi(in); + printf("name?\n"); + add_user(id, gets(in)); + break; + case 3: + printf("id?\n"); + s = find_user(atoi(gets(in))); + printf("user: %s\n", s ? s->name : "unknown"); + break; + case 4: + printf("id?\n"); + s = find_user(atoi(gets(in))); + if (s) { + delete_user(s); + } else { + printf("id unknown\n"); + } + break; + case 5: + delete_all(); + break; + case 6: + sort_by_name(); + break; + case 7: + sort_by_id(); + break; + case 8: + print_users(); + break; + case 9: + num_users=HASH_COUNT(users); + printf("there are %u users\n", num_users); + break; + case 10: + running=0; + break; + } + } + + delete_all(); /* free any structures */ + return 0; +} diff --git a/tests/hashscan.c b/tests/hashscan.c new file mode 100644 index 000000000..c487d9cee --- /dev/null +++ b/tests/hashscan.c @@ -0,0 +1,678 @@ +/* +Copyright (c) 2005-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <inttypes.h> +#include <sys/types.h> /* on OSX, must come before ptrace.h */ +#include <sys/ptrace.h> +#include <unistd.h> +#include <sys/wait.h> +#include <assert.h> + +#ifdef __FreeBSD__ +#include <sys/param.h> /* MAXPATHLEN */ +#include <vm/vm.h> /* VM_PROT_* flags */ +#endif + +#if defined(PT_ATTACH) && !defined(PTRACE_ATTACH) +#define PTRACE_ATTACH PT_ATTACH +#define PTRACE_DETACH PT_DETACH +#endif + +/* need this defined so offsetof can give us bloom offsets in UT_hash_table */ +#define HASH_BLOOM 16 +#include "uthash.h" + +#ifdef __FreeBSD__ +typedef struct { + void *start; + void *end; +} vma_t; +#else +typedef struct { + off_t start; + off_t end; + char perms[4]; /* rwxp */ + char device[5]; /* fd:01 or 00:00 */ +} vma_t; +#endif + +const uint32_t sig = HASH_SIGNATURE; +int verbose=0; +int getkeys=0; + +#define vv(...) do {if (verbose>0) printf(__VA_ARGS__);} while(0) +#define vvv(...) do {if (verbose>1) printf(__VA_ARGS__);} while(0) + +/* these id's are arbitrary, only meaningful within this file */ +#define JEN 1 +#define BER 2 +#define SFH 3 +#define SAX 4 +#define FNV 5 +#define OAT 6 +#define NUM_HASH_FUNCS 7 /* includes id 0, the non-function */ +const char *hash_fcns[] = {"???","JEN","BER","SFH","SAX","FNV","OAT"}; + +/* given a peer key/len/hashv, reverse engineer its hash function */ +static int infer_hash_function(char *key, size_t keylen, uint32_t hashv) +{ + uint32_t ohashv; + /* BER SAX FNV OAT JEN SFH */ + HASH_JEN(key,keylen,ohashv); + if (ohashv == hashv) { + return JEN; + } + HASH_BER(key,keylen,ohashv); + if (ohashv == hashv) { + return BER; + } + HASH_SFH(key,keylen,ohashv); + if (ohashv == hashv) { + return SFH; + } + HASH_SAX(key,keylen,ohashv); + if (ohashv == hashv) { + return SAX; + } + HASH_FNV(key,keylen,ohashv); + if (ohashv == hashv) { + return FNV; + } + HASH_OAT(key,keylen,ohashv); + if (ohashv == hashv) { + return OAT; + } + return 0; +} + +/* read peer's memory from addr for len bytes, store into our dst */ +#ifdef __FreeBSD__ +static int read_mem(void *dst, pid_t pid, void *start, size_t len) +{ + struct ptrace_io_desc io_desc; + int ret; + + io_desc.piod_op = PIOD_READ_D; + io_desc.piod_offs = start; + io_desc.piod_addr = dst; + io_desc.piod_len = len; + + ret = ptrace(PT_IO, pid, (void *) &io_desc, 0); + + if (ret) { + vv("read_mem: ptrace failed: %s\n", strerror(errno)); + return -1; + } else if (io_desc.piod_len != len) { + vv("read_mem: short read!\n"); + return -1; + } + + return 0; +} +#else +static int read_mem(void *dst, int fd, off_t start, size_t len) +{ + int rc; + size_t bytes_read=0; + if (lseek(fd, start, SEEK_SET) == (off_t)-1) { + fprintf(stderr, "lseek failed: %s\n", strerror(errno)); + return -1; + } + while ( len && ((rc=read(fd, (char*)dst+bytes_read, len)) > 0)) { + len -= rc; + bytes_read += rc; + } + if (rc==-1) { + vv("read_mem failed (%s)\n",strerror(errno)); + } + if ((len != 0 && rc >= 0)) { + vv("INTERNAL ERROR\n"); + } + return (rc == -1) ? -1 : 0; +} +#endif + +/* later compensate for possible presence of bloom filter */ +static char *tbl_from_sig_addr(char *sig) +{ + return (sig - offsetof(UT_hash_table,signature)); +} + +#define HS_BIT_TEST(v,i) (v[i/8] & (1U << (i%8))) +static void found(int fd, char* peer_sig, pid_t pid) +{ + UT_hash_table *tbl=NULL; + UT_hash_bucket *bkts=NULL; + UT_hash_handle hh; + size_t i, bloom_len, bloom_bitlen, bloom_on_bits=0,bloom_off_bits=0; + char *peer_tbl, *peer_bloom_sig, *peer_bloom_nbits, *peer_bloombv_ptr, + *peer_bloombv, *peer_bkts, *peer_hh, *key=NULL; + const char *peer_key; + const char *hash_fcn = NULL; + unsigned char *bloombv=NULL; + static int fileno=0; + char keyfile[50]; + unsigned char bloom_nbits=0; + int keyfd=-1, mode=S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, + hash_fcn_hits[NUM_HASH_FUNCS], hash_fcn_winner; + unsigned max_chain=0; + uint32_t bloomsig; + int has_bloom_filter_fields = 0; + + for(i=0; i < NUM_HASH_FUNCS; i++) { + hash_fcn_hits[i]=0; + } + + if (getkeys) { + snprintf(keyfile, sizeof(keyfile), "/tmp/%u-%u.key", (unsigned)pid,fileno++); + if ( (keyfd = open(keyfile, O_WRONLY|O_CREAT|O_TRUNC, mode)) == -1) { + fprintf(stderr, "can't open %s: %s\n", keyfile, strerror(errno)); + exit(-1); + } + } + + vv("found signature at peer %p\n", (void*)peer_sig); + peer_tbl = tbl_from_sig_addr(peer_sig); + vvv("reading table at peer %p\n", (void*)peer_tbl); + + if ( (tbl = (UT_hash_table*)malloc(sizeof(UT_hash_table))) == NULL) { + fprintf(stderr, "out of memory\n"); + exit(-1); + } +#ifdef __FreeBSD__ + if (read_mem(tbl, pid, (void *)peer_tbl, sizeof(UT_hash_table)) != 0) { +#else + if (read_mem(tbl, fd, (off_t)peer_tbl, sizeof(UT_hash_table)) != 0) { +#endif + fprintf(stderr, "failed to read peer memory\n"); + goto done; + } + + /* got the table. how about the buckets */ + peer_bkts = (char*)tbl->buckets; + vvv("reading %u buckets at peer %p\n", tbl->num_buckets, (void*)peer_bkts); + bkts = (UT_hash_bucket*)malloc(sizeof(UT_hash_bucket)*tbl->num_buckets); + if (bkts == NULL) { + fprintf(stderr, "out of memory\n"); + goto done; + } +#ifdef __FreeBSD__ + if (read_mem(bkts, pid, (void *)peer_bkts, sizeof(UT_hash_bucket)*tbl->num_buckets) != 0) { +#else + if (read_mem(bkts, fd, (off_t)peer_bkts, sizeof(UT_hash_bucket)*tbl->num_buckets) != 0) { +#endif + fprintf(stderr, "failed to read peer memory\n"); + goto done; + } + + vvv("scanning %u peer buckets\n", tbl->num_buckets); + for(i=0; i < tbl->num_buckets; i++) { + vvv("bucket %u has %u items\n", (unsigned)i, (unsigned)(bkts[i].count)); + if (bkts[i].count > max_chain) { + max_chain = bkts[i].count; + } + if (bkts[i].expand_mult) { + vvv(" bucket %u has expand_mult %u\n", (unsigned)i, (unsigned)(bkts[i].expand_mult)); + } + + vvv("scanning bucket %u chain:\n", (unsigned)i); + peer_hh = (char*)bkts[i].hh_head; + while(peer_hh) { +#ifdef __FreeBSD__ + if (read_mem(&hh, pid, (void *)peer_hh, sizeof(hh)) != 0) { +#else + if (read_mem(&hh, fd, (off_t)peer_hh, sizeof(hh)) != 0) { +#endif + fprintf(stderr, "failed to read peer memory\n"); + goto done; + } + if ((char*)hh.tbl != peer_tbl) { + goto done; + } + peer_hh = (char*)hh.hh_next; + peer_key = (const char*)(hh.key); + /* malloc space to read the key, and read it */ + if ( (key = (char*)malloc(sizeof(hh.keylen))) == NULL) { + fprintf(stderr, "out of memory\n"); + exit(-1); + } +#ifdef __FreeBSD__ + if (read_mem(key, pid, (void*)peer_key, hh.keylen) != 0) { +#else + if (read_mem(key, fd, (off_t)peer_key, hh.keylen) != 0) { +#endif + fprintf(stderr, "failed to read peer memory\n"); + goto done; + } + hash_fcn_hits[infer_hash_function(key,hh.keylen,hh.hashv)]++; + /* write the key if requested */ + if (getkeys) { + write(keyfd, &hh.keylen, sizeof(unsigned)); + write(keyfd, key, hh.keylen); + } + free(key); + key=NULL; + } + } + + /* does it have a bloom filter? */ + peer_bloom_sig = peer_tbl + offsetof(UT_hash_table, bloom_sig); + peer_bloombv_ptr = peer_tbl + offsetof(UT_hash_table, bloom_bv); + peer_bloom_nbits = peer_tbl + offsetof(UT_hash_table, bloom_nbits); + vvv("looking for bloom signature at peer %p\n", (void*)peer_bloom_sig); +#ifdef __FreeBSD__ + if ((read_mem(&bloomsig, pid, (void *)peer_bloom_sig, sizeof(uint32_t)) == 0) && + (bloomsig == HASH_BLOOM_SIGNATURE)) { +#else + if ((read_mem(&bloomsig, fd, (off_t)peer_bloom_sig, sizeof(uint32_t)) == 0) && + (bloomsig == HASH_BLOOM_SIGNATURE)) { +#endif + vvv("bloom signature (%x) found\n",bloomsig); + /* bloom found. get at bv, nbits */ +#ifdef __FreeBSD__ + if (read_mem(&bloom_nbits, pid, (void *)peer_bloom_nbits, sizeof(char)) == 0) { +#else + if (read_mem(&bloom_nbits, fd, (off_t)peer_bloom_nbits, sizeof(char)) == 0) { +#endif + /* scan bloom filter, calculate saturation */ + bloom_bitlen = (1ULL << bloom_nbits); + bloom_len = (bloom_bitlen / 8) + ((bloom_bitlen % 8) ? 1 : 0); + vvv("bloom bitlen is %u, bloom_bytelen is %u\n", (unsigned)bloom_bitlen, (unsigned)bloom_len); + if ( (bloombv = (unsigned char*)malloc(bloom_len)) == NULL) { + fprintf(stderr, "out of memory\n"); + exit(-1); + } + /* read the address of the bitvector in the peer, then read the bv itself */ +#ifdef __FreeBSD__ + if ((read_mem(&peer_bloombv, pid, (void *)peer_bloombv_ptr, sizeof(void*)) == 0) && + (read_mem(bloombv, pid, (void *)peer_bloombv, bloom_len) == 0)) { +#else + if ((read_mem(&peer_bloombv, fd, (off_t)peer_bloombv_ptr, sizeof(void*)) == 0) && + (read_mem(bloombv, fd, (off_t)peer_bloombv, bloom_len) == 0)) { +#endif + /* calculate saturation */ + vvv("read peer bloom bitvector from %p (%u bytes)\n", (void*)peer_bloombv, (unsigned)bloom_len); + for(i=0; i < bloom_bitlen; i++) { + if (HS_BIT_TEST(bloombv,(unsigned)i)) { + /* vvv("bit %u set\n",(unsigned)i); */ + bloom_on_bits++; + } else { + bloom_off_bits++; + } + } + has_bloom_filter_fields = 1; + vvv("there were %u on_bits among %u total bits\n", (unsigned)bloom_on_bits, (unsigned)bloom_bitlen); + } + } + } + + /* choose apparent hash function */ + hash_fcn_winner=0; + for(i=0; i<NUM_HASH_FUNCS; i++) { + if (hash_fcn_hits[i] > hash_fcn_hits[hash_fcn_winner]) { + hash_fcn_winner=i; + } + } + hash_fcn = hash_fcns[hash_fcn_winner]; + + /* + Address ideal items buckets mc fl bloom sat fcn keys saved to + ------------------ ----- -------- -------- -- -- ----- ----- --- ------------- + 0x10aa4090 98% 10000000 32000000 10 ok BER /tmp/9110-0.key + 0x10abcdef 100% 10000000 32000000 9 NX 27 12% BER /tmp/9110-1.key + */ + printf("Address ideal items buckets mc fl bloom sat fcn keys saved to\n"); + printf("------------------ ----- -------- -------- -- -- ----- ----- --- -------------\n"); + if (has_bloom_filter_fields) { + printf("%-18p %4.0f%% %8u %8u %2u %2s %5u %4.0f%c %3s %s\n", + (void*)peer_tbl, + (tbl->num_items - tbl->nonideal_items) * 100.0 / tbl->num_items, + tbl->num_items, + tbl->num_buckets, + max_chain, + tbl->noexpand ? "NX" : "ok", + bloom_nbits, + bloom_on_bits * 100.0 / bloom_bitlen, '%', + hash_fcn, + (getkeys ? keyfile : "")); + } else { + printf("%-18p %4.0f%% %8u %8u %2u %2s %5s %4s%c %3s %s\n", + (void*)peer_tbl, + (tbl->num_items - tbl->nonideal_items) * 100.0 / tbl->num_items, + tbl->num_items, + tbl->num_buckets, + max_chain, + tbl->noexpand ? "NX" : "ok", + "", + "", ' ', + hash_fcn, + (getkeys ? keyfile : "")); + } + +#if 0 + printf("read peer tbl:\n"); + printf("num_buckets: %u\n", tbl->num_buckets); + printf("num_items: %u\n", tbl->num_items); + printf("nonideal_items: %u (%.2f%%)\n", tbl->nonideal_items, + tbl->nonideal_items*100.0/tbl->num_items); + printf("expand: %s\n", tbl->noexpand ? "inhibited": "normal"); + if (getkeys) { + printf("keys written to %s\n", keyfile); + } +#endif + +done: + if (bkts) { + free(bkts); + } + if (tbl) { + free(tbl); + } + if (key) { + free(key); + } + if (keyfd != -1) { + close(keyfd); + } + if (bloombv) { + free(bloombv); + } +} + + +#ifdef __FreeBSD__ +static void sigscan(pid_t pid, void *start, void *end, uint32_t sig) +{ + struct ptrace_io_desc io_desc; + int page_size = getpagesize(); + char *buf; + char *pos; + + /* make sure page_size is a multiple of the signature size, code below assumes this */ + assert(page_size % sizeof(sig) == 0); + + buf = malloc(page_size); + + if (buf == NULL) { + fprintf(stderr, "malloc failed in sigscan()\n"); + return; + } + + io_desc.piod_op = PIOD_READ_D; + io_desc.piod_offs = start; + io_desc.piod_addr = buf; + io_desc.piod_len = page_size; + + /* read in one page after another and search sig */ + while(!ptrace(PT_IO, pid, (void *) &io_desc, 0)) { + if (io_desc.piod_len != page_size) { + fprintf(stderr, "PT_IO returned less than page size in sigscan()\n"); + return; + } + + /* iterate over the the page using the signature size and look for the sig */ + for (pos = buf; pos < (buf + page_size); pos += sizeof(sig)) { + if (*(uint32_t *) pos == sig) { + found(pid, (char *) io_desc.piod_offs + (pos - buf), pid); + } + } + + /* + * 'end' is inclusive (the address of the last valid byte), so if the current offset + * plus a page is beyond 'end', we're already done. since all vm map entries consist + * of entire pages and 'end' is inclusive, current offset plus one page should point + * exactly one byte beyond 'end'. this is assert()ed below to be on the safe side. + */ + if (io_desc.piod_offs + page_size > end) { + assert(io_desc.piod_offs + page_size == (end + 1)); + break; + } + + /* advance to the next page */ + io_desc.piod_offs += page_size; + } +} +#else +static void sigscan(int fd, off_t start, off_t end, uint32_t sig, pid_t pid) +{ + int rlen; + uint32_t u; + off_t at=0; + + if (lseek(fd, start, SEEK_SET) == (off_t)-1) { + fprintf(stderr, "lseek failed: %s\n", strerror(errno)); + return; + } + + while ( (rlen = read(fd,&u,sizeof(u))) == sizeof(u)) { + if (!memcmp(&u,&sig,sizeof(u))) { + found(fd, (char*)(start+at),pid); + } + at += sizeof(u); + if ((off_t)(at + sizeof(u)) > end-start) { + break; + } + } + + if (rlen == -1) { + //fprintf(stderr,"read failed: %s\n", strerror(errno)); + //exit(-1); + } +} +#endif + + +#ifdef __FreeBSD__ +static int scan(pid_t pid) +{ + vma_t *vmas=NULL, vma; + unsigned i, num_vmas = 0; + int ret; + struct ptrace_vm_entry vm_entry; + char path[MAXPATHLEN]; + + vv("attaching to peer\n"); + if (ptrace(PT_ATTACH,pid,NULL,0) == -1) { + fprintf(stderr,"failed to attach to %u: %s\n", (unsigned)pid, strerror(errno)); + exit(EXIT_FAILURE); + } + vv("waiting for peer to suspend temporarily\n"); + if (waitpid(pid,NULL,0) != pid) { + fprintf(stderr,"failed to wait for pid %u: %s\n",(unsigned)pid, strerror(errno)); + goto die; + } + + /* read memory map using ptrace */ + vv("listing peer virtual memory areas\n"); + vm_entry.pve_entry = 0; + vm_entry.pve_path = path; /* not used but required to make vm_entry.pve_pathlen work */ + while(1) { + /* set pve_pathlen every turn, it gets overwritten by ptrace */ + vm_entry.pve_pathlen = MAXPATHLEN; + errno = 0; + + ret = ptrace(PT_VM_ENTRY, pid, (void *) &vm_entry, 0); + + if (ret) { + if (errno == ENOENT) { + /* we've reached the last entry */ + break; + } + fprintf(stderr, "fetching vm map entry failed: %s (%i)\n", strerror(errno), errno); + goto die; + } + + vvv("vmmap entry: start: %p, end: %p", (void *) vm_entry.pve_start, (void *) vm_entry.pve_end); + + /* skip unreadable or vnode-backed entries */ + if (!(vm_entry.pve_prot & VM_PROT_READ) || vm_entry.pve_pathlen > 0) { + vvv(" -> skipped (not readable or vnode-backed)\n"); + vm_entry.pve_path[0] = 0; + continue; + } + + /* useful entry, add to list */ + vvv(" -> will be scanned\n"); + vma.start = (void *)vm_entry.pve_start; + vma.end = (void *)vm_entry.pve_end; + vmas = (vma_t *) realloc(vmas, (num_vmas + 1) * sizeof(vma_t)); + if (vmas == NULL) { + exit(-1); + } + vmas[num_vmas++] = vma; + } + + vv("peer has %u virtual memory areas\n", num_vmas); + + /* look for the hash signature */ + vv("scanning peer memory for hash table signatures\n"); + for(i=0; i<num_vmas; i++) { + vma = vmas[i]; + sigscan(pid, vma.start, vma.end, sig); + } + +die: + vv("detaching and resuming peer\n"); + if (ptrace(PT_DETACH, pid, NULL, 0) == -1) { + fprintf(stderr,"failed to detach from %u: %s\n", (unsigned)pid, strerror(errno)); + } + return 0; +} +# else +static int scan(pid_t pid) +{ + FILE *mapf; + char mapfile[30], memfile[30], line[100]; + vma_t *vmas=NULL, vma; + unsigned i, num_vmas = 0; + int memfd; + void *pstart, *pend, *unused; + + /* attach to the target process and wait for it to suspend */ + vv("attaching to peer\n"); + if (ptrace(PTRACE_ATTACH, pid, NULL, 0) == -1) { + fprintf(stderr,"failed to attach to %u: %s\n", (unsigned)pid, strerror(errno)); + exit(-1); + } + vv("waiting for peer to suspend temporarily\n"); + if (waitpid(pid,NULL,0) != pid) { + fprintf(stderr,"failed to wait for pid %u: %s\n",(unsigned)pid, strerror(errno)); + goto die; + } + + /* get ready to open its memory map. this gives us its valid memory areas */ + snprintf(mapfile,sizeof(mapfile),"/proc/%u/maps",(unsigned)pid); + snprintf(memfile,sizeof(memfile),"/proc/%u/mem", (unsigned)pid); + vv("opening peer memory map [%s]\n", mapfile); + if ( (mapf = fopen(mapfile,"r")) == NULL) { + fprintf(stderr,"failed to open %s: %s\n", mapfile, strerror(errno)); + goto die; + } + vv("listing peer virtual memory areas\n"); + while(fgets(line,sizeof(line),mapf)) { + if (sscanf(line, "%p-%p %4c %p %5c", &pstart, &pend, vma.perms, + &unused, vma.device) == 5) { + vma.start = (off_t)pstart; + vma.end = (off_t)pend; + if (vma.perms[0] != 'r') { + continue; /* only readable vma's */ + } + if (memcmp(vma.device,"fd",2)==0) { + continue; /* skip mapped files */ + } + vmas = (vma_t*)realloc(vmas, (num_vmas+1) * sizeof(vma_t)); + if (vmas == NULL) { + exit(-1); + } + vmas[num_vmas++] = vma; + } + } + vv("peer has %u virtual memory areas\n",num_vmas); + fclose(mapf); + + /* ok, open up its memory and start looking around in there */ + vv("opening peer memory\n"); + if ( (memfd=open(memfile,O_RDONLY)) == -1) { + fprintf(stderr,"failed to open %s: %s\n", memfile, strerror(errno)); + goto die; + } + /* look for the hash signature */ + vv("scanning peer memory for hash table signatures\n"); + for(i=0; i<num_vmas; i++) { + vma = vmas[i]; + pstart = (void*)vma.start; + pend = (void*)vma.end; + /*fprintf(stderr,"scanning %p-%p %.4s %.5s\n", pstart, pend, + vma.perms, vma.device);*/ + sigscan(memfd, vma.start, vma.end, sig, pid); + } + + /* done. close memory and detach. this resumes the target process */ + close(memfd); + +die: + vv("detaching and resuming peer\n"); + if (ptrace(PTRACE_DETACH, pid, NULL, 0) == -1) { + fprintf(stderr,"failed to detach from %u: %s\n", (unsigned)pid, strerror(errno)); + } + return 0; +} +#endif + + +static int usage(const char *prog) +{ + fprintf(stderr,"usage: %s [-v] [-k] <pid>\n", prog); + return -1; +} + +int main(int argc, char *argv[]) +{ + int opt; + + while ( (opt = getopt(argc, argv, "kv")) != -1) { + switch (opt) { + case 'v': + verbose++; + break; + case 'k': + getkeys++; + break; + default: + return usage(argv[0]); + } + } + + if (optind < argc) { + pid_t pid = atoi(argv[optind++]); + return scan(pid); + } else { + return usage(argv[0]); + } +} diff --git a/tests/keystat.c b/tests/keystat.c new file mode 100644 index 000000000..cb64ca66f --- /dev/null +++ b/tests/keystat.c @@ -0,0 +1,255 @@ +#include <sys/types.h> /* for 'open' */ +#include <sys/stat.h> /* for 'open' */ +#include <fcntl.h> /* for 'open' */ +#include <stdlib.h> /* for 'malloc' */ +#include <stdio.h> /* for 'printf' */ +#include <unistd.h> /* for 'read' */ +#include <errno.h> /* for 'sterror' */ +#include <sys/time.h> /* for 'gettimeofday' */ +#include "uthash.h" + +#undef uthash_noexpand_fyi +#define uthash_noexpand_fyi(t) die() +#define UNALIGNED_KEYS 0 + +static void die() +{ + fprintf(stderr,"expansion inhibited\n"); + exit(-1); +} + +/* Windows doesn't have gettimeofday. While Cygwin and some + * versions of MinGW supply one, it is very coarse. This substitute + * gives much more accurate elapsed times under Windows. */ +#if (( defined __CYGWIN__ ) || ( defined __MINGW32__ )) +#include <windows.h> +static void win_gettimeofday(struct timeval* p, void* tz /* IGNORED */) +{ + LARGE_INTEGER q; + static long long freq; + static long long cyg_timer; + QueryPerformanceFrequency(&q); + freq = q.QuadPart; + QueryPerformanceCounter(&q); + cyg_timer = q.QuadPart; + p->tv_sec = (long)(cyg_timer / freq); + p->tv_usec = (long)(((cyg_timer % freq) * 1000000) / freq); +} +#define gettimeofday win_gettimeofday +#define MODE (O_RDONLY|O_BINARY) +#else +#define MODE (O_RDONLY) +#endif + +#ifndef timersub +#define timersub(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ + if ((result)->tv_usec < 0) { \ + --(result)->tv_sec; \ + (result)->tv_usec += 1000000; \ + } \ + } while (0) +#endif + +typedef struct stat_key { + char *key; + unsigned len; + UT_hash_handle hh, hh2; +} stat_key; + +#define CHAIN_0 0 +#define CHAIN_5 1 +#define CHAIN_10 2 +#define CHAIN_20 3 +#define CHAIN_100 4 +#define CHAIN_MAX 5 +static void hash_chain_len_histogram(const UT_hash_table *tbl) +{ + unsigned i, bkt_hist[CHAIN_MAX+1]; + double pct = 100.0/(double)tbl->num_buckets; + memset(bkt_hist,0,sizeof(bkt_hist)); + for(i=0; i < tbl->num_buckets; i++) { + unsigned count = tbl->buckets[i].count; + if (count == 0U) { + bkt_hist[CHAIN_0]++; + } else if (count < 5U) { + bkt_hist[CHAIN_5]++; + } else if (count < 10U) { + bkt_hist[CHAIN_10]++; + } else if (count < 20U) { + bkt_hist[CHAIN_20]++; + } else if (count < 100U) { + bkt_hist[CHAIN_100]++; + } else { + bkt_hist[CHAIN_MAX]++; + } + } + fprintf(stderr, "Buckets with 0 items: %.1f%%\n", (double)bkt_hist[CHAIN_0 ]*pct); + fprintf(stderr, "Buckets with < 5 items: %.1f%%\n", (double)bkt_hist[CHAIN_5 ]*pct); + fprintf(stderr, "Buckets with < 10 items: %.1f%%\n", (double)bkt_hist[CHAIN_10]*pct); + fprintf(stderr, "Buckets with < 20 items: %.1f%%\n", (double)bkt_hist[CHAIN_20]*pct); + fprintf(stderr, "Buckets with < 100 items: %.1f%%\n", (double)bkt_hist[CHAIN_100]*pct); + fprintf(stderr, "Buckets with > 100 items: %.1f%%\n", (double)bkt_hist[CHAIN_MAX]*pct); +} + +int main(int argc, char *argv[]) +{ + int dups=0, rc, fd, done=0, err=0, want, i, padding=0, v=1, percent=100; + unsigned keylen, max_keylen=0, verbose=0; + const char *filename = "/dev/stdin"; + char *dst; + stat_key *keyt, *keytmp, *keys=NULL, *keys2=NULL; + struct timeval start_tm, end_tm, elapsed_tm, elapsed_tm2, elapsed_tm3; + + if ((argc >= 3) && (strcmp(argv[1],"-p") == 0)) { + percent = atoi(argv[2]); + v = 3; + } + if ((v < argc) && (strcmp(argv[v],"-v") == 0)) { + verbose=1; + v++; + } + if (v < argc) { + filename=argv[v]; + } + fd=open(filename,MODE); + + if ( fd == -1 ) { + fprintf(stderr,"open failed %s: %s\n", filename, strerror(errno)); + return -1; + } + + for(i=0; done==0; i++) { + + want = sizeof(int); + dst = (char*)&keylen; +readmore1: + rc = read(fd,dst,want); + if (rc != want) { + if (rc == 0) { + done=1; + } else if (rc == -1) { + fprintf(stderr,"read failed: %s\n", strerror(errno)); + err=1; + } else if (rc > 0) { + want -= rc; + dst += rc; + goto readmore1; + } + } + + if (done || err) { + break; + } + if (keylen > max_keylen) { + max_keylen=keylen; + } + + keyt = (stat_key*)malloc(sizeof(stat_key)); + if (keyt == NULL) { + fprintf(stderr,"out of memory\n"); + exit(-1); + } + + /* read key */ +#ifdef UNALIGNED_KEYS + padding = i%8; +#endif + keyt->key = (char*)malloc(padding+keylen); + if (keyt->key == NULL) { + fprintf(stderr,"out of memory\n"); + exit(-1); + } + keyt->key += padding; /* forcibly alter the alignment of key */ + keyt->len = keylen; + + want = keylen; + dst = keyt->key; +readmore2: + rc = read(fd,dst,want); + if (rc != want) { + if (rc == -1) { + fprintf(stderr,"read failed: %s\n", strerror(errno)); + err=1; + } else if (rc == 0) { + fprintf(stderr,"incomplete file\n"); + err=1; + } else if (rc >= 0) { + want -= rc; + dst += rc; + goto readmore2; + } + } + if (err != 0) { + break; + } + /* if percent was set to something less than 100%, skip some keys*/ + if (((rand()*1.0) / RAND_MAX) > ((percent*1.0)/100)) { + free(keyt->key-padding); + free(keyt); + continue; + } + + /* eliminate dups */ + HASH_FIND(hh,keys,keyt->key,keylen,keytmp); + if (keytmp != NULL) { + dups++; + free(keyt->key - padding); + free(keyt); + } else { + HASH_ADD_KEYPTR(hh,keys,keyt->key,keylen,keyt); + } + } + + if (verbose != 0) { + unsigned key_count = HASH_COUNT(keys); + fprintf(stderr,"max key length: %u\n", max_keylen); + fprintf(stderr,"number unique keys: %u\n", key_count); + fprintf(stderr,"keystats memory: %u\n", + (unsigned)((sizeof(stat_key)+max_keylen)*key_count)); + hash_chain_len_histogram(keys->hh.tbl); + } + + /* add all keys to a new hash, so we can measure add time w/o malloc */ + gettimeofday(&start_tm,NULL); + for(keyt = keys; keyt != NULL; keyt=(stat_key*)keyt->hh.next) { + HASH_ADD_KEYPTR(hh2,keys2,keyt->key,keyt->len,keyt); + } + gettimeofday(&end_tm,NULL); + timersub(&end_tm, &start_tm, &elapsed_tm); + + /* now look up all keys in the new hash, again measuring elapsed time */ + gettimeofday(&start_tm,NULL); + for(keyt = keys; keyt != NULL; keyt=(stat_key*)keyt->hh.next) { + HASH_FIND(hh2,keys2,keyt->key,keyt->len,keytmp); + if (keytmp == NULL) { + fprintf(stderr,"internal error, key not found\n"); + } + } + gettimeofday(&end_tm,NULL); + timersub(&end_tm, &start_tm, &elapsed_tm2); + + /* now delete all items in the new hash, measuring elapsed time */ + gettimeofday(&start_tm,NULL); + while (keys2 != NULL) { + keytmp = keys2; + HASH_DELETE(hh2,keys2,keytmp); + } + gettimeofday(&end_tm,NULL); + timersub(&end_tm, &start_tm, &elapsed_tm3); + + if (err == 0) { + printf("%.3f,%u,%u,%d,%s,%ld,%ld,%ld\n", + 1-(1.0*keys->hh.tbl->nonideal_items/keys->hh.tbl->num_items), + keys->hh.tbl->num_items, + keys->hh.tbl->num_buckets, + dups, + (keys->hh.tbl->noexpand != 0U) ? "nx" : "ok", + (elapsed_tm.tv_sec * 1000000) + elapsed_tm.tv_usec, + (elapsed_tm2.tv_sec * 1000000) + elapsed_tm2.tv_usec, + (elapsed_tm3.tv_sec * 1000000) + elapsed_tm3.tv_usec ); + } + return 0; +} diff --git a/tests/keystats b/tests/keystats new file mode 100755 index 000000000..9d4076278 --- /dev/null +++ b/tests/keystats @@ -0,0 +1,40 @@ +#!/usr/bin/perl + +use strict; + +use FindBin; + +sub usage { + print "usage: keystats [-v] keyfile\n"; + print "usage: keystats [-p <pct> [-v]] keyfile\n"; + exit -1; +} + +usage if ((@ARGV == 0) or ($ARGV[0] eq '-h')); + +my @exes = glob "$FindBin::Bin/keystat.???"; +my %stats; +for my $exe (@exes) { + $stats{$exe} = `$exe @ARGV`; + delete $stats{$exe} if ($? != 0); # omit hash functions that fail to produce stats (nx) +} + +print( "fcn ideal% #items #buckets dup% fl add_usec find_usec del-all usec\n"); +printf("--- ------ ---------- ---------- ----- -- ---------- ---------- ------------\n"); +for my $exe (sort statsort keys %stats) { + my ($ideal,$items,$bkts,$dups,$ok,$add,$find,$del) = split /,/, $stats{$exe}; + + # convert 0-1 values to percentages + $dups = $items ? (100.0 * $dups / $items) : 0.0; + $ideal = 100.0 * $ideal; + + printf("%3s %5.1f%% %10d %10d %4.0f%% %2s %10d %10d %12d\n", substr($exe,-3,3), + $ideal,$items,$bkts,$dups,$ok,$add,$find,$del); +} + +# sort on hash_q (desc) then by find_usec (asc) +sub statsort { + my @a_stats = split /,/, $stats{$a}; + my @b_stats = split /,/, $stats{$b}; + return ($b_stats[0] <=> $a_stats[0]) || ($a_stats[-1] <=> $b_stats[-1]); +} diff --git a/tests/lru_cache/Makefile b/tests/lru_cache/Makefile new file mode 100644 index 000000000..aa3a2cb89 --- /dev/null +++ b/tests/lru_cache/Makefile @@ -0,0 +1,21 @@ +CC=gcc + +CFLAGS+=-W -Werror -Wall -Wextra -std=c99 \ + -D_FORTIFY_SOURCE=2 -fstack-protector -g \ + -Wformat=2 -pedantic -pedantic-errors \ + -D_GNU_SOURCE=1 -D_BSD_SOURCE=1 \ + -I../../src + +LDFLAGS+=-pthread + +cache: main.o cache.o + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) main.o cache.o -o cache + +main.o: main.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c main.c -o main.o + +cache.o: cache.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c cache.c -o cache.o + +clean: + rm -f cache *.o diff --git a/tests/lru_cache/cache.c b/tests/lru_cache/cache.c new file mode 100644 index 000000000..632c55862 --- /dev/null +++ b/tests/lru_cache/cache.c @@ -0,0 +1,221 @@ +/* + * ===================================================================================== + * + * Filename: cache.c + * + * Description: A simple cache + * + * Version: 1.0 + * Created: 04/11/2013 02:31:02 PM + * Revision: none + * Compiler: gcc + * + * Author: Oliver Lorenz (ol), olli@olorenz.org + * Company: https://olorenz.org + * License: This is licensed under the same terms as uthash itself + * + * ===================================================================================== + */ + +#include <errno.h> +#include <pthread.h> +#include <stdlib.h> +#include "cache.h" +#include "uthash.h" + +/** + * A cache entry + */ +struct foo_cache_entry { + char *key; /**<The key */ + void *data; /**<Payload */ + UT_hash_handle hh; /**<Hash Handle for uthash */ +}; +#define KEY_MAX_LENGTH 32 + +/** + * A cache object + */ +struct foo_cache { + size_t max_entries; /**<Amount of entries this cache object can hold */ + pthread_rwlock_t cache_lock; /**<A lock for concurrent access */ + struct foo_cache_entry *entries; /**<Head pointer for uthash */ + void (*free_cb) (void *element);/**<Callback function to free cache entries */ +}; + +/** Creates a new cache object + + @param dst + Where the newly allocated cache object will be stored in + + @param capacity + The maximum number of elements this cache object can hold + + @return EINVAL if dst is NULL, ENOMEM if malloc fails, 0 otherwise +*/ +int foo_cache_create(struct foo_cache **dst, const size_t capacity, + void (*free_cb) (void *element)) +{ + struct foo_cache *new = NULL; + int rv; + + if (!dst) + return EINVAL; + + if ((new = malloc(sizeof(*new))) == NULL) + return ENOMEM; + + if ((rv = pthread_rwlock_init(&(new->cache_lock), NULL)) != 0) + goto err_out; + + new->max_entries = capacity; + new->entries = NULL; + new->free_cb = free_cb; + *dst = new; + return 0; + +err_out: + if (new) + free(new); + return rv; +} + +/** Frees an allocated cache object + + @param cache + The cache object to free + + @param keep_data + Whether to free contained data or just delete references to it + + @return EINVAL if cache is NULL, 0 otherwise +*/ +int foo_cache_delete(struct foo_cache *cache, int keep_data) +{ + struct foo_cache_entry *entry, *tmp; + int rv; + + if (!cache) + return EINVAL; + + rv = pthread_rwlock_wrlock(&(cache->cache_lock)); + if (rv) + return rv; + + if (keep_data) { + HASH_CLEAR(hh, cache->entries); + } else { + HASH_ITER(hh, cache->entries, entry, tmp) { + HASH_DEL(cache->entries, entry); + if (cache->free_cb) + cache->free_cb(entry->data); + free(entry); + } + } + (void)pthread_rwlock_unlock(&(cache->cache_lock)); + (void)pthread_rwlock_destroy(&(cache->cache_lock)); + free(cache); + cache = NULL; + return 0; +} + +/** Checks if a given key is in the cache + + @param cache + The cache object + + @param key + The key to look-up + + @param result + Where to store the result if key is found. + + A warning: Even though result is just a pointer, + you have to call this function with a **ptr, + otherwise this will blow up in your face. + + @return EINVAL if cache is NULL, 0 otherwise +*/ +int foo_cache_lookup(struct foo_cache *cache, char *key, void *result) +{ + int rv; + struct foo_cache_entry *tmp = NULL; + char **dirty_hack = result; + + if (!cache || !key || !result) + return EINVAL; + + rv = pthread_rwlock_wrlock(&(cache->cache_lock)); + if (rv) + return rv; + + HASH_FIND_STR(cache->entries, key, tmp); + if (tmp) { + size_t key_len = strnlen(tmp->key, KEY_MAX_LENGTH); + HASH_DELETE(hh, cache->entries, tmp); + HASH_ADD_KEYPTR(hh, cache->entries, tmp->key, key_len, tmp); + *dirty_hack = tmp->data; + } else { + *dirty_hack = result = NULL; + } + rv = pthread_rwlock_unlock(&(cache->cache_lock)); + return rv; +} + +/** Inserts a given <key, value> pair into the cache + + @param cache + The cache object + + @param key + The key that identifies <value> + + @param data + Data associated with <key> + + @return EINVAL if cache is NULL, ENOMEM if malloc fails, 0 otherwise +*/ +int foo_cache_insert(struct foo_cache *cache, char *key, void *data) +{ + struct foo_cache_entry *entry = NULL; + struct foo_cache_entry *tmp_entry = NULL; + size_t key_len = 0; + int rv; + + if (!cache || !data) + return EINVAL; + + if ((entry = malloc(sizeof(*entry))) == NULL) + return ENOMEM; + + if ((rv = pthread_rwlock_wrlock(&(cache->cache_lock))) != 0) + goto err_out; + + entry->key = key; + entry->data = data; + key_len = strnlen(entry->key, KEY_MAX_LENGTH); + HASH_ADD_KEYPTR(hh, cache->entries, entry->key, key_len, entry); + + if (HASH_COUNT(cache->entries) >= cache->max_entries) { + HASH_ITER(hh, cache->entries, entry, tmp_entry) { + HASH_DELETE(hh, cache->entries, entry); + if (cache->free_cb) + cache->free_cb(entry->data); + else + free(entry->data); + /* free(key->key) if data has been copied */ + free(entry); + break; + } + } + + rv = pthread_rwlock_unlock(&(cache->cache_lock)); + return rv; + +err_out: + if (entry) + free(entry); + (void)pthread_rwlock_unlock(&(cache->cache_lock)); + return rv; + +} diff --git a/tests/lru_cache/cache.h b/tests/lru_cache/cache.h new file mode 100644 index 000000000..350576d4f --- /dev/null +++ b/tests/lru_cache/cache.h @@ -0,0 +1,31 @@ +/* + * ===================================================================================== + * + * Filename: cache.h + * + * Description: A simple cache + * + * Version: 1.0 + * Created: 04/11/2013 02:30:46 PM + * Revision: none + * Compiler: gcc + * + * Author: Oliver Lorenz (ol), olli@olorenz.org + * Company: https://olorenz.org + * License: This is licensed under the same terms as uthash itself + * + * ===================================================================================== + */ + +#ifndef _CACHE_ +#define _CACHE_ + +struct foo_cache; + +extern int foo_cache_create(struct foo_cache **dst, const size_t capacity, + void (*free_cb) (void *element)); +extern int foo_cache_delete(struct foo_cache *cache, int keep_data); +extern int foo_cache_lookup(struct foo_cache *cache, char *key, void *result); +extern int foo_cache_insert(struct foo_cache *cache, char *key, void *data); + +#endif diff --git a/tests/lru_cache/main.c b/tests/lru_cache/main.c new file mode 100644 index 000000000..7f0eae2f2 --- /dev/null +++ b/tests/lru_cache/main.c @@ -0,0 +1,191 @@ +#include <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "cache.h" + +#define MAX_RANDOM_ENTRIES 32 + +struct key_record { + char *key; + char *value; +}; + +int generate_random_entry(struct key_record **entry); +int generate_random_string(char **dst, const size_t len); +void free_random_entry(void *entry); + +void *producer(void *arg) +{ + struct foo_cache *cache = arg; + int i; + + for (i = 0; i < MAX_RANDOM_ENTRIES; i++) { + struct key_record *entry = NULL; + if (generate_random_entry(&entry)) { + fprintf(stderr, "generate_random_entry() failed\n"); + continue; + } +#if defined(DEBUG) + printf("Random Entry:\n"); + printf(" key: %s\n", entry->key); + printf(" Key: %s\n", entry->value); +#else + printf("inserted %s (%d)\n", entry->key, + (int)strlen(entry->key)); +#endif + if (foo_cache_insert(cache, entry->key, entry)) { + fprintf(stderr, "foo_cache_insert() failed\n"); + continue; + } + } + + pthread_exit(NULL); +} + +void *consumer(void *arg) +{ + struct foo_cache *cache = arg; + struct key_record *result = NULL; + char *buffer = malloc(64); + char key[33]; + int stop = 0; + + if (!buffer) + goto out; + + /* give producer time to populate the cache */ + sleep(2); + printf("\n\n"); + + do { + memset(key, 0, 64); + result = NULL; + + printf("Enter key for lookup: "); + fgets(buffer, sizeof(key), stdin); + sscanf(buffer, "%s\n", key); + /* read '\n' from stdin */ + getchar(); + + if (strncmp(key, "exit", 4) == 0) { + stop = 1; + continue; + } + + printf("Got key %s (%d)\n", key, (int)strlen(key)); + + if (foo_cache_lookup(cache, key, &result)) { + fprintf(stderr, "Could not retrieve key %s\n", key); + continue; + } + + if (!result) { + printf("MISS\n"); + continue; + } + + printf("HIT\n"); + printf("key: %s\n", result->key); + printf("key : %s\n", result->value); + } while (!stop); + +out: + if (buffer) + free(buffer); + pthread_exit(NULL); +} + +int main() +{ + int rv; + struct foo_cache *cache = NULL; + pthread_t workers[2]; + + rv = foo_cache_create(&cache, MAX_RANDOM_ENTRIES / 2, + free_random_entry); + if (rv) { + fprintf(stderr, "Could not create cache\n"); + exit(1); + } + + (void)pthread_create(&workers[0], NULL, producer, (void *)cache); + (void)pthread_create(&workers[1], NULL, consumer, (void *)cache); + + pthread_join(workers[0], NULL); + pthread_join(workers[1], NULL); + + (void)foo_cache_delete(cache, 0); + return 0; +} + +int generate_random_entry(struct key_record **entry) +{ + struct key_record *new = NULL; + char *key = NULL; + char *value = NULL; + int rv; + + if (!entry) + return EINVAL; + + rv = generate_random_string(&key, 33); + if (rv) + return rv; + + rv = generate_random_string(&value, 129); + if (rv) + return rv; + + if ((new = malloc(sizeof(*new))) == NULL) { + free(key); + free(value); + return ENOMEM; + } + + new->key = key; + new->value = value; + + *entry = new; + return 0; +} + +int generate_random_string(char **dst, const size_t len) +{ + static const char alphanum[] = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + size_t i; + char *s; + + if (!dst || len == 0) + return EINVAL; + + if ((s = malloc(len)) == NULL) + return ENOMEM; + + for (i = 0; i < len - 1; i++) { + s[i] = alphanum[rand() % (sizeof(alphanum) - 1)]; + } + + s[len - 1] = '\0'; + *dst = s; + return 0; +} + +void free_random_entry(void *entry) +{ +#if defined(DEBUG) + fprintf(stderr, "In %s: entry @ %p\n", __func__, entry); +#endif + struct key_record *record = entry; + if (!record) + return; + if (record->key) + free(record->key); + if (record->value) + free(record->value); + free(record); + record = NULL; +} diff --git a/tests/simkeys.pl b/tests/simkeys.pl new file mode 100755 index 000000000..acc5583b7 --- /dev/null +++ b/tests/simkeys.pl @@ -0,0 +1,28 @@ +#!/usr/bin/perl + +# This program generates a simkey10.dat (100, 1000, etc) each +# containing 100 random keys of length 10 (100, 1000, etc). +# These files can then be fed into keystats to observe that +# the time to add or find the keys is directly proportional to +# keylength n [in other words, O(n)]. +# +# The conclusion is that really long keys (e.g. 100k) are not +# efficient. TDH 23Jan07 + +use strict; +use warnings; + + +#for my $len (10,100,1000,10000,100000,1000000) { +for my $len (100) { + open OUTFILE, ">simkeys$len.dat" or die "can't open: $!\n"; + # we'll do 100 keys of $len + print "keylen $len\n"; + for my $i (0..99) { + my $key = pack "I", $len; + $key .= pack "C", (int(rand(256))) for (1..$len); + print OUTFILE $key; + } + close OUTFILE; +} + diff --git a/tests/sleep_test.c b/tests/sleep_test.c new file mode 100644 index 000000000..60e60d1b6 --- /dev/null +++ b/tests/sleep_test.c @@ -0,0 +1,32 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ +#include <unistd.h> /* getpid */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +int main() +{ + int i; + example_user_t *user, *users=NULL; + + /* create elements */ + for(i=0; i<10000; i++) { + if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + + printf("pid: %u\n", (unsigned)getpid()); + /* printf("sig: %p\n", &users->hh.tbl->signature); */ + /* printf("bbv: %p\n", &users->hh.tbl->bloom_bv); */ + sleep(60*10); + return 0; +} diff --git a/tests/tdiff.cpp b/tests/tdiff.cpp new file mode 100644 index 000000000..4be14fed6 --- /dev/null +++ b/tests/tdiff.cpp @@ -0,0 +1,34 @@ +// Windows does not have unix diff so this is a simple replacement +#include <iostream> +#include <fstream> +using namespace std; +int main(int argc, char *argv[] ) { + int rc=-1; + if (argc != 3) { + cout << "usage: " << argv[0] << " file1 file2\n"; + return -1; + } + char *file1 = argv[1]; + char *file2 = argv[2]; + ifstream is1(file1, ios::in); + ifstream is2(file2, ios::in); + if (is1.fail()) {cerr << "failed to open " << file1 << "\n"; goto done;} + if (is2.fail()) {cerr << "failed to open " << file2 << "\n"; goto done;} + char d1[256], d2[256]; + do { + is1.read(d1,sizeof(d1)); + is2.read(d2,sizeof(d2)); + if ((is1.gcount() != is2.gcount()) || memcmp(d1,d2,is1.gcount())) { + cout << file1 << " and " << file2 << " differ\n"; + goto done; + } + } while (!is1.eof() && !is2.eof()); + + rc=0; + + done: + is1.close(); + is2.close(); + return rc; +} + diff --git a/tests/test1.ans b/tests/test1.ans new file mode 100644 index 000000000..0b08c48c3 --- /dev/null +++ b/tests/test1.ans @@ -0,0 +1,10 @@ +user 0, cookie 0 +user 1, cookie 1 +user 2, cookie 4 +user 3, cookie 9 +user 4, cookie 16 +user 5, cookie 25 +user 6, cookie 36 +user 7, cookie 49 +user 8, cookie 64 +user 9, cookie 81 diff --git a/tests/test1.c b/tests/test1.c new file mode 100644 index 000000000..5e457ab3b --- /dev/null +++ b/tests/test1.c @@ -0,0 +1,31 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +int main() +{ + int i; + example_user_t *user, *users=NULL; + + /* create elements */ + for(i=0; i<10; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + + for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { + printf("user %d, cookie %d\n", user->id, user->cookie); + } + return 0; +} diff --git a/tests/test10.ans b/tests/test10.ans new file mode 100644 index 000000000..b1a27a844 --- /dev/null +++ b/tests/test10.ans @@ -0,0 +1,4 @@ +9 found in hh +9 found in alth +10 not found in hh +10 found in alth diff --git a/tests/test10.c b/tests/test10.c new file mode 100644 index 000000000..64f8035e2 --- /dev/null +++ b/tests/test10.c @@ -0,0 +1,51 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; + UT_hash_handle alth; +} example_user_t; + +int main() +{ + int i; + example_user_t *user, *tmp, *users=NULL, *altusers=NULL; + + /* create elements */ + for(i=0; i<1000; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + if (i<10) { + HASH_ADD_INT(users,id,user); + } + HASH_ADD(alth,altusers,id,sizeof(int),user); + } + + /* + printf("hh items: %d, alth items: %d\n", + users->hh.tbl->num_items, users->alth.tbl->num_items); + printf("hh buckets: %d, alth buckets: %d\n", + users->hh.tbl->num_buckets, users->alth.tbl->num_buckets); + */ + + i=9; + HASH_FIND_INT(users,&i,tmp); + printf("%d %s in hh\n", i, (tmp != NULL) ? "found" : "not found"); + HASH_FIND(alth,altusers,&i,sizeof(int),tmp); + printf("%d %s in alth\n", i, (tmp != NULL) ? "found" : "not found"); + + i=10; + HASH_FIND_INT(users,&i,tmp); + printf("%d %s in hh\n", i, (tmp != NULL) ? "found" : "not found"); + HASH_FIND(alth,altusers,&i,sizeof(int),tmp); + printf("%d %s in alth\n", i, (tmp != NULL) ? "found" : "not found"); + + return 0; +} diff --git a/tests/test11.ans b/tests/test11.ans new file mode 100644 index 000000000..2b72e985a --- /dev/null +++ b/tests/test11.ans @@ -0,0 +1,51 @@ +ADRIAN +ARNOLDO +CARROLL +CARY +CHONG +CLIFTON +CODY +COLTON +CORNELL +DAMON +DANNIE +DARIO +DONN +DOUG +DOUGLAS +FREDERICK +FRITZ +GERALD +GUS +HARVEY +IRVING +ISAIAH +JARVIS +JOHN +KENTON +LAURENCE +LESTER +LINCOLN +LOWELL +NELSON +NEVILLE +NIGEL +NORMAND +ODIS +OMAR +ORLANDO +RAYMUNDO +REX +ROLANDO +RON +SHANE +TONEY +TRINIDAD +WALTER +WARNER +WARREN +WES +WILLARD +WILLIAM +WINFRED +XAVIER diff --git a/tests/test11.c b/tests/test11.c new file mode 100644 index 000000000..1460141f7 --- /dev/null +++ b/tests/test11.c @@ -0,0 +1,57 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <errno.h> /* perror */ +#include <stdio.h> /* printf */ + +#define BUFLEN 20 + +#if 0 +/* Print a message if the hash's no-expand flag is set. */ +#undef uthash_noexpand_fyi +#undef uthash_expand_fyi +#define uthash_noexpand_fyi(tbl) printf("noexpand set\n"); +#define uthash_expand_fyi(tbl) printf("hash expanded\n"); +#endif + +typedef struct name_rec { + char boy_name[BUFLEN]; + UT_hash_handle hh; +} name_rec; + +static int namecmp(void *_a, void *_b) +{ + name_rec *a = (name_rec*)_a; + name_rec *b = (name_rec*)_b; + return strcmp(a->boy_name,b->boy_name); +} + +int main() +{ + name_rec *name, *names=NULL; + char linebuf[BUFLEN]; + FILE *file; + + file = fopen( "test11.dat", "r" ); + if (file == NULL) { + perror("can't open: "); + exit(-1); + } + + while (fgets(linebuf,BUFLEN,file) != NULL) { + name = (name_rec*)malloc(sizeof(name_rec)); + if (name == NULL) { + exit(-1); + } + strcpy(name->boy_name, linebuf); + HASH_ADD_STR(names,boy_name,name); + } + + fclose(file); + HASH_SORT(names,namecmp); + for(name=names; name!=NULL; name=(name_rec*)(name->hh.next)) { + printf("%s",name->boy_name); + } + + return 0; +} + diff --git a/tests/test11.dat b/tests/test11.dat new file mode 100644 index 000000000..bb6051b75 --- /dev/null +++ b/tests/test11.dat @@ -0,0 +1,51 @@ +JOHN +WILLIAM +WALTER +DOUGLAS +GERALD +FREDERICK +WARREN +SHANE +LESTER +RON +HARVEY +ADRIAN +CODY +NELSON +CLIFTON +WILLARD +DOUG +ORLANDO +REX +OMAR +DAMON +LOWELL +IRVING +CARROLL +LAURENCE +ROLANDO +CARY +XAVIER +ISAIAH +GUS +JARVIS +WINFRED +RAYMUNDO +LINCOLN +CORNELL +NIGEL +NORMAND +FRITZ +DONN +TRINIDAD +ODIS +DANNIE +DARIO +KENTON +CHONG +NEVILLE +TONEY +WARNER +WES +COLTON +ARNOLDO diff --git a/tests/test12.ans b/tests/test12.ans new file mode 100644 index 000000000..727f397eb --- /dev/null +++ b/tests/test12.ans @@ -0,0 +1,20 @@ +added bob (id 0) +added jack (id 1) +added gary (id 2) +added ty (id 3) +added bo (id 4) +added phil (id 5) +added art (id 6) +added gil (id 7) +added buck (id 8) +added ted (id 9) +found bob (id 0) +found jack (id 1) +found gary (id 2) +found ty (id 3) +found bo (id 4) +found phil (id 5) +found art (id 6) +found gil (id 7) +found buck (id 8) +found ted (id 9) diff --git a/tests/test12.c b/tests/test12.c new file mode 100644 index 000000000..1ed0d3b34 --- /dev/null +++ b/tests/test12.c @@ -0,0 +1,40 @@ +#include "uthash.h" +#include <stdio.h> +#include <stdlib.h> /* malloc */ + +typedef struct person_t { + char first_name[10]; + int id; + UT_hash_handle hh; +} person_t; + +int main() +{ + person_t *people=NULL, *person; + const char **name; + const char * names[] = { "bob", "jack", "gary", "ty", "bo", "phil", "art", + "gil", "buck", "ted", NULL + }; + int id=0; + + for(name=names; *name != NULL; name++) { + person = (person_t*)malloc(sizeof(person_t)); + if (person == NULL) { + exit(-1); + } + strcpy(person->first_name, *name); + person->id = id++; + HASH_ADD_STR(people,first_name,person); + printf("added %s (id %d)\n", person->first_name, person->id); + } + + for(name=names; *name != NULL; name++) { + HASH_FIND_STR(people,*name,person); + if (person != NULL) { + printf("found %s (id %d)\n", person->first_name, person->id); + } else { + printf("failed to find %s\n", *name); + } + } + return 0; +} diff --git a/tests/test13.ans b/tests/test13.ans new file mode 100644 index 000000000..baf3ff215 --- /dev/null +++ b/tests/test13.ans @@ -0,0 +1,5 @@ +id 9, following prev... +id 7, following prev... +id 5, following prev... +id 3, following prev... +id 1, following prev... diff --git a/tests/test13.c b/tests/test13.c new file mode 100644 index 000000000..eef7d029b --- /dev/null +++ b/tests/test13.c @@ -0,0 +1,50 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +int main() +{ + int i; + example_user_t *user, *tmp, *users=NULL; + + /* create elements */ + for(i=0; i<10; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + + /* delete each even ID */ + for(i=0; i<10; i+=2) { + HASH_FIND_INT(users,&i,tmp); + if (tmp != NULL) { + HASH_DEL(users,tmp); + free(tmp); + } else { + printf("user id %d not found\n", i); + } + } + + i=9; + HASH_FIND_INT(users,&i,tmp); + if (tmp != NULL) { + while (tmp != NULL) { + printf("id %d, following prev...\n", tmp->id); + tmp = (example_user_t*)tmp->hh.prev; + } + } else { + printf("user id %d not found\n", i); + } + + return 0; +} diff --git a/tests/test14.ans b/tests/test14.ans new file mode 100644 index 000000000..77aeaebd0 --- /dev/null +++ b/tests/test14.ans @@ -0,0 +1 @@ +lookup on 1219 of 1219 names succeeded diff --git a/tests/test14.c b/tests/test14.c new file mode 100644 index 000000000..cb2606716 --- /dev/null +++ b/tests/test14.c @@ -0,0 +1,54 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <errno.h> /* perror */ +#include <stdio.h> /* printf */ + +#define BUFLEN 20 +#if 0 +#undef uthash_expand_fyi +#define uthash_expand_fyi(tbl) printf("expanding to %d buckets\n", tbl->num_buckets) +#endif + +typedef struct name_rec { + char boy_name[BUFLEN]; + UT_hash_handle hh; +} name_rec; + +int main() +{ + name_rec *name, *names=NULL; + char linebuf[BUFLEN]; + FILE *file; + int i=0,j=0; + + file = fopen( "test14.dat", "r" ); + if (file == NULL ) { + perror("can't open: "); + exit(-1); + } + + while (fgets(linebuf,BUFLEN,file) != NULL) { + i++; + name = (name_rec*)malloc(sizeof(name_rec)); + if (name == NULL) { + exit(-1); + } + strcpy(name->boy_name, linebuf); + HASH_ADD_STR(names,boy_name,name); + } + + fseek(file,0L,SEEK_SET); + + while (fgets(linebuf,BUFLEN,file) != NULL) { + HASH_FIND_STR(names,linebuf,name); + if (!name) { + printf("failed to find: %s", linebuf); + } else { + j++; + } + } + fclose(file); + printf("lookup on %d of %d names succeeded\n", j, i); + return 0; +} + diff --git a/tests/test14.dat b/tests/test14.dat new file mode 100644 index 000000000..ea0b4eac6 --- /dev/null +++ b/tests/test14.dat @@ -0,0 +1,1219 @@ +JAMES +JOHN +ROBERT +MICHAEL +WILLIAM +DAVID +RICHARD +CHARLES +JOSEPH +THOMAS +CHRISTOPHER +DANIEL +PAUL +MARK +DONALD +GEORGE +KENNETH +STEVEN +EDWARD +BRIAN +RONALD +ANTHONY +KEVIN +JASON +MATTHEW +GARY +TIMOTHY +JOSE +LARRY +JEFFREY +FRANK +SCOTT +ERIC +STEPHEN +ANDREW +RAYMOND +GREGORY +JOSHUA +JERRY +DENNIS +WALTER +PATRICK +PETER +HAROLD +DOUGLAS +HENRY +CARL +ARTHUR +RYAN +ROGER +JOE +JUAN +JACK +ALBERT +JONATHAN +JUSTIN +TERRY +GERALD +KEITH +SAMUEL +WILLIE +RALPH +LAWRENCE +NICHOLAS +ROY +BENJAMIN +BRUCE +BRANDON +ADAM +HARRY +FRED +WAYNE +BILLY +STEVE +LOUIS +JEREMY +AARON +RANDY +HOWARD +EUGENE +CARLOS +RUSSELL +BOBBY +VICTOR +MARTIN +ERNEST +PHILLIP +TODD +JESSE +CRAIG +ALAN +SHAWN +CLARENCE +SEAN +PHILIP +CHRIS +JOHNNY +EARL +JIMMY +ANTONIO +DANNY +BRYAN +TONY +LUIS +MIKE +STANLEY +LEONARD +NATHAN +DALE +MANUEL +RODNEY +CURTIS +NORMAN +ALLEN +MARVIN +VINCENT +GLENN +JEFFERY +TRAVIS +JEFF +CHAD +JACOB +LEE +MELVIN +ALFRED +KYLE +FRANCIS +BRADLEY +JESUS +HERBERT +FREDERICK +RAY +JOEL +EDWIN +DON +EDDIE +RICKY +TROY +RANDALL +BARRY +ALEXANDER +BERNARD +MARIO +LEROY +FRANCISCO +MARCUS +MICHEAL +THEODORE +CLIFFORD +MIGUEL +OSCAR +JAY +JIM +TOM +CALVIN +ALEX +JON +RONNIE +BILL +LLOYD +TOMMY +LEON +DEREK +WARREN +DARRELL +JEROME +FLOYD +LEO +ALVIN +TIM +WESLEY +GORDON +DEAN +GREG +JORGE +DUSTIN +PEDRO +DERRICK +DAN +LEWIS +ZACHARY +COREY +HERMAN +MAURICE +VERNON +ROBERTO +CLYDE +GLEN +HECTOR +SHANE +RICARDO +SAM +RICK +LESTER +BRENT +RAMON +CHARLIE +TYLER +GILBERT +GENE +MARC +REGINALD +RUBEN +BRETT +ANGEL +NATHANIEL +RAFAEL +LESLIE +EDGAR +MILTON +RAUL +BEN +CHESTER +CECIL +DUANE +FRANKLIN +ANDRE +ELMER +BRAD +GABRIEL +RON +MITCHELL +ROLAND +ARNOLD +HARVEY +JARED +ADRIAN +KARL +CORY +CLAUDE +ERIK +DARRYL +JAMIE +NEIL +JESSIE +CHRISTIAN +JAVIER +FERNANDO +CLINTON +TED +MATHEW +TYRONE +DARREN +LONNIE +LANCE +CODY +JULIO +KELLY +KURT +ALLAN +NELSON +GUY +CLAYTON +HUGH +MAX +DWAYNE +DWIGHT +ARMANDO +FELIX +JIMMIE +EVERETT +JORDAN +IAN +WALLACE +KEN +BOB +JAIME +CASEY +ALFREDO +ALBERTO +DAVE +IVAN +JOHNNIE +SIDNEY +BYRON +JULIAN +ISAAC +MORRIS +CLIFTON +WILLARD +DARYL +ROSS +VIRGIL +ANDY +MARSHALL +SALVADOR +PERRY +KIRK +SERGIO +MARION +TRACY +SETH +KENT +TERRANCE +RENE +EDUARDO +TERRENCE +ENRIQUE +FREDDIE +WADE +AUSTIN +STUART +FREDRICK +ARTURO +ALEJANDRO +JACKIE +JOEY +NICK +LUTHER +WENDELL +JEREMIAH +EVAN +JULIUS +DANA +DONNIE +OTIS +SHANNON +TREVOR +OLIVER +LUKE +HOMER +GERARD +DOUG +KENNY +HUBERT +ANGELO +SHAUN +LYLE +MATT +LYNN +ALFONSO +ORLANDO +REX +CARLTON +ERNESTO +CAMERON +NEAL +PABLO +LORENZO +OMAR +WILBUR +BLAKE +GRANT +HORACE +RODERICK +KERRY +ABRAHAM +WILLIS +RICKEY +JEAN +IRA +ANDRES +CESAR +JOHNATHAN +MALCOLM +RUDOLPH +DAMON +KELVIN +RUDY +PRESTON +ALTON +ARCHIE +MARCO +WM +PETE +RANDOLPH +GARRY +GEOFFREY +JONATHON +FELIPE +BENNIE +GERARDO +ED +DOMINIC +ROBIN +LOREN +DELBERT +COLIN +GUILLERMO +EARNEST +LUCAS +BENNY +NOEL +SPENCER +RODOLFO +MYRON +EDMUND +GARRETT +SALVATORE +CEDRIC +LOWELL +GREGG +SHERMAN +WILSON +DEVIN +SYLVESTER +KIM +ROOSEVELT +ISRAEL +JERMAINE +FORREST +WILBERT +LELAND +SIMON +GUADALUPE +CLARK +IRVING +CARROLL +BRYANT +OWEN +RUFUS +WOODROW +SAMMY +KRISTOPHER +MACK +LEVI +MARCOS +GUSTAVO +JAKE +LIONEL +MARTY +TAYLOR +ELLIS +DALLAS +GILBERTO +CLINT +NICOLAS +LAURENCE +ISMAEL +ORVILLE +DREW +JODY +ERVIN +DEWEY +AL +WILFRED +JOSH +HUGO +IGNACIO +CALEB +TOMAS +SHELDON +ERICK +FRANKIE +STEWART +DOYLE +DARREL +ROGELIO +TERENCE +SANTIAGO +ALONZO +ELIAS +BERT +ELBERT +RAMIRO +CONRAD +PAT +NOAH +GRADY +PHIL +CORNELIUS +LAMAR +ROLANDO +CLAY +PERCY +DEXTER +BRADFORD +MERLE +DARIN +AMOS +TERRELL +MOSES +IRVIN +SAUL +ROMAN +DARNELL +RANDAL +TOMMIE +TIMMY +DARRIN +WINSTON +BRENDAN +TOBY +VAN +ABEL +DOMINICK +BOYD +COURTNEY +JAN +EMILIO +ELIJAH +CARY +DOMINGO +SANTOS +AUBREY +EMMETT +MARLON +EMANUEL +JERALD +EDMOND +EMIL +DEWAYNE +WILL +OTTO +TEDDY +REYNALDO +BRET +MORGAN +JESS +TRENT +HUMBERTO +EMMANUEL +STEPHAN +LOUIE +VICENTE +LAMONT +STACY +GARLAND +MILES +MICAH +EFRAIN +BILLIE +LOGAN +HEATH +RODGER +HARLEY +DEMETRIUS +ETHAN +ELDON +ROCKY +PIERRE +JUNIOR +FREDDY +ELI +BRYCE +ANTOINE +ROBBIE +KENDALL +ROYCE +STERLING +MICKEY +CHASE +GROVER +ELTON +CLEVELAND +DYLAN +CHUCK +DAMIAN +REUBEN +STAN +AUGUST +LEONARDO +JASPER +RUSSEL +ERWIN +BENITO +HANS +MONTE +BLAINE +ERNIE +CURT +QUENTIN +AGUSTIN +MURRAY +JAMAL +DEVON +ADOLFO +HARRISON +TYSON +BURTON +BRADY +ELLIOTT +WILFREDO +BART +JARROD +VANCE +DENIS +DAMIEN +JOAQUIN +HARLAN +DESMOND +ELLIOT +DARWIN +ASHLEY +GREGORIO +BUDDY +XAVIER +KERMIT +ROSCOE +ESTEBAN +ANTON +SOLOMON +SCOTTY +NORBERT +ELVIN +WILLIAMS +NOLAN +CAREY +ROD +QUINTON +HAL +BRAIN +ROB +ELWOOD +KENDRICK +DARIUS +MOISES +SON +MARLIN +FIDEL +THADDEUS +CLIFF +MARCEL +ALI +JACKSON +RAPHAEL +BRYON +ARMAND +ALVARO +JEFFRY +DANE +JOESPH +THURMAN +NED +SAMMIE +RUSTY +MICHEL +MONTY +RORY +FABIAN +REGGIE +MASON +GRAHAM +KRIS +ISAIAH +VAUGHN +GUS +AVERY +LOYD +DIEGO +ALEXIS +ADOLPH +NORRIS +MILLARD +ROCCO +GONZALO +DERICK +RODRIGO +GERRY +STACEY +CARMEN +WILEY +RIGOBERTO +ALPHONSO +TY +SHELBY +RICKIE +NOE +VERN +BOBBIE +REED +JEFFERSON +ELVIS +BERNARDO +MAURICIO +HIRAM +DONOVAN +BASIL +RILEY +OLLIE +NICKOLAS +MAYNARD +SCOT +VINCE +QUINCY +EDDY +SEBASTIAN +FEDERICO +ULYSSES +HERIBERTO +DONNELL +COLE +DENNY +DAVIS +GAVIN +EMERY +WARD +ROMEO +JAYSON +DION +DANTE +CLEMENT +COY +ODELL +MAXWELL +JARVIS +BRUNO +ISSAC +MARY +DUDLEY +BROCK +SANFORD +COLBY +CARMELO +BARNEY +NESTOR +HOLLIS +STEFAN +DONNY +ART +LINWOOD +BEAU +WELDON +GALEN +ISIDRO +TRUMAN +DELMAR +JOHNATHON +SILAS +FREDERIC +DICK +KIRBY +IRWIN +CRUZ +MERLIN +MERRILL +CHARLEY +MARCELINO +LANE +HARRIS +CLEO +CARLO +TRENTON +KURTIS +HUNTER +AURELIO +WINFRED +VITO +COLLIN +DENVER +CARTER +LEONEL +EMORY +PASQUALE +MOHAMMAD +MARIANO +DANIAL +BLAIR +LANDON +DIRK +BRANDEN +ADAN +NUMBERS +CLAIR +BUFORD +GERMAN +BERNIE +WILMER +JOAN +EMERSON +ZACHERY +FLETCHER +JACQUES +ERROL +DALTON +MONROE +JOSUE +DOMINIQUE +EDWARDO +BOOKER +WILFORD +SONNY +SHELTON +CARSON +THERON +RAYMUNDO +DAREN +TRISTAN +HOUSTON +ROBBY +LINCOLN +JAME +GENARO +GALE +BENNETT +OCTAVIO +CORNELL +LAVERNE +HUNG +ARRON +ANTONY +HERSCHEL +ALVA +GIOVANNI +GARTH +CYRUS +CYRIL +RONNY +STEVIE +LON +FREEMAN +ERIN +DUNCAN +KENNITH +CARMINE +AUGUSTINE +YOUNG +ERICH +CHADWICK +WILBURN +RUSS +REID +MYLES +ANDERSON +MORTON +JONAS +FOREST +MITCHEL +MERVIN +ZANE +RICH +JAMEL +LAZARO +ALPHONSE +RANDELL +MAJOR +JOHNIE +JARRETT +BROOKS +ARIEL +ABDUL +DUSTY +LUCIANO +LINDSEY +TRACEY +SEYMOUR +SCOTTIE +EUGENIO +MOHAMMED +SANDY +VALENTIN +CHANCE +ARNULFO +LUCIEN +FERDINAND +THAD +EZRA +SYDNEY +ALDO +RUBIN +ROYAL +MITCH +EARLE +ABE +WYATT +MARQUIS +LANNY +KAREEM +JAMAR +BORIS +ISIAH +EMILE +ELMO +ARON +LEOPOLDO +EVERETTE +JOSEF +GAIL +ELOY +DORIAN +RODRICK +REINALDO +LUCIO +JERROD +WESTON +HERSHEL +BARTON +PARKER +LEMUEL +LAVERN +BURT +JULES +GIL +ELISEO +AHMAD +NIGEL +EFREN +ANTWAN +ALDEN +MARGARITO +COLEMAN +REFUGIO +DINO +OSVALDO +LES +DEANDRE +NORMAND +KIETH +IVORY +ANDREA +TREY +NORBERTO +NAPOLEON +JEROLD +FRITZ +ROSENDO +MILFORD +SANG +DEON +CHRISTOPER +ALFONZO +LYMAN +JOSIAH +BRANT +WILTON +RICO +JAMAAL +DEWITT +CAROL +BRENTON +YONG +OLIN +FOSTER +FAUSTINO +CLAUDIO +JUDSON +GINO +EDGARDO +BERRY +ALEC +TANNER +JARRED +DONN +TRINIDAD +TAD +SHIRLEY +PRINCE +PORFIRIO +ODIS +MARIA +LENARD +CHAUNCEY +CHANG +TOD +MEL +MARCELO +KORY +AUGUSTUS +KEVEN +HILARIO +BUD +SAL +ROSARIO +ORVAL +MAURO +DANNIE +ZACHARIAH +OLEN +ANIBAL +MILO +JED +FRANCES +THANH +DILLON +AMADO +NEWTON +CONNIE +LENNY +TORY +RICHIE +LUPE +HORACIO +BRICE +MOHAMED +DELMER +DARIO +REYES +DEE +MAC +JONAH +JERROLD +ROBT +HANK +SUNG +RUPERT +ROLLAND +KENTON +DAMION +CHI +ANTONE +WALDO +FREDRIC +BRADLY +QUINN +KIP +BURL +WALKER +TYREE +JEFFEREY +AHMED +WILLY +STANFORD +OREN +NOBLE +MOSHE +MIKEL +ENOCH +BRENDON +QUINTIN +JAMISON +FLORENCIO +DARRICK +TOBIAS +MINH +HASSAN +GIUSEPPE +DEMARCUS +CLETUS +TYRELL +LYNDON +KEENAN +WERNER +THEO +GERALDO +LOU +COLUMBUS +CHET +BERTRAM +MARKUS +HUEY +HILTON +DWAIN +DONTE +TYRON +OMER +ISAIAS +HIPOLITO +FERMIN +CHUNG +ADALBERTO +VALENTINE +JAMEY +BO +BARRETT +WHITNEY +TEODORO +MCKINLEY +MAXIMO +GARFIELD +SOL +RALEIGH +LAWERENCE +ABRAM +RASHAD +KING +EMMITT +DARON +CHONG +SAMUAL +PARIS +OTHA +MIQUEL +LACY +EUSEBIO +DONG +DOMENIC +DARRON +BUSTER +ANTONIA +WILBER +RENATO +JC +HOYT +HAYWOOD +EZEKIEL +CHAS +FLORENTINO +ELROY +CLEMENTE +ARDEN +NEVILLE +KELLEY +EDISON +DESHAWN +CARROL +SHAYNE +NATHANIAL +JORDON +DANILO +CLAUD +VAL +SHERWOOD +RAYMON +RAYFORD +CRISTOBAL +AMBROSE +TITUS +HYMAN +FELTON +EZEQUIEL +ERASMO +STANTON +LONNY +LEN +IKE +MILAN +LINO +JAROD +HERB +ANDREAS +WALTON +RHETT +PALMER +JUDE +DOUGLASS +CORDELL +OSWALDO +ELLSWORTH +VIRGILIO +TONEY +NATHANAEL +DEL +BRITT +BENEDICT +MOSE +HONG +LEIGH +JOHNSON +ISREAL +GAYLE +GARRET +FAUSTO +ASA +ARLEN +ZACK +WARNER +MODESTO +FRANCESCO +MANUAL +JAE +GAYLORD +GASTON +FILIBERTO +DEANGELO +MICHALE +GRANVILLE +WES +MALIK +ZACKARY +TUAN +NICKY +ELDRIDGE +CRISTOPHER +CORTEZ +ANTIONE +MALCOM +LONG +KOREY +JOSPEH +COLTON +WAYLON +VON +HOSEA +SHAD +SANTO +RUDOLF +ROLF +REY +RENALDO +MARCELLUS +LUCIUS +LESLEY +KRISTOFER +BOYCE +BENTON +MAN +KASEY +JEWELL +HAYDEN +HARLAND +ARNOLDO +RUEBEN +LEANDRO +KRAIG +JERRELL +JEROMY +HOBERT +CEDRICK +ARLIE +WINFORD +WALLY +PATRICIA +LUIGI +KENETH +JACINTO +GRAIG +FRANKLYN +EDMUNDO +SID +PORTER +LEIF +LAUREN +JERAMY +ELISHA +BUCK +WILLIAN +VINCENZO +SHON +MICHAL +LYNWOOD +LINDSAY +JEWEL +JERE +HAI +ELDEN +DORSEY +DARELL +BRODERICK +ALONSO diff --git a/tests/test15.ans b/tests/test15.ans new file mode 100644 index 000000000..ad69a9470 --- /dev/null +++ b/tests/test15.ans @@ -0,0 +1 @@ +betty's id is 2 diff --git a/tests/test15.c b/tests/test15.c new file mode 100644 index 000000000..56140928d --- /dev/null +++ b/tests/test15.c @@ -0,0 +1,40 @@ +#include <string.h> /* strcpy */ +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ +#include "uthash.h" + +struct my_struct { + char name[10]; /* key */ + int id; + UT_hash_handle hh; /* makes this structure hashable */ +}; + + +int main() +{ + const char **n, *names[] = { "joe", "bob", "betty", NULL }; + struct my_struct *s, *tmp, *users = NULL; + int i=0; + + for (n = names; *n != NULL; n++) { + s = (struct my_struct*)malloc(sizeof(struct my_struct)); + if (s == NULL) { + exit(-1); + } + strcpy(s->name, *n); + s->id = i++; + HASH_ADD_STR( users, name, s ); + } + + HASH_FIND_STR( users, "betty", s); + if (s != NULL) { + printf("betty's id is %d\n", s->id); + } + + /* free the hash table contents */ + HASH_ITER(hh, users, s, tmp) { + HASH_DEL(users, s); + free(s); + } + return 0; +} diff --git a/tests/test16.ans b/tests/test16.ans new file mode 100644 index 000000000..1b4d7e183 --- /dev/null +++ b/tests/test16.ans @@ -0,0 +1 @@ +found: user 5, unix time 157680000 diff --git a/tests/test16.c b/tests/test16.c new file mode 100644 index 000000000..f9e2f853b --- /dev/null +++ b/tests/test16.c @@ -0,0 +1,53 @@ +#include <stdlib.h> /* malloc */ +#include <stddef.h> /* offsetof */ +#include <stdio.h> /* printf */ +#include <string.h> /* memset */ +#include "uthash.h" + +struct inner { + int a; + int b; +}; + +struct my_event { + struct inner is; /* key is aggregate of this field */ + char event_code; /* and this field. */ + int user_id; + UT_hash_handle hh; /* makes this structure hashable */ +}; + + +int main() +{ + struct my_event *e, ev, *events = NULL; + unsigned keylen; + int i; + + keylen = offsetof(struct my_event, event_code) + sizeof(char) + - offsetof(struct my_event, is); + + for(i = 0; i < 10; i++) { + e = (struct my_event*)malloc(sizeof(struct my_event)); + if (e == NULL) { + exit(-1); + } + memset(e,0,sizeof(struct my_event)); + e->is.a = i * (60*60*24*365); /* i years (sec)*/ + e->is.b = 0; + e->event_code = 'a'+(i%2); /* meaningless */ + e->user_id = i; + + HASH_ADD( hh, events, is, keylen, e); + } + + /* look for one specific event */ + memset(&ev,0,sizeof(struct my_event)); + ev.is.a = 5 * (60*60*24*365); + ev.is.b = 0; + ev.event_code = 'b'; + HASH_FIND( hh, events, &ev.is, keylen , e); + if (e != NULL) { + printf("found: user %d, unix time %d\n", e->user_id, e->is.a); + } + return 0; +} diff --git a/tests/test17.ans b/tests/test17.ans new file mode 100644 index 000000000..92ae3ef25 --- /dev/null +++ b/tests/test17.ans @@ -0,0 +1,134 @@ +user 9, cookie 81 +user 8, cookie 64 +user 7, cookie 49 +user 6, cookie 36 +user 5, cookie 25 +user 4, cookie 16 +user 3, cookie 9 +user 2, cookie 4 +user 1, cookie 1 +user 0, cookie 0 +sorting +called for a:9, b:8 +called for a:7, b:6 +called for a:5, b:4 +called for a:3, b:2 +called for a:1, b:0 +called for a:8, b:6 +called for a:8, b:7 +called for a:4, b:2 +called for a:4, b:3 +called for a:6, b:2 +called for a:6, b:3 +called for a:6, b:4 +called for a:6, b:5 +called for a:2, b:0 +called for a:2, b:1 +user 0, cookie 0 +user 1, cookie 1 +user 2, cookie 4 +user 3, cookie 9 +user 4, cookie 16 +user 5, cookie 25 +user 6, cookie 36 +user 7, cookie 49 +user 8, cookie 64 +user 9, cookie 81 +adding 10-20 +user 0, cookie 0 +user 1, cookie 1 +user 2, cookie 4 +user 3, cookie 9 +user 4, cookie 16 +user 5, cookie 25 +user 6, cookie 36 +user 7, cookie 49 +user 8, cookie 64 +user 9, cookie 81 +user 20, cookie 400 +user 19, cookie 361 +user 18, cookie 324 +user 17, cookie 289 +user 16, cookie 256 +user 15, cookie 225 +user 14, cookie 196 +user 13, cookie 169 +user 12, cookie 144 +user 11, cookie 121 +user 10, cookie 100 +sorting +called for a:0, b:1 +called for a:2, b:3 +called for a:4, b:5 +called for a:6, b:7 +called for a:8, b:9 +called for a:20, b:19 +called for a:18, b:17 +called for a:16, b:15 +called for a:14, b:13 +called for a:12, b:11 +called for a:0, b:2 +called for a:1, b:2 +called for a:4, b:6 +called for a:5, b:6 +called for a:8, b:19 +called for a:9, b:19 +called for a:17, b:15 +called for a:17, b:16 +called for a:13, b:11 +called for a:13, b:12 +called for a:0, b:4 +called for a:1, b:4 +called for a:2, b:4 +called for a:3, b:4 +called for a:8, b:15 +called for a:9, b:15 +called for a:19, b:15 +called for a:19, b:16 +called for a:19, b:17 +called for a:19, b:18 +called for a:11, b:10 +called for a:0, b:8 +called for a:1, b:8 +called for a:2, b:8 +called for a:3, b:8 +called for a:4, b:8 +called for a:5, b:8 +called for a:6, b:8 +called for a:7, b:8 +called for a:0, b:10 +called for a:1, b:10 +called for a:2, b:10 +called for a:3, b:10 +called for a:4, b:10 +called for a:5, b:10 +called for a:6, b:10 +called for a:7, b:10 +called for a:8, b:10 +called for a:9, b:10 +called for a:15, b:10 +called for a:15, b:11 +called for a:15, b:12 +called for a:15, b:13 +called for a:15, b:14 +user 0, cookie 0 +user 1, cookie 1 +user 2, cookie 4 +user 3, cookie 9 +user 4, cookie 16 +user 5, cookie 25 +user 6, cookie 36 +user 7, cookie 49 +user 8, cookie 64 +user 9, cookie 81 +user 10, cookie 100 +user 11, cookie 121 +user 12, cookie 144 +user 13, cookie 169 +user 14, cookie 196 +user 15, cookie 225 +user 16, cookie 256 +user 17, cookie 289 +user 18, cookie 324 +user 19, cookie 361 +user 20, cookie 400 diff --git a/tests/test17.c b/tests/test17.c new file mode 100644 index 000000000..cb6300128 --- /dev/null +++ b/tests/test17.c @@ -0,0 +1,63 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +static int rev(void *_a, void *_b) +{ + example_user_t *a = (example_user_t*)_a; + example_user_t *b = (example_user_t*)_b; + printf("called for a:%d, b:%d\n",a->id, b->id); + return (a->id - b->id); +} + +int main() +{ + int i; + example_user_t *user, *users=NULL; + + /* create elements */ + for(i=9; i>=0; i--) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + + for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { + printf("user %d, cookie %d\n", user->id, user->cookie); + } + printf("sorting\n"); + HASH_SORT(users,rev); + for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { + printf("user %d, cookie %d\n", user->id, user->cookie); + } + + printf("adding 10-20\n"); + for(i=20; i>=10; i--) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { + printf("user %d, cookie %d\n", user->id, user->cookie); + } + printf("sorting\n"); + HASH_SORT(users,rev); + for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { + printf("user %d, cookie %d\n", user->id, user->cookie); + } + return 0; +} diff --git a/tests/test18.ans b/tests/test18.ans new file mode 100644 index 000000000..db48dcf10 --- /dev/null +++ b/tests/test18.ans @@ -0,0 +1,20 @@ +user 0, cookie 0 +user 1, cookie 1 +user 2, cookie 4 +user 3, cookie 9 +user 4, cookie 16 +user 5, cookie 25 +user 6, cookie 36 +user 7, cookie 49 +user 8, cookie 64 +user 9, cookie 81 +deleting id 0 +deleting id 1 +deleting id 2 +deleting id 3 +deleting id 4 +deleting id 5 +deleting id 6 +deleting id 7 +deleting id 8 +deleting id 9 diff --git a/tests/test18.c b/tests/test18.c new file mode 100644 index 000000000..623cf569c --- /dev/null +++ b/tests/test18.c @@ -0,0 +1,37 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +int main() +{ + int i; + example_user_t *user, *users=NULL; + + /* create elements */ + for(i=0; i<10; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + + for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { + printf("user %d, cookie %d\n", user->id, user->cookie); + } + + /* delete them all, pathologically */ + while(users != NULL) { + printf("deleting id %i\n", users->id); + HASH_DEL(users,users); /* single head/deletee var! */ + } + return 0; +} diff --git a/tests/test19.ans b/tests/test19.ans new file mode 100644 index 000000000..588d0d9a3 --- /dev/null +++ b/tests/test19.ans @@ -0,0 +1,1012 @@ +sorting users ascending +user 0 +user 1 +user 2 +user 3 +user 4 +user 5 +user 6 +user 7 +user 8 +user 9 +sorting altusers descending +altuser 999 +altuser 998 +altuser 997 +altuser 996 +altuser 995 +altuser 994 +altuser 993 +altuser 992 +altuser 991 +altuser 990 +altuser 989 +altuser 988 +altuser 987 +altuser 986 +altuser 985 +altuser 984 +altuser 983 +altuser 982 +altuser 981 +altuser 980 +altuser 979 +altuser 978 +altuser 977 +altuser 976 +altuser 975 +altuser 974 +altuser 973 +altuser 972 +altuser 971 +altuser 970 +altuser 969 +altuser 968 +altuser 967 +altuser 966 +altuser 965 +altuser 964 +altuser 963 +altuser 962 +altuser 961 +altuser 960 +altuser 959 +altuser 958 +altuser 957 +altuser 956 +altuser 955 +altuser 954 +altuser 953 +altuser 952 +altuser 951 +altuser 950 +altuser 949 +altuser 948 +altuser 947 +altuser 946 +altuser 945 +altuser 944 +altuser 943 +altuser 942 +altuser 941 +altuser 940 +altuser 939 +altuser 938 +altuser 937 +altuser 936 +altuser 935 +altuser 934 +altuser 933 +altuser 932 +altuser 931 +altuser 930 +altuser 929 +altuser 928 +altuser 927 +altuser 926 +altuser 925 +altuser 924 +altuser 923 +altuser 922 +altuser 921 +altuser 920 +altuser 919 +altuser 918 +altuser 917 +altuser 916 +altuser 915 +altuser 914 +altuser 913 +altuser 912 +altuser 911 +altuser 910 +altuser 909 +altuser 908 +altuser 907 +altuser 906 +altuser 905 +altuser 904 +altuser 903 +altuser 902 +altuser 901 +altuser 900 +altuser 899 +altuser 898 +altuser 897 +altuser 896 +altuser 895 +altuser 894 +altuser 893 +altuser 892 +altuser 891 +altuser 890 +altuser 889 +altuser 888 +altuser 887 +altuser 886 +altuser 885 +altuser 884 +altuser 883 +altuser 882 +altuser 881 +altuser 880 +altuser 879 +altuser 878 +altuser 877 +altuser 876 +altuser 875 +altuser 874 +altuser 873 +altuser 872 +altuser 871 +altuser 870 +altuser 869 +altuser 868 +altuser 867 +altuser 866 +altuser 865 +altuser 864 +altuser 863 +altuser 862 +altuser 861 +altuser 860 +altuser 859 +altuser 858 +altuser 857 +altuser 856 +altuser 855 +altuser 854 +altuser 853 +altuser 852 +altuser 851 +altuser 850 +altuser 849 +altuser 848 +altuser 847 +altuser 846 +altuser 845 +altuser 844 +altuser 843 +altuser 842 +altuser 841 +altuser 840 +altuser 839 +altuser 838 +altuser 837 +altuser 836 +altuser 835 +altuser 834 +altuser 833 +altuser 832 +altuser 831 +altuser 830 +altuser 829 +altuser 828 +altuser 827 +altuser 826 +altuser 825 +altuser 824 +altuser 823 +altuser 822 +altuser 821 +altuser 820 +altuser 819 +altuser 818 +altuser 817 +altuser 816 +altuser 815 +altuser 814 +altuser 813 +altuser 812 +altuser 811 +altuser 810 +altuser 809 +altuser 808 +altuser 807 +altuser 806 +altuser 805 +altuser 804 +altuser 803 +altuser 802 +altuser 801 +altuser 800 +altuser 799 +altuser 798 +altuser 797 +altuser 796 +altuser 795 +altuser 794 +altuser 793 +altuser 792 +altuser 791 +altuser 790 +altuser 789 +altuser 788 +altuser 787 +altuser 786 +altuser 785 +altuser 784 +altuser 783 +altuser 782 +altuser 781 +altuser 780 +altuser 779 +altuser 778 +altuser 777 +altuser 776 +altuser 775 +altuser 774 +altuser 773 +altuser 772 +altuser 771 +altuser 770 +altuser 769 +altuser 768 +altuser 767 +altuser 766 +altuser 765 +altuser 764 +altuser 763 +altuser 762 +altuser 761 +altuser 760 +altuser 759 +altuser 758 +altuser 757 +altuser 756 +altuser 755 +altuser 754 +altuser 753 +altuser 752 +altuser 751 +altuser 750 +altuser 749 +altuser 748 +altuser 747 +altuser 746 +altuser 745 +altuser 744 +altuser 743 +altuser 742 +altuser 741 +altuser 740 +altuser 739 +altuser 738 +altuser 737 +altuser 736 +altuser 735 +altuser 734 +altuser 733 +altuser 732 +altuser 731 +altuser 730 +altuser 729 +altuser 728 +altuser 727 +altuser 726 +altuser 725 +altuser 724 +altuser 723 +altuser 722 +altuser 721 +altuser 720 +altuser 719 +altuser 718 +altuser 717 +altuser 716 +altuser 715 +altuser 714 +altuser 713 +altuser 712 +altuser 711 +altuser 710 +altuser 709 +altuser 708 +altuser 707 +altuser 706 +altuser 705 +altuser 704 +altuser 703 +altuser 702 +altuser 701 +altuser 700 +altuser 699 +altuser 698 +altuser 697 +altuser 696 +altuser 695 +altuser 694 +altuser 693 +altuser 692 +altuser 691 +altuser 690 +altuser 689 +altuser 688 +altuser 687 +altuser 686 +altuser 685 +altuser 684 +altuser 683 +altuser 682 +altuser 681 +altuser 680 +altuser 679 +altuser 678 +altuser 677 +altuser 676 +altuser 675 +altuser 674 +altuser 673 +altuser 672 +altuser 671 +altuser 670 +altuser 669 +altuser 668 +altuser 667 +altuser 666 +altuser 665 +altuser 664 +altuser 663 +altuser 662 +altuser 661 +altuser 660 +altuser 659 +altuser 658 +altuser 657 +altuser 656 +altuser 655 +altuser 654 +altuser 653 +altuser 652 +altuser 651 +altuser 650 +altuser 649 +altuser 648 +altuser 647 +altuser 646 +altuser 645 +altuser 644 +altuser 643 +altuser 642 +altuser 641 +altuser 640 +altuser 639 +altuser 638 +altuser 637 +altuser 636 +altuser 635 +altuser 634 +altuser 633 +altuser 632 +altuser 631 +altuser 630 +altuser 629 +altuser 628 +altuser 627 +altuser 626 +altuser 625 +altuser 624 +altuser 623 +altuser 622 +altuser 621 +altuser 620 +altuser 619 +altuser 618 +altuser 617 +altuser 616 +altuser 615 +altuser 614 +altuser 613 +altuser 612 +altuser 611 +altuser 610 +altuser 609 +altuser 608 +altuser 607 +altuser 606 +altuser 605 +altuser 604 +altuser 603 +altuser 602 +altuser 601 +altuser 600 +altuser 599 +altuser 598 +altuser 597 +altuser 596 +altuser 595 +altuser 594 +altuser 593 +altuser 592 +altuser 591 +altuser 590 +altuser 589 +altuser 588 +altuser 587 +altuser 586 +altuser 585 +altuser 584 +altuser 583 +altuser 582 +altuser 581 +altuser 580 +altuser 579 +altuser 578 +altuser 577 +altuser 576 +altuser 575 +altuser 574 +altuser 573 +altuser 572 +altuser 571 +altuser 570 +altuser 569 +altuser 568 +altuser 567 +altuser 566 +altuser 565 +altuser 564 +altuser 563 +altuser 562 +altuser 561 +altuser 560 +altuser 559 +altuser 558 +altuser 557 +altuser 556 +altuser 555 +altuser 554 +altuser 553 +altuser 552 +altuser 551 +altuser 550 +altuser 549 +altuser 548 +altuser 547 +altuser 546 +altuser 545 +altuser 544 +altuser 543 +altuser 542 +altuser 541 +altuser 540 +altuser 539 +altuser 538 +altuser 537 +altuser 536 +altuser 535 +altuser 534 +altuser 533 +altuser 532 +altuser 531 +altuser 530 +altuser 529 +altuser 528 +altuser 527 +altuser 526 +altuser 525 +altuser 524 +altuser 523 +altuser 522 +altuser 521 +altuser 520 +altuser 519 +altuser 518 +altuser 517 +altuser 516 +altuser 515 +altuser 514 +altuser 513 +altuser 512 +altuser 511 +altuser 510 +altuser 509 +altuser 508 +altuser 507 +altuser 506 +altuser 505 +altuser 504 +altuser 503 +altuser 502 +altuser 501 +altuser 500 +altuser 499 +altuser 498 +altuser 497 +altuser 496 +altuser 495 +altuser 494 +altuser 493 +altuser 492 +altuser 491 +altuser 490 +altuser 489 +altuser 488 +altuser 487 +altuser 486 +altuser 485 +altuser 484 +altuser 483 +altuser 482 +altuser 481 +altuser 480 +altuser 479 +altuser 478 +altuser 477 +altuser 476 +altuser 475 +altuser 474 +altuser 473 +altuser 472 +altuser 471 +altuser 470 +altuser 469 +altuser 468 +altuser 467 +altuser 466 +altuser 465 +altuser 464 +altuser 463 +altuser 462 +altuser 461 +altuser 460 +altuser 459 +altuser 458 +altuser 457 +altuser 456 +altuser 455 +altuser 454 +altuser 453 +altuser 452 +altuser 451 +altuser 450 +altuser 449 +altuser 448 +altuser 447 +altuser 446 +altuser 445 +altuser 444 +altuser 443 +altuser 442 +altuser 441 +altuser 440 +altuser 439 +altuser 438 +altuser 437 +altuser 436 +altuser 435 +altuser 434 +altuser 433 +altuser 432 +altuser 431 +altuser 430 +altuser 429 +altuser 428 +altuser 427 +altuser 426 +altuser 425 +altuser 424 +altuser 423 +altuser 422 +altuser 421 +altuser 420 +altuser 419 +altuser 418 +altuser 417 +altuser 416 +altuser 415 +altuser 414 +altuser 413 +altuser 412 +altuser 411 +altuser 410 +altuser 409 +altuser 408 +altuser 407 +altuser 406 +altuser 405 +altuser 404 +altuser 403 +altuser 402 +altuser 401 +altuser 400 +altuser 399 +altuser 398 +altuser 397 +altuser 396 +altuser 395 +altuser 394 +altuser 393 +altuser 392 +altuser 391 +altuser 390 +altuser 389 +altuser 388 +altuser 387 +altuser 386 +altuser 385 +altuser 384 +altuser 383 +altuser 382 +altuser 381 +altuser 380 +altuser 379 +altuser 378 +altuser 377 +altuser 376 +altuser 375 +altuser 374 +altuser 373 +altuser 372 +altuser 371 +altuser 370 +altuser 369 +altuser 368 +altuser 367 +altuser 366 +altuser 365 +altuser 364 +altuser 363 +altuser 362 +altuser 361 +altuser 360 +altuser 359 +altuser 358 +altuser 357 +altuser 356 +altuser 355 +altuser 354 +altuser 353 +altuser 352 +altuser 351 +altuser 350 +altuser 349 +altuser 348 +altuser 347 +altuser 346 +altuser 345 +altuser 344 +altuser 343 +altuser 342 +altuser 341 +altuser 340 +altuser 339 +altuser 338 +altuser 337 +altuser 336 +altuser 335 +altuser 334 +altuser 333 +altuser 332 +altuser 331 +altuser 330 +altuser 329 +altuser 328 +altuser 327 +altuser 326 +altuser 325 +altuser 324 +altuser 323 +altuser 322 +altuser 321 +altuser 320 +altuser 319 +altuser 318 +altuser 317 +altuser 316 +altuser 315 +altuser 314 +altuser 313 +altuser 312 +altuser 311 +altuser 310 +altuser 309 +altuser 308 +altuser 307 +altuser 306 +altuser 305 +altuser 304 +altuser 303 +altuser 302 +altuser 301 +altuser 300 +altuser 299 +altuser 298 +altuser 297 +altuser 296 +altuser 295 +altuser 294 +altuser 293 +altuser 292 +altuser 291 +altuser 290 +altuser 289 +altuser 288 +altuser 287 +altuser 286 +altuser 285 +altuser 284 +altuser 283 +altuser 282 +altuser 281 +altuser 280 +altuser 279 +altuser 278 +altuser 277 +altuser 276 +altuser 275 +altuser 274 +altuser 273 +altuser 272 +altuser 271 +altuser 270 +altuser 269 +altuser 268 +altuser 267 +altuser 266 +altuser 265 +altuser 264 +altuser 263 +altuser 262 +altuser 261 +altuser 260 +altuser 259 +altuser 258 +altuser 257 +altuser 256 +altuser 255 +altuser 254 +altuser 253 +altuser 252 +altuser 251 +altuser 250 +altuser 249 +altuser 248 +altuser 247 +altuser 246 +altuser 245 +altuser 244 +altuser 243 +altuser 242 +altuser 241 +altuser 240 +altuser 239 +altuser 238 +altuser 237 +altuser 236 +altuser 235 +altuser 234 +altuser 233 +altuser 232 +altuser 231 +altuser 230 +altuser 229 +altuser 228 +altuser 227 +altuser 226 +altuser 225 +altuser 224 +altuser 223 +altuser 222 +altuser 221 +altuser 220 +altuser 219 +altuser 218 +altuser 217 +altuser 216 +altuser 215 +altuser 214 +altuser 213 +altuser 212 +altuser 211 +altuser 210 +altuser 209 +altuser 208 +altuser 207 +altuser 206 +altuser 205 +altuser 204 +altuser 203 +altuser 202 +altuser 201 +altuser 200 +altuser 199 +altuser 198 +altuser 197 +altuser 196 +altuser 195 +altuser 194 +altuser 193 +altuser 192 +altuser 191 +altuser 190 +altuser 189 +altuser 188 +altuser 187 +altuser 186 +altuser 185 +altuser 184 +altuser 183 +altuser 182 +altuser 181 +altuser 180 +altuser 179 +altuser 178 +altuser 177 +altuser 176 +altuser 175 +altuser 174 +altuser 173 +altuser 172 +altuser 171 +altuser 170 +altuser 169 +altuser 168 +altuser 167 +altuser 166 +altuser 165 +altuser 164 +altuser 163 +altuser 162 +altuser 161 +altuser 160 +altuser 159 +altuser 158 +altuser 157 +altuser 156 +altuser 155 +altuser 154 +altuser 153 +altuser 152 +altuser 151 +altuser 150 +altuser 149 +altuser 148 +altuser 147 +altuser 146 +altuser 145 +altuser 144 +altuser 143 +altuser 142 +altuser 141 +altuser 140 +altuser 139 +altuser 138 +altuser 137 +altuser 136 +altuser 135 +altuser 134 +altuser 133 +altuser 132 +altuser 131 +altuser 130 +altuser 129 +altuser 128 +altuser 127 +altuser 126 +altuser 125 +altuser 124 +altuser 123 +altuser 122 +altuser 121 +altuser 120 +altuser 119 +altuser 118 +altuser 117 +altuser 116 +altuser 115 +altuser 114 +altuser 113 +altuser 112 +altuser 111 +altuser 110 +altuser 109 +altuser 108 +altuser 107 +altuser 106 +altuser 105 +altuser 104 +altuser 103 +altuser 102 +altuser 101 +altuser 100 +altuser 99 +altuser 98 +altuser 97 +altuser 96 +altuser 95 +altuser 94 +altuser 93 +altuser 92 +altuser 91 +altuser 90 +altuser 89 +altuser 88 +altuser 87 +altuser 86 +altuser 85 +altuser 84 +altuser 83 +altuser 82 +altuser 81 +altuser 80 +altuser 79 +altuser 78 +altuser 77 +altuser 76 +altuser 75 +altuser 74 +altuser 73 +altuser 72 +altuser 71 +altuser 70 +altuser 69 +altuser 68 +altuser 67 +altuser 66 +altuser 65 +altuser 64 +altuser 63 +altuser 62 +altuser 61 +altuser 60 +altuser 59 +altuser 58 +altuser 57 +altuser 56 +altuser 55 +altuser 54 +altuser 53 +altuser 52 +altuser 51 +altuser 50 +altuser 49 +altuser 48 +altuser 47 +altuser 46 +altuser 45 +altuser 44 +altuser 43 +altuser 42 +altuser 41 +altuser 40 +altuser 39 +altuser 38 +altuser 37 +altuser 36 +altuser 35 +altuser 34 +altuser 33 +altuser 32 +altuser 31 +altuser 30 +altuser 29 +altuser 28 +altuser 27 +altuser 26 +altuser 25 +altuser 24 +altuser 23 +altuser 22 +altuser 21 +altuser 20 +altuser 19 +altuser 18 +altuser 17 +altuser 16 +altuser 15 +altuser 14 +altuser 13 +altuser 12 +altuser 11 +altuser 10 +altuser 9 +altuser 8 +altuser 7 +altuser 6 +altuser 5 +altuser 4 +altuser 3 +altuser 2 +altuser 1 +altuser 0 diff --git a/tests/test19.c b/tests/test19.c new file mode 100644 index 000000000..aec898f8f --- /dev/null +++ b/tests/test19.c @@ -0,0 +1,66 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; + UT_hash_handle alth; +} example_user_t; + +static int ascending_sort(void *_a, void *_b) +{ + example_user_t *a = (example_user_t*)_a; + example_user_t *b = (example_user_t*)_b; + if (a->id == b->id) { + return 0; + } + return (a->id < b->id) ? -1 : 1; +} + +static int descending_sort(void *_a, void *_b) +{ + example_user_t *a = (example_user_t*)_a; + example_user_t *b = (example_user_t*)_b; + if (a->id == b->id) { + return 0; + } + return (a->id < b->id) ? 1 : -1; +} + +int main() +{ + int i; + example_user_t *user, *users=NULL, *altusers=NULL; + + /* create elements */ + for(i=0; i<1000; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + if (i<10) { + HASH_ADD_INT(users,id,user); + } + HASH_ADD(alth,altusers,id,sizeof(int),user); + } + + printf("sorting users ascending\n"); + HASH_SRT(hh,users,ascending_sort); + for(user=users; user!=NULL; user=(example_user_t*)user->hh.next) { + printf("user %d\n", user->id); + } + + printf("sorting altusers descending\n"); + HASH_SRT(alth,altusers,descending_sort); + for(user=altusers; user!=NULL; user=(example_user_t*)user->alth.next) { + printf("altuser %d\n", user->id); + } + + /* HASH_FSCK(hh,users); */ + /* HASH_FSCK(alth,altusers); */ + return 0; +} diff --git a/tests/test2.ans b/tests/test2.ans new file mode 100644 index 000000000..fd4e2f8ad --- /dev/null +++ b/tests/test2.ans @@ -0,0 +1,5 @@ +user id 0 found, cookie 0 +user id 2 found, cookie 4 +user id 4 found, cookie 16 +user id 6 found, cookie 36 +user id 8 found, cookie 64 diff --git a/tests/test2.c b/tests/test2.c new file mode 100644 index 000000000..30bbb2f11 --- /dev/null +++ b/tests/test2.c @@ -0,0 +1,38 @@ +#include "uthash.h" +#include <time.h> +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +int main() +{ + int i; + example_user_t *user, *tmp, *users=NULL; + + /* create elements */ + for(i=0; i<10; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + + /* find each even ID */ + for(i=0; i<10; i+=2) { + HASH_FIND_INT(users,&i,tmp); + if (tmp != NULL) { + printf("user id %d found, cookie %d\n", tmp->id, tmp->cookie); + } else { + printf("user id %d not found\n", i); + } + } + return 0; +} diff --git a/tests/test20.ans b/tests/test20.ans new file mode 100644 index 000000000..4d3bb1d0b --- /dev/null +++ b/tests/test20.ans @@ -0,0 +1 @@ +found diff --git a/tests/test20.c b/tests/test20.c new file mode 100644 index 000000000..9ac01f0ac --- /dev/null +++ b/tests/test20.c @@ -0,0 +1,34 @@ +#include <string.h> /* memcpy */ +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ +#include "uthash.h" + +struct my_struct { + char bkey[5]; /* "binary" key */ + int data; + UT_hash_handle hh; +}; + +int main() +{ + struct my_struct *s, *t, *bins = NULL; + char binary[5] = {'\3','\1','\4','\1','\6'}; + + /* allocate our structure. initialize to some values */ + s = (struct my_struct*)calloc(1UL,sizeof(struct my_struct)); + if (s == NULL) { + exit(-1); + } + memcpy(s->bkey, binary, sizeof(binary)); + + /* add to hash table using general macro */ + HASH_ADD( hh, bins, bkey, sizeof(binary), s); + + /* look up the structure we just added */ + HASH_FIND( hh, bins, binary, sizeof(binary), t ); + + if (t != NULL) { + printf("found\n"); + } + return 0; +} diff --git a/tests/test21.ans b/tests/test21.ans new file mode 100644 index 000000000..af89f48c2 --- /dev/null +++ b/tests/test21.ans @@ -0,0 +1 @@ +found a 1 diff --git a/tests/test21.c b/tests/test21.c new file mode 100644 index 000000000..b4000df1d --- /dev/null +++ b/tests/test21.c @@ -0,0 +1,44 @@ +#include <stdlib.h> +#include <stdio.h> +#include "uthash.h" + +typedef struct { + char a; + int b; +} record_key_t; + +typedef struct { + record_key_t key; + /* ... other data ... */ + UT_hash_handle hh; +} record_t; + +int main() +{ + record_t l, *p, *r, *tmp, *records = NULL; + + r = (record_t*)malloc( sizeof(record_t) ); + if (r == NULL) { + exit(-1); + } + memset(r, 0, sizeof(record_t)); + r->key.a = 'a'; + r->key.b = 1; + HASH_ADD(hh, records, key, sizeof(record_key_t), r); + + memset(&l, 0, sizeof(record_t)); + l.key.a = 'a'; + l.key.b = 1; + HASH_FIND(hh, records, &l.key, sizeof(record_key_t), p); + + if (p != NULL) { + printf("found %c %d\n", p->key.a, p->key.b); + } + + HASH_ITER(hh, records, p, tmp) { + HASH_DEL(records, p); + free(p); + } + return 0; +} + diff --git a/tests/test22.ans b/tests/test22.ans new file mode 100644 index 000000000..2483a24d6 --- /dev/null +++ b/tests/test22.ans @@ -0,0 +1 @@ +found diff --git a/tests/test22.c b/tests/test22.c new file mode 100644 index 000000000..d013db925 --- /dev/null +++ b/tests/test22.c @@ -0,0 +1,68 @@ +#include <stdlib.h> /* malloc */ +#include <stddef.h> /* offsetof */ +#include <stdio.h> /* printf */ +#include <string.h> /* memset */ +#include "uthash.h" + +#define UTF32 '\x1' + +typedef struct { + UT_hash_handle hh; + size_t len; + char encoding; /* these two fields */ + int text[]; /* comprise the key */ +} msg_t; + +typedef struct { + char encoding; + int text[]; +} lookup_key_t; + +int main() +{ + unsigned keylen; + msg_t *msg, *tmp, *msgs = NULL; + lookup_key_t *lookup_key; + + int beijing[] = {0x5317, 0x4eac}; /* UTF-32LE for 北京 */ + + /* allocate and initialize our structure */ + msg = (msg_t*)malloc( sizeof(msg_t) + sizeof(beijing) ); + if (msg == NULL) { + exit(-1); + } + memset(msg, 0, sizeof(msg_t)+sizeof(beijing)); /* zero fill */ + msg->len = sizeof(beijing); + msg->encoding = UTF32; + memcpy(msg->text, beijing, sizeof(beijing)); + + /* calculate the key length including padding, using formula */ + keylen = offsetof(msg_t, text) /* offset of last key field */ + + sizeof(beijing) /* size of last key field */ + - offsetof(msg_t, encoding); /* offset of first key field */ + + /* add our structure to the hash table */ + HASH_ADD( hh, msgs, encoding, keylen, msg); + + /* look it up to prove that it worked :-) */ + msg=NULL; + + lookup_key = (lookup_key_t*)malloc(sizeof(*lookup_key) + sizeof(beijing)); + if (lookup_key == NULL) { + exit(-1); + } + memset(lookup_key, 0, sizeof(*lookup_key) + sizeof(beijing)); + lookup_key->encoding = UTF32; + memcpy(lookup_key->text, beijing, sizeof(beijing)); + HASH_FIND( hh, msgs, &lookup_key->encoding, keylen, msg ); + if (msg != NULL) { + printf("found \n"); + } + free(lookup_key); + + HASH_ITER(hh, msgs, msg, tmp) { + HASH_DEL(msgs, msg); + free(msg); + } + return 0; +} diff --git a/tests/test23.ans b/tests/test23.ans new file mode 100644 index 000000000..79ed10a1a --- /dev/null +++ b/tests/test23.ans @@ -0,0 +1,6 @@ +found 12345 +found 6789 +found 98765 +deleting 12345 +deleting 6789 +deleting 98765 diff --git a/tests/test23.c b/tests/test23.c new file mode 100644 index 000000000..132da4207 --- /dev/null +++ b/tests/test23.c @@ -0,0 +1,69 @@ +#include <stdio.h> +#include <stdlib.h> +#include "uthash.h" + +typedef struct { + int key; + int data; + UT_hash_handle hh; +} item; + +int main() +{ + item *i, *j, *items=NULL; + int k; + + /* first item */ + k = 12345; + i = (item*)malloc(sizeof(item)); + if (i == NULL) { + exit(-1); + } + i->key = k; + i->data = 0; + HASH_ADD_INT(items,key,i); + + /* second item */ + k = 6789; + i = (item*)malloc(sizeof(item)); + if (i == NULL) { + exit(-1); + } + i->key = k; + i->data = 0; + HASH_ADD_INT(items,key,i); + + /* third item */ + k = 98765; + i = (item*)malloc(sizeof(item)); + if (i == NULL) { + exit(-1); + } + i->key = k; + i->data = 0; + HASH_ADD_INT(items,key,i); + + /* look them all up */ + k = 12345; + HASH_FIND_INT(items, &k, j); + if (j != NULL) { + printf("found %d\n",k); + } + k = 6789; + HASH_FIND_INT(items, &k, j); + if (j != NULL) { + printf("found %d\n",k); + } + k = 98765; + HASH_FIND_INT(items, &k, j); + if (j != NULL) { + printf("found %d\n",k); + } + + /* delete them not the way we prefer but it works */ + for(j=items; j != NULL; j=(item*)j->hh.next) { + printf("deleting %d\n", j->key); + HASH_DEL(items,j); + } + return 0; +} diff --git a/tests/test24.ans b/tests/test24.ans new file mode 100644 index 000000000..4a2034ac8 --- /dev/null +++ b/tests/test24.ans @@ -0,0 +1 @@ +hash contains 10 items diff --git a/tests/test24.c b/tests/test24.c new file mode 100644 index 000000000..459d6bd01 --- /dev/null +++ b/tests/test24.c @@ -0,0 +1,29 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +int main() +{ + int i; + example_user_t *user, *users=NULL; + + /* create elements */ + for(i=0; i<10; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + + printf("hash contains %u items\n", HASH_COUNT(users)); + return 0; +} diff --git a/tests/test25.ans b/tests/test25.ans new file mode 100644 index 000000000..9490482f4 --- /dev/null +++ b/tests/test25.ans @@ -0,0 +1,31 @@ +CDL macros +c b a +count = 3 +advancing head pointer +b a c +b a c b a c b a c b +b c a b c a b c a b +deleting b +a c +deleting (a) +c +deleting (c) + +DL macros +a b c +count = 3 +deleting tail c +a b +deleting head a +b +deleting head b + +LL macros +a b c +count = 3 +deleting tail c +a b +deleting head a +b +deleting head b + diff --git a/tests/test25.c b/tests/test25.c new file mode 100644 index 000000000..22e3761d8 --- /dev/null +++ b/tests/test25.c @@ -0,0 +1,138 @@ +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *next, *prev; +} el; + +int main() +{ + int i; + int count; + el els[10], *e; + el *head = NULL; + for(i=0; i<10; i++) { + els[i].id=(int)'a'+i; + } + + /* test CDL macros */ + printf("CDL macros\n"); + CDL_PREPEND(head,&els[0]); + CDL_PREPEND(head,&els[1]); + CDL_PREPEND(head,&els[2]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + CDL_COUNT(head,e, count); + printf("count = %d\n", count); + + /* point head to head->next */ + printf("advancing head pointer\n"); + head = head->next; + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* follow circular loop a few times */ + for(i=0,e=head; e && i<10; i++,e=e->next) { + printf("%c ", e->id); + } + printf("\n"); + + /* follow circular loop backwards a few times */ + for(i=0,e=head; e && i<10; i++,e=e->prev) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting b\n"); + CDL_DELETE(head,&els[1]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (a)\n"); + CDL_DELETE(head,&els[0]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (c)\n"); + CDL_DELETE(head,&els[2]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* test DL macros */ + printf("DL macros\n"); + DL_APPEND(head,&els[0]); + DL_APPEND(head,&els[1]); + DL_APPEND(head,&els[2]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + DL_COUNT(head,e, count); + printf("count = %d\n", count); + + printf("deleting tail c\n"); + DL_DELETE(head,&els[2]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting head a\n"); + DL_DELETE(head,&els[0]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting head b\n"); + DL_DELETE(head,&els[1]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* test LL macros */ + printf("LL macros\n"); + LL_APPEND(head,&els[0]); + LL_APPEND(head,&els[1]); + LL_APPEND(head,&els[2]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + LL_COUNT(head,e,count); + printf("count = %d\n", count); + + printf("deleting tail c\n"); + LL_DELETE(head,&els[2]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting head a\n"); + LL_DELETE(head,&els[0]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting head b\n"); + LL_DELETE(head,&els[1]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + return 0; +} diff --git a/tests/test26.ans b/tests/test26.ans new file mode 100644 index 000000000..764b01d2d --- /dev/null +++ b/tests/test26.ans @@ -0,0 +1,53 @@ +ADRIAN +ARNOLDO +CARROLL +CARY +CHONG +CLIFTON +CODY +COLTON +CORNELL +DAMON +DANNIE +DARIO +DONN +DOUG +DOUGLAS +FREDERICK +FRITZ +GERALD +GUS +HARVEY +IRVING +ISAIAH +JARVIS +JOHN +KENTON +LAURENCE +LESTER +LINCOLN +LOWELL +NELSON +NEVILLE +NIGEL +NORMAND +ODIS +OMAR +ORLANDO +RAYMUNDO +REX +ROLANDO +RON +SHANE +TONEY +TRINIDAD +WALTER +WARNER +WARREN +WES +WILLARD +WILLIAM +WINFRED +XAVIER +found WES + diff --git a/tests/test26.c b/tests/test26.c new file mode 100644 index 000000000..6e9d96214 --- /dev/null +++ b/tests/test26.c @@ -0,0 +1,61 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "utlist.h" + +#define BUFLEN 20 + +typedef struct el { + char bname[BUFLEN]; + struct el *next, *prev; +} el; + +static int namecmp(void *_a, void *_b) +{ + el *a = (el*)_a; + el *b = (el*)_b; + return strcmp(a->bname,b->bname); +} + +int main() +{ + el *name, *elt, *tmp, etmp; + el *head = NULL; /* important- initialize to NULL! */ + + char linebuf[BUFLEN]; + FILE *file; + + file = fopen( "test11.dat", "r" ); + if (file == NULL) { + perror("can't open: "); + exit(-1); + } + + while (fgets(linebuf,BUFLEN,file) != NULL) { + name = (el*)malloc(sizeof(el)); + if (name == NULL) { + exit(-1); + } + strcpy(name->bname, linebuf); + DL_APPEND(head, name); + } + DL_SORT(head, namecmp); + DL_FOREACH(head,elt) { + printf("%s", elt->bname); + } + + memcpy(etmp.bname, "WES\n", 5UL); + DL_SEARCH(head,elt,&etmp,namecmp); + if (elt != NULL) { + printf("found %s\n", elt->bname); + } + + /* now delete each element, use the safe iterator */ + DL_FOREACH_SAFE(head,elt,tmp) { + DL_DELETE(head,elt); + } + + fclose(file); + + return 0; +} diff --git a/tests/test27.ans b/tests/test27.ans new file mode 100644 index 000000000..80b476c66 --- /dev/null +++ b/tests/test27.ans @@ -0,0 +1,28 @@ +CDL macros +c b a +advancing head pointer +b a c +b a c b a c b a c b +b c a b c a b c a b +deleting b +a c +deleting head (a) +c +deleting new head (c) + +DL macros +c b a +deleting c +b a +deleting a +b +deleting b + +LL macros +c b a +deleting c +b a +deleting a +b +deleting b + diff --git a/tests/test27.c b/tests/test27.c new file mode 100644 index 000000000..73842ee2c --- /dev/null +++ b/tests/test27.c @@ -0,0 +1,130 @@ +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *next, *prev; +} el; + +int main() +{ + int i; + el els[10], *e; + el *head = NULL; + for(i=0; i<10; i++) { + els[i].id=(int)'a'+i; + } + + /* test CDL macros */ + printf("CDL macros\n"); + CDL_PREPEND(head,&els[0]); + CDL_PREPEND(head,&els[1]); + CDL_PREPEND(head,&els[2]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* point head to head->next */ + printf("advancing head pointer\n"); + head = head->next; + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* follow circular loop a few times */ + for(i=0,e=head; e && i<10; i++,e=e->next) { + printf("%c ", e->id); + } + printf("\n"); + + /* follow circular loop backwards a few times */ + for(i=0,e=head; e && i<10; i++,e=e->prev) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting b\n"); + CDL_DELETE(head,&els[1]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting head (a)\n"); + CDL_DELETE(head,&els[0]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting new head (c)\n"); + CDL_DELETE(head,&els[2]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* test DL macros */ + printf("DL macros\n"); + DL_PREPEND(head,&els[0]); + DL_PREPEND(head,&els[1]); + DL_PREPEND(head,&els[2]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting c\n"); + DL_DELETE(head,&els[2]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting a\n"); + DL_DELETE(head,&els[0]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting b\n"); + DL_DELETE(head,&els[1]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* test LL macros */ + printf("LL macros\n"); + LL_PREPEND(head,&els[0]); + LL_PREPEND(head,&els[1]); + LL_PREPEND(head,&els[2]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting c\n"); + LL_DELETE(head,&els[2]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting a\n"); + LL_DELETE(head,&els[0]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting b\n"); + LL_DELETE(head,&els[1]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + return 0; +} diff --git a/tests/test28.ans b/tests/test28.ans new file mode 100644 index 000000000..eb88650af --- /dev/null +++ b/tests/test28.ans @@ -0,0 +1,34 @@ +CDL macros +d c b a +advancing head pointer +c b a d +c b a d c b a d c b +c d a b c d a b c d +deleting b +c a d +deleting (a) +c d +deleting (c) +d +deleting (d) + +DL macros +c b a d +deleting c +b a d +deleting a +b d +deleting b +d +deleting d + +LL macros +c b a d +deleting c +b a d +deleting a +b d +deleting b +d +deleting d + diff --git a/tests/test28.c b/tests/test28.c new file mode 100644 index 000000000..da32c082c --- /dev/null +++ b/tests/test28.c @@ -0,0 +1,153 @@ +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *next, *prev; +} el; + +int main() +{ + int i; + el els[10], *e; + el *head = NULL; + for(i=0; i<10; i++) { + els[i].id=(int)'a'+i; + } + + /* test CDL macros */ + printf("CDL macros\n"); + CDL_PREPEND(head,&els[0]); + CDL_PREPEND(head,&els[1]); + CDL_PREPEND(head,&els[2]); + CDL_PREPEND(head,&els[3]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* point head to head->next */ + printf("advancing head pointer\n"); + head = head->next; + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* follow circular loop a few times */ + for(i=0,e=head; e && i<10; i++,e=e->next) { + printf("%c ", e->id); + } + printf("\n"); + + /* follow circular loop backwards a few times */ + for(i=0,e=head; e && i<10; i++,e=e->prev) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting b\n"); + CDL_DELETE(head,&els[1]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (a)\n"); + CDL_DELETE(head,&els[0]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (c)\n"); + CDL_DELETE(head,&els[2]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (d)\n"); + CDL_DELETE(head,&els[3]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* test DL macros */ + printf("DL macros\n"); + DL_PREPEND(head,&els[0]); + DL_PREPEND(head,&els[1]); + DL_PREPEND(head,&els[2]); + DL_APPEND(head,&els[3]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting c\n"); + DL_DELETE(head,&els[2]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting a\n"); + DL_DELETE(head,&els[0]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting b\n"); + DL_DELETE(head,&els[1]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting d\n"); + DL_DELETE(head,&els[3]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* test LL macros */ + printf("LL macros\n"); + LL_PREPEND(head,&els[0]); + LL_PREPEND(head,&els[1]); + LL_PREPEND(head,&els[2]); + LL_APPEND(head,&els[3]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting c\n"); + LL_DELETE(head,&els[2]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting a\n"); + LL_DELETE(head,&els[0]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting b\n"); + LL_DELETE(head,&els[1]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting d\n"); + LL_DELETE(head,&els[3]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + return 0; +} diff --git a/tests/test29.ans b/tests/test29.ans new file mode 100644 index 000000000..6467b600a --- /dev/null +++ b/tests/test29.ans @@ -0,0 +1,103 @@ +ADRIAN +ARNOLDO +CARROLL +CARY +CHONG +CLIFTON +CODY +COLTON +CORNELL +DAMON +DANNIE +DARIO +DONN +DOUG +DOUGLAS +FREDERICK +FRITZ +GERALD +GUS +HARVEY +IRVING +ISAIAH +JARVIS +JOHN +KENTON +LAURENCE +LESTER +LINCOLN +LOWELL +NELSON +NEVILLE +NIGEL +NORMAND +ODIS +OMAR +ORLANDO +RAYMUNDO +REX +ROLANDO +RON +SHANE +TONEY +TRINIDAD +WALTER +WARNER +WARREN +WES +WILLARD +WILLIAM +WINFRED +XAVIER +deleting head ADRIAN +head->prev: XAVIER +ARNOLDO +CARROLL +CARY +CHONG +CLIFTON +CODY +COLTON +CORNELL +DAMON +DANNIE +DARIO +DONN +DOUG +DOUGLAS +FREDERICK +FRITZ +GERALD +GUS +HARVEY +IRVING +ISAIAH +JARVIS +JOHN +KENTON +LAURENCE +LESTER +LINCOLN +LOWELL +NELSON +NEVILLE +NIGEL +NORMAND +ODIS +OMAR +ORLANDO +RAYMUNDO +REX +ROLANDO +RON +SHANE +TONEY +TRINIDAD +WALTER +WARNER +WARREN +WES +WILLARD +WILLIAM +WINFRED +XAVIER diff --git a/tests/test29.c b/tests/test29.c new file mode 100644 index 000000000..e579a0e23 --- /dev/null +++ b/tests/test29.c @@ -0,0 +1,57 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "utlist.h" + +#define BUFLEN 20 + +typedef struct el { + char bname[BUFLEN]; + struct el *next, *prev; +} el; + +static int namecmp(void *_a, void *_b) +{ + el *a = (el*)_a; + el *b = (el*)_b; + return strcmp(a->bname,b->bname); +} + +int main() +{ + el *name, *tmp; + el *head = NULL; + + char linebuf[BUFLEN]; + FILE *file; + + file = fopen( "test11.dat", "r" ); + if (file == NULL) { + perror("can't open: "); + exit(-1); + } + + while (fgets(linebuf,BUFLEN,file) != NULL) { + name = (el*)malloc(sizeof(el)); + if (name == NULL) { + exit(-1); + } + strcpy(name->bname, linebuf); + DL_APPEND(head, name); + } + DL_SORT(head, namecmp); + DL_FOREACH(head,tmp) { + printf("%s", tmp->bname); + } + + /* now delete the list head */ + printf("deleting head %shead->prev: %s", head->bname, head->prev->bname); + DL_DELETE(head,head); + DL_FOREACH(head,tmp) { + printf("%s", tmp->bname); + } + + fclose(file); + + return 0; +} diff --git a/tests/test3.ans b/tests/test3.ans new file mode 100644 index 000000000..56a52a3f0 --- /dev/null +++ b/tests/test3.ans @@ -0,0 +1,5 @@ +user 1, cookie 1 +user 3, cookie 9 +user 5, cookie 25 +user 7, cookie 49 +user 9, cookie 81 diff --git a/tests/test3.c b/tests/test3.c new file mode 100644 index 000000000..630b8b3d3 --- /dev/null +++ b/tests/test3.c @@ -0,0 +1,43 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +int main() +{ + int i; + example_user_t *user, *tmp, *users=NULL; + + /* create elements */ + for(i=0; i<10; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + + /* delete each even ID */ + for(i=0; i<10; i+=2) { + HASH_FIND_INT(users,&i,tmp); + if (tmp != NULL) { + HASH_DEL(users,tmp); + free(tmp); + } else { + printf("user id %d not found\n", i); + } + } + + /* show the hash */ + for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { + printf("user %d, cookie %d\n", user->id, user->cookie); + } + return 0; +} diff --git a/tests/test30.ans b/tests/test30.ans new file mode 100644 index 000000000..2b72e985a --- /dev/null +++ b/tests/test30.ans @@ -0,0 +1,51 @@ +ADRIAN +ARNOLDO +CARROLL +CARY +CHONG +CLIFTON +CODY +COLTON +CORNELL +DAMON +DANNIE +DARIO +DONN +DOUG +DOUGLAS +FREDERICK +FRITZ +GERALD +GUS +HARVEY +IRVING +ISAIAH +JARVIS +JOHN +KENTON +LAURENCE +LESTER +LINCOLN +LOWELL +NELSON +NEVILLE +NIGEL +NORMAND +ODIS +OMAR +ORLANDO +RAYMUNDO +REX +ROLANDO +RON +SHANE +TONEY +TRINIDAD +WALTER +WARNER +WARREN +WES +WILLARD +WILLIAM +WINFRED +XAVIER diff --git a/tests/test30.c b/tests/test30.c new file mode 100644 index 000000000..58bfb7356 --- /dev/null +++ b/tests/test30.c @@ -0,0 +1,50 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "utlist.h" + +#define BUFLEN 20 + +typedef struct el { + char bname[BUFLEN]; + struct el *next, *prev; +} el; + +static int namecmp(void *_a, void *_b) +{ + el *a = (el*)_a; + el *b = (el*)_b; + return strcmp(a->bname,b->bname); +} + +int main() +{ + el *name, *tmp; + el *head = NULL; + + char linebuf[BUFLEN]; + FILE *file; + + file = fopen( "test11.dat", "r" ); + if (file == NULL) { + perror("can't open: "); + exit(-1); + } + + while (fgets(linebuf,BUFLEN,file) != NULL) { + name = (el*)malloc(sizeof(el)); + if (name == NULL) { + exit(-1); + } + strcpy(name->bname, linebuf); + CDL_PREPEND(head, name); + } + CDL_SORT(head, namecmp); + CDL_FOREACH(head,tmp) { + printf("%s", tmp->bname); + } + + fclose(file); + + return 0; +} diff --git a/tests/test31.ans b/tests/test31.ans new file mode 100644 index 000000000..2b72e985a --- /dev/null +++ b/tests/test31.ans @@ -0,0 +1,51 @@ +ADRIAN +ARNOLDO +CARROLL +CARY +CHONG +CLIFTON +CODY +COLTON +CORNELL +DAMON +DANNIE +DARIO +DONN +DOUG +DOUGLAS +FREDERICK +FRITZ +GERALD +GUS +HARVEY +IRVING +ISAIAH +JARVIS +JOHN +KENTON +LAURENCE +LESTER +LINCOLN +LOWELL +NELSON +NEVILLE +NIGEL +NORMAND +ODIS +OMAR +ORLANDO +RAYMUNDO +REX +ROLANDO +RON +SHANE +TONEY +TRINIDAD +WALTER +WARNER +WARREN +WES +WILLARD +WILLIAM +WINFRED +XAVIER diff --git a/tests/test31.c b/tests/test31.c new file mode 100644 index 000000000..58bfb7356 --- /dev/null +++ b/tests/test31.c @@ -0,0 +1,50 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "utlist.h" + +#define BUFLEN 20 + +typedef struct el { + char bname[BUFLEN]; + struct el *next, *prev; +} el; + +static int namecmp(void *_a, void *_b) +{ + el *a = (el*)_a; + el *b = (el*)_b; + return strcmp(a->bname,b->bname); +} + +int main() +{ + el *name, *tmp; + el *head = NULL; + + char linebuf[BUFLEN]; + FILE *file; + + file = fopen( "test11.dat", "r" ); + if (file == NULL) { + perror("can't open: "); + exit(-1); + } + + while (fgets(linebuf,BUFLEN,file) != NULL) { + name = (el*)malloc(sizeof(el)); + if (name == NULL) { + exit(-1); + } + strcpy(name->bname, linebuf); + CDL_PREPEND(head, name); + } + CDL_SORT(head, namecmp); + CDL_FOREACH(head,tmp) { + printf("%s", tmp->bname); + } + + fclose(file); + + return 0; +} diff --git a/tests/test32.ans b/tests/test32.ans new file mode 100644 index 000000000..2a4d7f716 --- /dev/null +++ b/tests/test32.ans @@ -0,0 +1,51 @@ +ARNOLDO +COLTON +WES +WARNER +TONEY +NEVILLE +CHONG +KENTON +DARIO +DANNIE +ODIS +TRINIDAD +DONN +FRITZ +NORMAND +NIGEL +CORNELL +LINCOLN +RAYMUNDO +WINFRED +JARVIS +GUS +ISAIAH +XAVIER +CARY +ROLANDO +LAURENCE +CARROLL +IRVING +LOWELL +DAMON +OMAR +REX +ORLANDO +DOUG +WILLARD +CLIFTON +NELSON +CODY +ADRIAN +HARVEY +RON +LESTER +SHANE +WARREN +FREDERICK +GERALD +DOUGLAS +WALTER +WILLIAM +JOHN diff --git a/tests/test32.c b/tests/test32.c new file mode 100644 index 000000000..f861b2ad4 --- /dev/null +++ b/tests/test32.c @@ -0,0 +1,43 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "utlist.h" + +#define BUFLEN 20 + +typedef struct el { + char bname[BUFLEN]; + struct el *next, *prev; +} el; + +int main() +{ + el *name, *tmp; + el *head = NULL; + + char linebuf[BUFLEN]; + FILE *file; + + file = fopen( "test11.dat", "r" ); + if (file == NULL) { + perror("can't open: "); + exit(-1); + } + + while (fgets(linebuf,BUFLEN,file) != NULL) { + name = (el*)malloc(sizeof(el)); + if (name == NULL) { + exit(-1); + } + strcpy(name->bname, linebuf); + DL_PREPEND(head, name); + } + /* DL_SORT(head, namecmp); */ + DL_FOREACH(head,tmp) { + printf("%s", tmp->bname); + } + + fclose(file); + + return 0; +} diff --git a/tests/test33.ans b/tests/test33.ans new file mode 100644 index 000000000..2b72e985a --- /dev/null +++ b/tests/test33.ans @@ -0,0 +1,51 @@ +ADRIAN +ARNOLDO +CARROLL +CARY +CHONG +CLIFTON +CODY +COLTON +CORNELL +DAMON +DANNIE +DARIO +DONN +DOUG +DOUGLAS +FREDERICK +FRITZ +GERALD +GUS +HARVEY +IRVING +ISAIAH +JARVIS +JOHN +KENTON +LAURENCE +LESTER +LINCOLN +LOWELL +NELSON +NEVILLE +NIGEL +NORMAND +ODIS +OMAR +ORLANDO +RAYMUNDO +REX +ROLANDO +RON +SHANE +TONEY +TRINIDAD +WALTER +WARNER +WARREN +WES +WILLARD +WILLIAM +WINFRED +XAVIER diff --git a/tests/test33.c b/tests/test33.c new file mode 100644 index 000000000..54cc31128 --- /dev/null +++ b/tests/test33.c @@ -0,0 +1,50 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "utlist.h" + +#define BUFLEN 20 + +typedef struct el { + char bname[BUFLEN]; + struct el *next, *prev; +} el; + +static int namecmp(void *_a, void *_b) +{ + el *a = (el*)_a; + el *b = (el*)_b; + return strcmp(a->bname,b->bname); +} + +int main() +{ + el *name, *tmp; + el *head = NULL; + + char linebuf[BUFLEN]; + FILE *file; + + file = fopen( "test11.dat", "r" ); + if (file == NULL) { + perror("can't open: "); + exit(-1); + } + + while (fgets(linebuf,BUFLEN,file) != NULL) { + name = (el*)malloc(sizeof(el)); + if (name == NULL) { + exit(-1); + } + strcpy(name->bname, linebuf); + LL_PREPEND(head, name); + } + LL_SORT(head, namecmp); + LL_FOREACH(head,tmp) { + printf("%s", tmp->bname); + } + + fclose(file); + + return 0; +} diff --git a/tests/test34.ans b/tests/test34.ans new file mode 100644 index 000000000..2a4d7f716 --- /dev/null +++ b/tests/test34.ans @@ -0,0 +1,51 @@ +ARNOLDO +COLTON +WES +WARNER +TONEY +NEVILLE +CHONG +KENTON +DARIO +DANNIE +ODIS +TRINIDAD +DONN +FRITZ +NORMAND +NIGEL +CORNELL +LINCOLN +RAYMUNDO +WINFRED +JARVIS +GUS +ISAIAH +XAVIER +CARY +ROLANDO +LAURENCE +CARROLL +IRVING +LOWELL +DAMON +OMAR +REX +ORLANDO +DOUG +WILLARD +CLIFTON +NELSON +CODY +ADRIAN +HARVEY +RON +LESTER +SHANE +WARREN +FREDERICK +GERALD +DOUGLAS +WALTER +WILLIAM +JOHN diff --git a/tests/test34.c b/tests/test34.c new file mode 100644 index 000000000..59377a024 --- /dev/null +++ b/tests/test34.c @@ -0,0 +1,43 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "utlist.h" + +#define BUFLEN 20 + +typedef struct el { + char bname[BUFLEN]; + struct el *next, *prev; +} el; + +int main() +{ + el *name, *tmp; + el *head = NULL; + + char linebuf[BUFLEN]; + FILE *file; + + file = fopen( "test11.dat", "r" ); + if (file == NULL) { + perror("can't open: "); + exit(-1); + } + + while (fgets(linebuf,BUFLEN,file) != NULL) { + name = (el*)malloc(sizeof(el)); + if (name == NULL) { + exit(-1); + } + strcpy(name->bname, linebuf); + CDL_PREPEND(head, name); + } + /* CDL_SORT(head, namecmp); */ + CDL_FOREACH(head,tmp) { + printf("%s", tmp->bname); + } + + fclose(file); + + return 0; +} diff --git a/tests/test35.ans b/tests/test35.ans new file mode 100644 index 000000000..b33c8088c --- /dev/null +++ b/tests/test35.ans @@ -0,0 +1,30 @@ +0: aello +1: bello +2: cello +3: dello +4: eello +5: fello +6: gello +7: hello +8: iello +9: jello +found aello +right address? yes +found bello +right address? yes +found cello +right address? yes +found dello +right address? yes +found eello +right address? yes +found fello +right address? yes +found gello +right address? yes +found hello +right address? yes +found iello +right address? yes +found jello +right address? yes diff --git a/tests/test35.c b/tests/test35.c new file mode 100644 index 000000000..a9c82b9c5 --- /dev/null +++ b/tests/test35.c @@ -0,0 +1,37 @@ +#include "uthash.h" +#include <string.h> /* strcpy */ +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct elt { + char *s; + UT_hash_handle hh; +} elt; + +int main() +{ + int i; + elt *head = NULL; + elt elts[10]; + char label[6] = "hello"; + for(i=0; i<10; i++) { + elts[i].s = (char*)malloc(6UL); + strcpy(elts[i].s, "hello"); + elts[i].s[0] = 'a' + i; + printf("%d: %s\n", i, elts[i].s); + HASH_ADD_KEYPTR(hh, head, elts[i].s, 6UL, &elts[i]); + } + + /* look up each element and verify the result pointer */ + for(i=0; i<10; i++) { + elt *e; + label[0] = 'a' + i; + HASH_FIND(hh,head,label,6UL,e); + if (e != NULL) { + printf( "found %s\n", e->s); + printf( "right address? %s\n", (e == &elts[i]) ? "yes" : "no"); + } + } + + return 0; +} diff --git a/tests/test36.ans b/tests/test36.ans new file mode 100644 index 000000000..4ea987369 --- /dev/null +++ b/tests/test36.ans @@ -0,0 +1,25 @@ +user 0 +user 1 +user 2 +user 3 +user 4 +user 5 +user 6 +user 7 +user 8 +user 9 +user 0, should_find=1, found=1 +user 1, should_find=0, found=0 +user 2, should_find=1, found=1 +user 3, should_find=0, found=0 +user 4, should_find=1, found=1 +user 5, should_find=0, found=0 +user 6, should_find=1, found=1 +user 7, should_find=0, found=0 +user 8, should_find=1, found=1 +user 9, should_find=0, found=0 +auser 0 +auser 2 +auser 4 +auser 6 +auser 8 diff --git a/tests/test36.c b/tests/test36.c new file mode 100644 index 000000000..5927d9419 --- /dev/null +++ b/tests/test36.c @@ -0,0 +1,60 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct { + int id; + UT_hash_handle hh; + UT_hash_handle ah; +} example_user_t; + +#define EVENS(x) (((x)->id % 2) == 0) +static int evens(void *userv) +{ + example_user_t *user = (example_user_t*)userv; + return ((user->id % 2) ? 0 : 1); +} + +static int idcmp(void *_a, void *_b) +{ + example_user_t *a = (example_user_t*)_a; + example_user_t *b = (example_user_t*)_b; + return (a->id - b->id); +} + +int main() +{ + int i; + example_user_t *user, *users=NULL, *ausers=NULL; + + /* create elements */ + for(i=0; i<10; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + HASH_ADD_INT(users,id,user); + } + + for(user=users; user!=NULL; user=(example_user_t*)(user->hh.next)) { + printf("user %d\n", user->id); + } + + /* now select some users into ausers */ + HASH_SELECT(ah,ausers,hh,users,evens); + HASH_SRT(ah,ausers,idcmp); + + for(user=users; user!=NULL; user=(example_user_t*)(user->hh.next)) { + example_user_t *found = NULL; + int should_find = !!evens(user); + HASH_FIND(ah, ausers, &user->id, sizeof(user->id), found); + printf("user %d, should_find=%d, found=%d\n", user->id, should_find, (int)(!!found)); + } + + for(user=ausers; user!=NULL; user=(example_user_t*)(user->ah.next)) { + printf("auser %d\n", user->id); + } + + return 0; +} diff --git a/tests/test37.ans b/tests/test37.ans new file mode 100644 index 000000000..f42a945cb --- /dev/null +++ b/tests/test37.ans @@ -0,0 +1,20 @@ +user 0 +user 1 +user 2 +user 3 +user 4 +user 5 +user 6 +user 7 +user 8 +user 9 +users count: 10 +auser 0 +auser 2 +auser 4 +auser 6 +auser 8 +ausers count: 5 +cleared ausers. +ausers count: 0 +users count: 10 diff --git a/tests/test37.c b/tests/test37.c new file mode 100644 index 000000000..ea5209fd8 --- /dev/null +++ b/tests/test37.c @@ -0,0 +1,56 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct { + int id; + UT_hash_handle hh; + UT_hash_handle ah; +} example_user_t; + +#define EVENS(x) ((((example_user_t*)(x))->id % 2) == 0) + +static int idcmp(void *_a, void *_b) +{ + example_user_t *a = (example_user_t*)_a; + example_user_t *b = (example_user_t*)_b; + return (a->id - b->id); +} + +int main() +{ + int i; + example_user_t *user, *users=NULL, *ausers=NULL; + + /* create elements */ + for(i=0; i<10; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + HASH_ADD_INT(users,id,user); + } + + for(user=users; user!=NULL; user=(example_user_t*)(user->hh.next)) { + printf("user %d\n", user->id); + } + printf("users count: %u\n", HASH_CNT(hh,users)); + + /* now select some users into ausers */ + HASH_SELECT(ah,ausers,hh,users,EVENS); + HASH_SRT(ah,ausers,idcmp); + + for(user=ausers; user!=NULL; user=(example_user_t*)(user->ah.next)) { + printf("auser %d\n", user->id); + } + printf("ausers count: %u\n", HASH_CNT(ah,ausers)); + HASH_CLEAR(ah,ausers); + printf("cleared ausers.\n"); + printf("ausers count: %u\n", HASH_CNT(ah,ausers)); + for(user=ausers; user!=NULL; user=(example_user_t*)(user->ah.next)) { + printf("auser %d\n", user->id); + } + printf("users count: %u\n", HASH_CNT(hh,users)); + return 0; +} diff --git a/tests/test38.ans b/tests/test38.ans new file mode 100644 index 000000000..b20e04bcb --- /dev/null +++ b/tests/test38.ans @@ -0,0 +1 @@ +hash count 10 diff --git a/tests/test38.c b/tests/test38.c new file mode 100644 index 000000000..dc9dae94e --- /dev/null +++ b/tests/test38.c @@ -0,0 +1,31 @@ +#include "uthash.h" +#include <stdlib.h> +#include <stdio.h> + +struct test_t { + int a; + UT_hash_handle hh; +}; + +int main() +{ + struct test_t *tests=NULL, *test; + int a, b; + for (b=0; b < 3; b++) { + for (a=0; a < 10; a++) { + test = NULL; + HASH_FIND(hh, tests, &a, sizeof(a), test); + if (test == NULL) { + test = (struct test_t*)malloc(sizeof(struct test_t)); + if (test == NULL) { + exit(-1); + } + memset(test, 0, sizeof(struct test_t)); + test->a = a; + HASH_ADD(hh, tests, a, sizeof(a), test); + } + } + } + printf("hash count %u\n", HASH_COUNT(tests)); + return 0; +} diff --git a/tests/test39.ans b/tests/test39.ans new file mode 100644 index 000000000..a7e7e6ceb --- /dev/null +++ b/tests/test39.ans @@ -0,0 +1,7 @@ +adding key eins +adding key zwei +adding key drei +hash count is 3 +looking for key eins... found. +looking for key zwei... found. +looking for key drei... found. diff --git a/tests/test39.c b/tests/test39.c new file mode 100644 index 000000000..18a0af8b4 --- /dev/null +++ b/tests/test39.c @@ -0,0 +1,34 @@ +#include <stdio.h> +#include <stdlib.h> +#include "uthash.h" + +typedef struct { + const char *name; + UT_hash_handle hh; +} ns_t; + +int main() +{ + const char *keys[] = {"eins", "zwei", "drei"}; + unsigned i; + ns_t *nsp; + ns_t *head = NULL; + + for(i=0; i < (sizeof(keys)/sizeof(keys[0])); i++) { + printf("adding key %s\n", keys[i]); + nsp = (ns_t*)malloc(sizeof(ns_t)); + if (nsp == NULL) { + exit(-1); + } + nsp->name = keys[i]; + HASH_ADD_KEYPTR(hh,head,nsp->name,strlen(nsp->name),nsp); + } + printf("hash count is %u\n", HASH_COUNT(head)); + + for(i=0; i < (sizeof(keys)/sizeof(keys[0])); i++) { + printf("looking for key %s... ", keys[i]); + HASH_FIND(hh,head,keys[i],strlen(keys[i]),nsp); + printf("%s.\n", (nsp!=NULL)?"found":"not found"); + } + return 0; +} diff --git a/tests/test4.ans b/tests/test4.ans new file mode 100644 index 000000000..19b148f51 --- /dev/null +++ b/tests/test4.ans @@ -0,0 +1,10 @@ +cookie 0, user 0 +cookie 1, user 1 +cookie 4, user 2 +cookie 9, user 3 +cookie 16, user 4 +cookie 25, user 5 +cookie 36, user 6 +cookie 49, user 7 +cookie 64, user 8 +cookie 81, user 9 diff --git a/tests/test4.c b/tests/test4.c new file mode 100644 index 000000000..fe9bcb403 --- /dev/null +++ b/tests/test4.c @@ -0,0 +1,33 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; + UT_hash_handle alth; +} example_user_t; + +int main() +{ + int i; + example_user_t *user, *users=NULL, *altusers=NULL; + + /* create elements */ + for(i=0; i<10; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + HASH_ADD(alth,altusers,cookie,sizeof(int),user); + } + + for(user=altusers; user != NULL; user=(example_user_t*)(user->alth.next)) { + printf("cookie %d, user %d\n", user->cookie, user->id); + } + return 0; +} diff --git a/tests/test40.ans b/tests/test40.ans new file mode 100644 index 000000000..ad69a9470 --- /dev/null +++ b/tests/test40.ans @@ -0,0 +1 @@ +betty's id is 2 diff --git a/tests/test40.c b/tests/test40.c new file mode 100644 index 000000000..af754611c --- /dev/null +++ b/tests/test40.c @@ -0,0 +1,40 @@ +#include <string.h> /* strcpy */ +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ +#include "uthash.h" + +struct my_struct { + const char *name; /* key */ + int id; + UT_hash_handle hh; /* makes this structure hashable */ +}; + + +int main() +{ + const char **n, *names[] = { "joe", "bob", "betty", NULL }; + struct my_struct *s, *tmp, *users = NULL; + int i=0; + + for (n = names; *n != NULL; n++) { + s = (struct my_struct*)malloc(sizeof(struct my_struct)); + if (s == NULL) { + exit(-1); + } + s->name = *n; + s->id = i++; + HASH_ADD_KEYPTR( hh, users, s->name, strlen(s->name), s ); + } + + HASH_FIND_STR( users, "betty", s); + if (s != NULL) { + printf("betty's id is %d\n", s->id); + } + + /* free the hash table contents */ + HASH_ITER(hh, users, s, tmp) { + HASH_DEL(users, s); + free(s); + } + return 0; +} diff --git a/tests/test41.ans b/tests/test41.ans new file mode 100644 index 000000000..f19e34b76 --- /dev/null +++ b/tests/test41.ans @@ -0,0 +1,6 @@ +CDL macros +c b a deleting c deleting b deleting a +DL macros +a b c deleting a deleting b deleting c +LL macros +a b c deleting a deleting b deleting c diff --git a/tests/test41.c b/tests/test41.c new file mode 100644 index 000000000..88a1a96eb --- /dev/null +++ b/tests/test41.c @@ -0,0 +1,72 @@ +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *next, *prev; +} el; + +int main() +{ + int i; + el *head = NULL; + el els[10], *e, *tmp, *tmp2; + for(i=0; i<10; i++) { + els[i].id=(int)'a'+i; + } + + /* test CDL macros */ + printf("CDL macros\n"); + CDL_PREPEND(head,&els[0]); + CDL_PREPEND(head,&els[1]); + CDL_PREPEND(head,&els[2]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + + /* point head to head->next */ + CDL_FOREACH_SAFE(head,e,tmp,tmp2) { + printf("deleting %c ", e->id); + CDL_DELETE(head,e); + } + printf("\n"); + if (head != NULL) { + printf("non-null head\n"); + } + + /* test DL macros */ + printf("DL macros\n"); + DL_APPEND(head,&els[0]); + DL_APPEND(head,&els[1]); + DL_APPEND(head,&els[2]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + DL_FOREACH_SAFE(head,e,tmp) { + printf("deleting %c ", e->id); + DL_DELETE(head,e); + } + printf("\n"); + if (head != NULL) { + printf("non-null head\n"); + } + + /* test LL macros */ + printf("LL macros\n"); + LL_APPEND(head,&els[0]); + LL_APPEND(head,&els[1]); + LL_APPEND(head,&els[2]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + LL_FOREACH_SAFE(head,e,tmp) { + printf("deleting %c ", e->id); + LL_DELETE(head,e); + } + printf("\n"); + if (head != NULL) { + printf("non-null head\n"); + } + + return 0; +} diff --git a/tests/test42.ans b/tests/test42.ans new file mode 100644 index 000000000..581660e3f --- /dev/null +++ b/tests/test42.ans @@ -0,0 +1,14 @@ +LL macros +a b c +search scalar found b +search found a + +DL macros +a b c +search scalar found b +search found a + +CDL macros +c b a +search scalar found b +search found a diff --git a/tests/test42.c b/tests/test42.c new file mode 100644 index 000000000..4da8f03dd --- /dev/null +++ b/tests/test42.c @@ -0,0 +1,90 @@ +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *next, *prev; +} el; + +static int eltcmp(el *a, el *b) +{ + return a->id - b->id; +} + +int main() +{ + int i; + el *head = NULL; + el els[10], *e, *tmp, *tmp2; + for(i=0; i<10; i++) { + els[i].id=(int)'a'+i; + } + + /* test LL macros */ + printf("LL macros\n"); + LL_APPEND(head,&els[0]); + LL_APPEND(head,&els[1]); + LL_APPEND(head,&els[2]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + LL_SEARCH_SCALAR(head, e, id, 'b'); + if (e != NULL) { + printf("search scalar found b\n"); + } + LL_SEARCH(head, e, &els[0], eltcmp); + if (e != NULL) { + printf("search found %c\n",e->id); + } + LL_FOREACH_SAFE(head,e,tmp) { + LL_DELETE(head,e); + } + + printf("\n"); + + /* test DL macros */ + printf("DL macros\n"); + DL_APPEND(head,&els[0]); + DL_APPEND(head,&els[1]); + DL_APPEND(head,&els[2]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + DL_SEARCH_SCALAR(head, e, id, 'b'); + if (e != NULL) { + printf("search scalar found b\n"); + } + DL_SEARCH(head, e, &els[0], eltcmp); + if (e != NULL) { + printf("search found %c\n",e->id); + } + DL_FOREACH_SAFE(head,e,tmp) { + DL_DELETE(head,e); + } + printf("\n"); + + /* test CDL macros */ + printf("CDL macros\n"); + CDL_PREPEND(head,&els[0]); + CDL_PREPEND(head,&els[1]); + CDL_PREPEND(head,&els[2]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + CDL_SEARCH_SCALAR(head, e, id, 'b'); + if (e != NULL) { + printf("search scalar found b\n"); + } + CDL_SEARCH(head, e, &els[0], eltcmp); + if (e != NULL) { + printf("search found %c\n",e->id); + } + CDL_FOREACH_SAFE(head,e,tmp,tmp2) { + CDL_DELETE(head,e); + } + + return 0; +} diff --git a/tests/test43.ans b/tests/test43.ans new file mode 100644 index 000000000..d09e9bd4e --- /dev/null +++ b/tests/test43.ans @@ -0,0 +1,88 @@ +length is 0 +push +length is 1 +back is 1 2 +pop +length is 0 +push +push +length is 2 +1 2 +3 4 +erase [0] +length is 1 +3 4 +push +3 4 +1 2 +clear +length is 0 +extend +length is 1 +ip points to [0] ? yes +push +0 0 +1 2 +erase [1] +length is 1 +0 0 +push +0 0 +3 4 +back is 3 4 +copy +cpy length is 2 +cpy 0 0 +cpy 3 4 +insert cpy[0] +cpy length is 3 +cpy 5 6 +cpy 0 0 +cpy 3 4 +erase cpy [0] [1] +cpy length is 1 +cpy 3 4 +inserta at cpy[1] +cpy length is 3 +cpy 3 4 +cpy 0 0 +cpy 3 4 +free cpy +length is 2 +resize to 30 +length is 30 +0 0 +3 4 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +0 0 +resize to 1 +length is 1 +resize to 0 +length is 0 +free diff --git a/tests/test43.c b/tests/test43.c new file mode 100644 index 000000000..216f529aa --- /dev/null +++ b/tests/test43.c @@ -0,0 +1,130 @@ +#include <stdio.h> +#include "utarray.h" + +typedef struct { + int a; + int b; +} intpair_t; + +int main() +{ + UT_array *pairs, *pairs_cpy; + intpair_t it, *ip; + UT_icd pairicd = { sizeof(intpair_t),NULL,NULL,NULL}; + size_t zero=0; + utarray_new(pairs, &pairicd); + printf("length is %u\n", utarray_len(pairs)); + it.a = 1; + it.b=2; + utarray_push_back(pairs, &it); + printf("push\n"); + printf("length is %u\n", utarray_len(pairs)); + ip = (intpair_t*)utarray_back(pairs); + printf("back is %d %d\n", ip->a, ip->b); + utarray_pop_back(pairs); + printf("pop\n"); + printf("length is %u\n", utarray_len(pairs)); + it.a = 1; + it.b=2; + utarray_push_back(pairs, &it); + printf("push\n"); + it.a = 3; + it.b=4; + utarray_push_back(pairs, &it); + printf("push\n"); + printf("length is %u\n", utarray_len(pairs)); + ip=NULL; + while( (ip=(intpair_t*)utarray_next(pairs,ip)) != NULL ) { + printf("%d %d\n", ip->a, ip->b); + } + utarray_erase(pairs,0,1); + printf("erase [0]\n"); + printf("length is %u\n", utarray_len(pairs)); + while( (ip=(intpair_t*)utarray_next(pairs,ip)) != NULL ) { + printf("%d %d\n", ip->a, ip->b); + } + it.a = 1; + it.b=2; + utarray_push_back(pairs, &it); + printf("push\n"); + while( (ip=(intpair_t*)utarray_next(pairs,ip)) != NULL ) { + printf("%d %d\n", ip->a, ip->b); + } + utarray_clear(pairs); + printf("clear\n"); + printf("length is %u\n", utarray_len(pairs)); + utarray_extend_back(pairs); + printf("extend\n"); + ip = (intpair_t*)utarray_back(pairs); + printf("length is %u\n", utarray_len(pairs)); + printf("ip points to [0] ? %s\n", (ip==(intpair_t*)utarray_front(pairs)) ? "yes" : "no"); + it.a = 1; + it.b=2; + utarray_push_back(pairs, &it); + printf("push\n"); + ip=NULL; + while( (ip=(intpair_t*)utarray_next(pairs,ip)) != NULL ) { + printf("%d %d\n", ip->a, ip->b); + } + utarray_erase(pairs,1,1); + printf("erase [1]\n"); + printf("length is %u\n", utarray_len(pairs)); + while( (ip=(intpair_t*)utarray_next(pairs,ip)) != NULL ) { + printf("%d %d\n", ip->a, ip->b); + } + it.a = 3; + it.b=4; + utarray_push_back(pairs, &it); + printf("push\n"); + for(ip=(intpair_t*)utarray_front(pairs); ip!=NULL; ip=(intpair_t*)utarray_next(pairs,ip)) { + printf("%d %d\n", ip->a,ip->b); + } + ip = (intpair_t*)utarray_back(pairs); + printf("back is %d %d\n", ip->a, ip->b); + utarray_new(pairs_cpy, &pairicd); + utarray_concat(pairs_cpy, pairs); + printf("copy\n"); + printf("cpy length is %u\n", utarray_len(pairs_cpy)); + ip=NULL; + while( (ip=(intpair_t*)utarray_next(pairs_cpy,ip)) != NULL ) { + printf("cpy %d %d\n", ip->a, ip->b); + } + it.a=5; + it.b=6; + utarray_insert(pairs_cpy, &it, 0); + printf("insert cpy[0]\n"); + printf("cpy length is %u\n", utarray_len(pairs_cpy)); + while( (ip=(intpair_t*)utarray_next(pairs_cpy,ip)) != NULL ) { + printf("cpy %d %d\n", ip->a, ip->b); + } + utarray_erase(pairs_cpy,0,2); + printf("erase cpy [0] [1]\n"); + printf("cpy length is %u\n", utarray_len(pairs_cpy)); + while( (ip=(intpair_t*)utarray_next(pairs_cpy,ip)) != NULL ) { + printf("cpy %d %d\n", ip->a, ip->b); + } + utarray_inserta(pairs_cpy, pairs, 1); + printf("inserta at cpy[1]\n"); + printf("cpy length is %u\n", utarray_len(pairs_cpy)); + while( (ip=(intpair_t*)utarray_next(pairs_cpy,ip)) != NULL ) { + printf("cpy %d %d\n", ip->a, ip->b); + } + utarray_free(pairs_cpy); + printf("free cpy\n"); + printf("length is %u\n", utarray_len(pairs)); + utarray_resize(pairs, 30); + printf("resize to 30\n"); + printf("length is %u\n", utarray_len(pairs)); + while( (ip=(intpair_t*)utarray_next(pairs,ip)) != NULL ) { + printf("%d %d\n", ip->a, ip->b); + } + utarray_resize(pairs, 1); + printf("resize to 1\n"); + printf("length is %u\n", utarray_len(pairs)); + utarray_resize(pairs, zero); + printf("resize to 0\n"); + printf("length is %u\n", utarray_len(pairs)); + utarray_free(pairs); + printf("free\n"); + return 0; +} diff --git a/tests/test44.ans b/tests/test44.ans new file mode 100644 index 000000000..f771df887 --- /dev/null +++ b/tests/test44.ans @@ -0,0 +1,9 @@ +0 1 2 3 4 5 6 7 8 9 +9 8 7 6 5 4 3 2 1 0 +9 8 7 3 2 1 0 +9 3 2 1 0 +3 2 1 0 +3 2 1 +3 2 1 0 0 +3 2 1 + diff --git a/tests/test44.c b/tests/test44.c new file mode 100644 index 000000000..042fc4c50 --- /dev/null +++ b/tests/test44.c @@ -0,0 +1,66 @@ +#include <stdio.h> +#include "utarray.h" + +static int reverse(const void *a, const void *b) +{ + int _a = *(const int*)a; + int _b = *(const int*)b; + return _b - _a; +} + +int main() +{ + UT_array *a; + int i, *p; + utarray_new(a, &ut_int_icd); + for(i=0; i<10; i++) { + utarray_push_back(a,&i); + } + for(p=(int*)utarray_front(a); p!=NULL; p=(int*)utarray_next(a,p)) { + printf("%d ",*p); + } + printf("\n"); + utarray_sort(a,reverse); + while ( (p=(int*)utarray_next(a,p)) != NULL ) { + printf("%d ", *p); + } + printf("\n"); + utarray_erase(a,3,3); + while ( (p=(int*)utarray_next(a,p)) != NULL ) { + printf("%d ", *p); + } + printf("\n"); + utarray_erase(a,1,2); + while ( (p=(int*)utarray_next(a,p)) != NULL ) { + printf("%d ", *p); + } + printf("\n"); + utarray_erase(a,0,1); + while ( (p=(int*)utarray_next(a,p)) != NULL ) { + printf("%d ", *p); + } + printf("\n"); + utarray_erase(a,3,1); + while ( (p=(int*)utarray_next(a,p)) != NULL ) { + printf("%d ", *p); + } + printf("\n"); + utarray_resize(a,5); + while ( (p=(int*)utarray_next(a,p)) != NULL ) { + printf("%d ", *p); + } + printf("\n"); + utarray_resize(a,3); + while ( (p=(int*)utarray_next(a,p)) != NULL ) { + printf("%d ", *p); + } + printf("\n"); + utarray_erase(a,0,3); + while ( (p=(int*)utarray_next(a,p)) != NULL ) { + printf("%d ", *p); + } + printf("\n"); + utarray_free(a); + return 0; +} + diff --git a/tests/test45.ans b/tests/test45.ans new file mode 100644 index 000000000..7e744bc38 --- /dev/null +++ b/tests/test45.ans @@ -0,0 +1,3 @@ +1 2 3 4 5 6 7 8 +1 2 3 100 4 5 6 7 8 +1 2 3 100 4 5 6 7 8 1000 diff --git a/tests/test45.c b/tests/test45.c new file mode 100644 index 000000000..b0633f2b4 --- /dev/null +++ b/tests/test45.c @@ -0,0 +1,36 @@ +#include <stdio.h> +#include "utarray.h" + +int main() +{ + UT_array *a; + int i, *p=NULL; + utarray_new(a, &ut_int_icd); + for(i=0; i<10; i++) { + utarray_push_back(a,&i); + } + utarray_pop_back(a); + utarray_erase(a,0,1); + while ( (p=(int*)utarray_next(a,p)) != NULL ) { + printf("%d ",*p); + } + printf("\n"); + i = 100; + utarray_insert(a,&i,3); + while ( (p=(int*)utarray_next(a,p)) != NULL ) { + printf("%d ",*p); + } + printf("\n"); + utarray_extend_back(a); + p = (int*)utarray_back(a); + *p = 1000; + p = NULL; + while ( (p=(int*)utarray_next(a,p)) != NULL ) { + printf("%d ",*p); + } + printf("\n"); + utarray_clear(a); + utarray_free(a); + return 0; +} + diff --git a/tests/test46.ans b/tests/test46.ans new file mode 100644 index 000000000..be625f352 --- /dev/null +++ b/tests/test46.ans @@ -0,0 +1,11 @@ +hello world +begin hello world +alt begin hello world oth +hello world oth +hello world +hello world begin hello world +begin hello world +sorting strs2 +begin hello world +reverse sorting strs2 +world hello begin diff --git a/tests/test46.c b/tests/test46.c new file mode 100644 index 000000000..b3ac63762 --- /dev/null +++ b/tests/test46.c @@ -0,0 +1,84 @@ +#include <stdio.h> +#include "utarray.h" + +static int strsort(const void *_a, const void *_b) +{ + const char *a = *(const char* const *)_a; + const char *b = *(const char* const *)_b; + return strcmp(a,b); +} + +static int revsort(const void *_a, const void *_b) +{ + const char *a = *(const char* const *)_a; + const char *b = *(const char* const *)_b; + return strcmp(b,a); +} + +int main() +{ + UT_array *strs,*strs2; + char *s, **p=NULL; + utarray_new(strs, &ut_str_icd); + s=(char*)"hello"; + utarray_push_back(strs, &s); + s=(char*)"world"; + utarray_push_back(strs, &s); + while ( (p=(char**)utarray_next(strs,p)) != NULL ) { + printf("%s ",*p); + } + printf("\n"); + s=(char*)"begin"; + utarray_insert(strs,&s,0); + while ( (p=(char**)utarray_next(strs,p)) != NULL ) { + printf("%s ",*p); + } + printf("\n"); + utarray_new(strs2, &ut_str_icd); + s=(char*)"alt"; + utarray_push_back(strs2, &s); + s=(char*)"oth"; + utarray_push_back(strs2, &s); + utarray_inserta(strs2, strs, 1); + while ( (p=(char**)utarray_next(strs2,p)) != NULL ) { + printf("%s ",*p); + } + printf("\n"); + utarray_erase(strs2,0,2); + while ( (p=(char**)utarray_next(strs2,p)) != NULL ) { + printf("%s ",*p); + } + printf("\n"); + utarray_pop_back(strs2); + while ( (p=(char**)utarray_next(strs2,p)) != NULL ) { + printf("%s ",*p); + } + printf("\n"); + utarray_concat(strs2, strs); + while ( (p=(char**)utarray_next(strs2,p)) != NULL ) { + printf("%s ",*p); + } + printf("\n"); + utarray_clear(strs2); + utarray_concat(strs2, strs); + while ( (p=(char**)utarray_next(strs2,p)) != NULL ) { + printf("%s ",*p); + } + printf("\n"); + printf("sorting strs2\n"); + utarray_sort(strs2,strsort); + while ( (p=(char**)utarray_next(strs2,p)) != NULL ) { + printf("%s ",*p); + } + printf("\n"); + printf("reverse sorting strs2\n"); + utarray_sort(strs2,revsort); + while ( (p=(char**)utarray_next(strs2,p)) != NULL ) { + printf("%s ",*p); + } + printf("\n"); + utarray_clear(strs2); + utarray_free(strs2); + utarray_free(strs); + return 0; +} diff --git a/tests/test47.ans b/tests/test47.ans new file mode 100644 index 000000000..546e06442 --- /dev/null +++ b/tests/test47.ans @@ -0,0 +1,8 @@ +hello world +hello world text + second +hello world text second +cleared, length t now: 0 +length s now: 23 +one 1 two 2 three (3) +length t now: 21 diff --git a/tests/test47.c b/tests/test47.c new file mode 100644 index 000000000..620c46e9f --- /dev/null +++ b/tests/test47.c @@ -0,0 +1,29 @@ +#include <stdio.h> /* printf */ +#include "utstring.h" + +int main() +{ + UT_string *s,*t; + char a[] = " text"; + utstring_new(s); + utstring_new(t); + + utstring_printf(s,"hello %s", "world"); + printf("%s\n", utstring_body(s)); + utstring_bincpy(s,a,sizeof(a)-1); + printf("%s\n", utstring_body(s)); + utstring_printf(t," second"); + printf("%s\n", utstring_body(t)); + utstring_concat(s,t); + printf("%s\n", utstring_body(s)); + utstring_clear(t); + printf("cleared, length t now: %u\n", (unsigned)utstring_len(t)); + printf("length s now: %u\n", (unsigned)utstring_len(s)); + utstring_printf(t,"one %d two %u three %s", 1, 2, "(3)"); + printf("%s\n", utstring_body(t)); + printf("length t now: %u\n", (unsigned)utstring_len(t)); + + utstring_free(t); + utstring_free(s); + return 0; +} diff --git a/tests/test48.ans b/tests/test48.ans new file mode 100644 index 000000000..8b1acc12b --- /dev/null +++ b/tests/test48.ans @@ -0,0 +1,10 @@ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 diff --git a/tests/test48.c b/tests/test48.c new file mode 100644 index 000000000..9e634c83e --- /dev/null +++ b/tests/test48.c @@ -0,0 +1,23 @@ +#include <stdio.h> +#include "utarray.h" + +int main() +{ + UT_array *nums; + int i, *p; + + utarray_new(nums,&ut_int_icd); + for(i=0; i < 10; i++) { + utarray_push_back(nums,&i); + } + + for(p=(int*)utarray_front(nums); + p!=NULL; + p=(int*)utarray_next(nums,p)) { + printf("%d\n",*p); + } + + utarray_free(nums); + + return 0; +} diff --git a/tests/test49.ans b/tests/test49.ans new file mode 100644 index 000000000..94954abda --- /dev/null +++ b/tests/test49.ans @@ -0,0 +1,2 @@ +hello +world diff --git a/tests/test49.c b/tests/test49.c new file mode 100644 index 000000000..972f01376 --- /dev/null +++ b/tests/test49.c @@ -0,0 +1,23 @@ +#include <stdio.h> +#include "utarray.h" + +int main() +{ + UT_array *strs; + const char *s, **p; + + utarray_new(strs,&ut_str_icd); + + s = "hello"; + utarray_push_back(strs, &s); + s = "world"; + utarray_push_back(strs, &s); + p = NULL; + while ( (p=(const char**)utarray_next(strs,p)) != NULL ) { + printf("%s\n",*p); + } + + utarray_free(strs); + + return 0; +} diff --git a/tests/test5.ans b/tests/test5.ans new file mode 100644 index 000000000..2ece88fe5 --- /dev/null +++ b/tests/test5.ans @@ -0,0 +1,5 @@ +cookie 0 found, user id 0 +cookie 4 found, user id 2 +cookie 16 found, user id 4 +cookie 36 found, user id 6 +cookie 64 found, user id 8 diff --git a/tests/test5.c b/tests/test5.c new file mode 100644 index 000000000..95acdc5ec --- /dev/null +++ b/tests/test5.c @@ -0,0 +1,40 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; + UT_hash_handle alth; +} example_user_t; + +int main() +{ + int i,j; + example_user_t *user, *tmp, *users=NULL, *altusers=NULL; + + /* create elements */ + for(i=0; i<10; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + HASH_ADD(alth,altusers,cookie,sizeof(int),user); + } + + /* find cookie corresponding to each even ID */ + for(i=0; i<10; i+=2) { + j=i*i; + HASH_FIND(alth,altusers,&j,sizeof(int),tmp); + if (tmp != NULL) { + printf("cookie %d found, user id %d\n", tmp->cookie, tmp->id); + } else { + printf("cookie %d not found\n", j); + } + } + return 0; +} diff --git a/tests/test50.ans b/tests/test50.ans new file mode 100644 index 000000000..1191247b6 --- /dev/null +++ b/tests/test50.ans @@ -0,0 +1,2 @@ +1 +2 diff --git a/tests/test50.c b/tests/test50.c new file mode 100644 index 000000000..82e6be59d --- /dev/null +++ b/tests/test50.c @@ -0,0 +1,23 @@ +#include <stdio.h> +#include "utarray.h" + +int main() +{ + UT_array *nums; + long l, *p; + UT_icd long_icd = {sizeof(long), NULL, NULL, NULL }; + utarray_new(nums, &long_icd); + + l=1; + utarray_push_back(nums, &l); + l=2; + utarray_push_back(nums, &l); + + p=NULL; + while( (p=(long*)utarray_next(nums,p)) != NULL ) { + printf("%ld\n", *p); + } + + utarray_free(nums); + return 0; +} diff --git a/tests/test51.ans b/tests/test51.ans new file mode 100644 index 000000000..3caf26976 --- /dev/null +++ b/tests/test51.ans @@ -0,0 +1,2 @@ +1 2 +10 20 diff --git a/tests/test51.c b/tests/test51.c new file mode 100644 index 000000000..92e7889fd --- /dev/null +++ b/tests/test51.c @@ -0,0 +1,32 @@ +#include <stdio.h> +#include "utarray.h" + +typedef struct { + int a; + int b; +} intpair_t; + +int main() +{ + + UT_array *pairs; + intpair_t ip, *p; + UT_icd intpair_icd = {sizeof(intpair_t), NULL, NULL, NULL}; + utarray_new(pairs,&intpair_icd); + + ip.a=1; + ip.b=2; + utarray_push_back(pairs, &ip); + ip.a=10; + ip.b=20; + utarray_push_back(pairs, &ip); + + for(p=(intpair_t*)utarray_front(pairs); + p!=NULL; + p=(intpair_t*)utarray_next(pairs,p)) { + printf("%d %d\n", p->a, p->b); + } + + utarray_free(pairs); + return 0; +} diff --git a/tests/test52.ans b/tests/test52.ans new file mode 100644 index 000000000..bd3740718 --- /dev/null +++ b/tests/test52.ans @@ -0,0 +1,2 @@ +1 hello +2 world diff --git a/tests/test52.c b/tests/test52.c new file mode 100644 index 000000000..3de12e40a --- /dev/null +++ b/tests/test52.c @@ -0,0 +1,48 @@ +#include <stdio.h> +#include <stdlib.h> +#include "utarray.h" + +typedef struct { + int a; + char *s; +} intchar_t; + +static void intchar_copy(void *_dst, const void *_src) +{ + intchar_t *dst = (intchar_t*)_dst; + const intchar_t *src = (const intchar_t*)_src; + dst->a = src->a; + dst->s = (src->s != NULL) ? strdup(src->s) : NULL; +} + +static void intchar_dtor(void *_elt) +{ + intchar_t *elt = (intchar_t*)_elt; + if (elt->s != NULL) { + free(elt->s); + } +} + +int main() +{ + UT_array *intchars; + intchar_t ic, *p; + UT_icd intchar_icd = {sizeof(intchar_t), NULL, intchar_copy, intchar_dtor}; + utarray_new(intchars, &intchar_icd); + + ic.a=1; + ic.s=(char*)"hello"; + utarray_push_back(intchars, &ic); + ic.a=2; + ic.s=(char*)"world"; + utarray_push_back(intchars, &ic); + + p=NULL; + while( (p=(intchar_t*)utarray_next(intchars,p)) != NULL ) { + printf("%d %s\n", p->a, (p->s != NULL) ? p->s : "null"); + } + + utarray_free(intchars); + return 0; +} + diff --git a/tests/test53.ans b/tests/test53.ans new file mode 100644 index 000000000..a04238969 --- /dev/null +++ b/tests/test53.ans @@ -0,0 +1 @@ +hello world! diff --git a/tests/test53.c b/tests/test53.c new file mode 100644 index 000000000..b30ee561a --- /dev/null +++ b/tests/test53.c @@ -0,0 +1,14 @@ +#include <stdio.h> +#include "utstring.h" + +int main() +{ + UT_string *s; + + utstring_new(s); + utstring_printf(s, "hello world!" ); + printf("%s\n", utstring_body(s)); + + utstring_free(s); + return 0; +} diff --git a/tests/test54.ans b/tests/test54.ans new file mode 100644 index 000000000..df0083e39 --- /dev/null +++ b/tests/test54.ans @@ -0,0 +1,2 @@ +length: 21 +hello world hi there diff --git a/tests/test54.c b/tests/test54.c new file mode 100644 index 000000000..5faaa9e92 --- /dev/null +++ b/tests/test54.c @@ -0,0 +1,24 @@ +#include <stdio.h> +#include "utstring.h" + +int main() +{ + UT_string *s, *t; + + utstring_new(s); + utstring_new(t); + + utstring_printf(s, "hello " ); + utstring_printf(s, "world " ); + + utstring_printf(t, "hi " ); + utstring_printf(t, "there " ); + + utstring_concat(s, t); + printf("length: %u\n", (unsigned)utstring_len(s)); + printf("%s\n", utstring_body(s)); + + utstring_free(s); + utstring_free(t); + return 0; +} diff --git a/tests/test55.ans b/tests/test55.ans new file mode 100644 index 000000000..a75e7be25 --- /dev/null +++ b/tests/test55.ans @@ -0,0 +1,2 @@ +length is 3 +number 10 diff --git a/tests/test55.c b/tests/test55.c new file mode 100644 index 000000000..95d8c01b6 --- /dev/null +++ b/tests/test55.c @@ -0,0 +1,19 @@ +#include <stdio.h> +#include "utstring.h" + +int main() +{ + UT_string *s; + char binary[] = "\xff\xff"; + + utstring_new(s); + utstring_bincpy(s, binary, sizeof(binary)); + printf("length is %u\n", (unsigned)utstring_len(s)); + + utstring_clear(s); + utstring_printf(s,"number %d", 10); + printf("%s\n", utstring_body(s)); + + utstring_free(s); + return 0; +} diff --git a/tests/test56.ans b/tests/test56.ans new file mode 100644 index 000000000..f615d0072 --- /dev/null +++ b/tests/test56.ans @@ -0,0 +1,65 @@ +ADRIAN +ARNOLDO +CARROLL +CARY +CHONG +CLIFTON +CODY +COLTON +CORNELL +DAMON +DANNIE +DARIO +DONN +DOUG +DOUGLAS +FREDERICK +FRITZ +GERALD +GUS +HARVEY +IRVING +ISAIAH +JARVIS +JOHN +KENTON +LAURENCE +LESTER +LINCOLN +LOWELL +NELSON +NEVILLE +NIGEL +NORMAND +ODIS +OMAR +ORLANDO +RAYMUNDO +REX +ROLANDO +RON +SHANE +TONEY +TRINIDAD +WALTER +WARNER +WARREN +WES +WILLARD +WILLIAM +WINFRED +XAVIER +found WES + +user 0, cookie 0 +user 1, cookie 1 +user 2, cookie 4 +user 3, cookie 9 +user 4, cookie 16 +user 5, cookie 25 +user 6, cookie 36 +user 7, cookie 49 +user 8, cookie 64 +user 9, cookie 81 +length is 3 +number 10 diff --git a/tests/test56.c b/tests/test56.c new file mode 100644 index 000000000..e4a0dce16 --- /dev/null +++ b/tests/test56.c @@ -0,0 +1,98 @@ +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ +#include <string.h> +#include "uthash.h" +#include "utlist.h" +#include "utstring.h" + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +#define BUFLEN 20 + +typedef struct el { + char bname[BUFLEN]; + struct el *next, *prev; +} el; + +static int namecmp(void *_a, void *_b) +{ + el *a = (el*)_a; + el *b = (el*)_b; + return strcmp(a->bname,b->bname); +} + +int main() +{ + el *name, *elt, *tmp, etmp; + int i; + example_user_t *user, *users=NULL; + el *head = NULL; /* important- initialize to NULL! */ + + char linebuf[BUFLEN]; + FILE *file; + + UT_string *s; + char binary[] = "\xff\xff"; + + file = fopen( "test11.dat", "r" ); + if (file == NULL) { + perror("can't open: "); + exit(-1); + } + + while (fgets(linebuf,BUFLEN,file) != NULL) { + name = (el*)malloc(sizeof(el)); + if (name == NULL) { + exit(-1); + } + strcpy(name->bname, linebuf); + DL_APPEND(head, name); + } + DL_SORT(head, namecmp); + DL_FOREACH(head,elt) { + printf("%s", elt->bname); + } + + memcpy(etmp.bname, "WES\n", 5UL); + DL_SEARCH(head,elt,&etmp,namecmp); + if (elt != NULL) { + printf("found %s\n", elt->bname); + } + + /* now delete each element, use the safe iterator */ + DL_FOREACH_SAFE(head,elt,tmp) { + DL_DELETE(head,elt); + } + + fclose(file); + + /* create elements */ + for(i=0; i<10; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + + for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { + printf("user %d, cookie %d\n", user->id, user->cookie); + } + + utstring_new(s); + utstring_bincpy(s, binary, sizeof(binary)); + printf("length is %u\n", (unsigned)utstring_len(s)); + + utstring_clear(s); + utstring_printf(s,"number %d", 10); + printf("%s\n", utstring_body(s)); + + utstring_free(s); + return 0; +} diff --git a/tests/test57.ans b/tests/test57.ans new file mode 100644 index 000000000..4d3bb1d0b --- /dev/null +++ b/tests/test57.ans @@ -0,0 +1 @@ +found diff --git a/tests/test57.c b/tests/test57.c new file mode 100644 index 000000000..3b89fb52d --- /dev/null +++ b/tests/test57.c @@ -0,0 +1,32 @@ +#include <stdio.h> +#include <stdlib.h> +#include "uthash.h" + +typedef struct { + void *key; + int i; + UT_hash_handle hh; +} el_t; + +int main() +{ + el_t *d; + el_t *hash = NULL; + char *someaddr = NULL; + el_t *e = (el_t*)malloc(sizeof(el_t)); + if (!e) { + return -1; + } + e->key = (void*)someaddr; + e->i = 1; + HASH_ADD_PTR(hash,key,e); + HASH_FIND_PTR(hash, &someaddr, d); + if (d != NULL) { + printf("found\n"); + } + + /* release memory */ + HASH_DEL(hash,e); + free(e); + return 0; +} diff --git a/tests/test58.ans b/tests/test58.ans new file mode 100644 index 000000000..a23ca72bc --- /dev/null +++ b/tests/test58.ans @@ -0,0 +1,18 @@ +user 0, cookie 0 +user 1, cookie 1 +user 2, cookie 4 +user 3, cookie 9 +user 4, cookie 16 +user 5, cookie 25 +user 6, cookie 36 +user 7, cookie 49 +user 8, cookie 64 +user 9, cookie 81 +10 users. Deleting odd id's... +user 0, cookie 0 +user 2, cookie 4 +user 4, cookie 16 +user 6, cookie 36 +user 8, cookie 64 +5 users. Deleting remaining id's... +0 users. diff --git a/tests/test58.c b/tests/test58.c new file mode 100644 index 000000000..8f5683c71 --- /dev/null +++ b/tests/test58.c @@ -0,0 +1,60 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +int main() +{ + int i; + unsigned c; + example_user_t *user, *tmp, *users=NULL; + + /* create elements */ + for(i=0; i<10; i++) { + if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + /* show the hash */ + for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { + printf("user %d, cookie %d\n", user->id, user->cookie); + } + + + c = HASH_COUNT(users); + printf("%u users. Deleting odd id's...\n", c); + /* delete the odd id's */ + HASH_ITER(hh, users, user, tmp) { + if ((user->id & 1) != 0) { + HASH_DEL(users,user); + } + } + + /* show the hash */ + for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { + printf("user %d, cookie %d\n", user->id, user->cookie); + } + + c = HASH_COUNT(users); + printf("%u users. Deleting remaining id's...\n", c); + /* delete all that are left */ + HASH_ITER(hh, users, user, tmp) { + HASH_DEL(users,user); + } + + c = HASH_COUNT(users); + printf("%u users.\n", c); + /* show the hash */ + for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { + printf("user %d, cookie %d\n", user->id, user->cookie); + } + return 0; +} diff --git a/tests/test59.ans b/tests/test59.ans new file mode 100644 index 000000000..e19f2f6cd --- /dev/null +++ b/tests/test59.ans @@ -0,0 +1 @@ +$items{bob}{age} = 37 diff --git a/tests/test59.c b/tests/test59.c new file mode 100644 index 000000000..f353ae164 --- /dev/null +++ b/tests/test59.c @@ -0,0 +1,57 @@ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "uthash.h" + +/* hash of hashes */ +typedef struct item { + char name[10]; + struct item *sub; + int val; + UT_hash_handle hh; +} item_t; + +int main() +{ + item_t *item1, *item2, *tmp1, *tmp2; + item_t *items=NULL; + + /* make initial element */ + item_t *i = (item_t *)malloc(sizeof(*i)); + if (i == NULL) { + exit(-1); + } + strcpy(i->name, "bob"); + i->sub = NULL; + i->val = 0; + HASH_ADD_STR(items, name, i); + + /* add a sub hash table off this element */ + item_t *s = (item_t *)malloc(sizeof(*s)); + if (s == NULL) { + exit(-1); + } + strcpy(s->name, "age"); + s->sub = NULL; + s->val = 37; + HASH_ADD_STR(i->sub, name, s); + + /* iterate over hash elements */ + HASH_ITER(hh, items, item1, tmp1) { + HASH_ITER(hh, item1->sub, item2, tmp2) { + printf("$items{%s}{%s} = %d\n", item1->name, item2->name, item2->val); + } + } + + /* clean up both hash tables */ + HASH_ITER(hh, items, item1, tmp1) { + HASH_ITER(hh, item1->sub, item2, tmp2) { + HASH_DEL(item1->sub, item2); + free(item2); + } + HASH_DEL(items, item1); + free(item1); + } + + return 0; +} diff --git a/tests/test6.ans b/tests/test6.ans new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/test6.ans diff --git a/tests/test6.c b/tests/test6.c new file mode 100644 index 000000000..55ce36bfb --- /dev/null +++ b/tests/test6.c @@ -0,0 +1,121 @@ +#include "uthash.h" +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* Set up macros for alternative malloc/free functions */ +#undef uthash_malloc +#undef uthash_free +#undef uthash_memcmp +#undef uthash_strlen +#undef uthash_bzero +#define uthash_malloc(sz) alt_malloc(sz) +#define uthash_free(ptr,sz) alt_free(ptr,sz) +#define uthash_memcmp(a,b,n) alt_memcmp(a,b,n) +#define uthash_strlen(s) ..fail_to_compile.. +#define uthash_bzero(a,n) alt_bzero(a,n) + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +static size_t alt_malloc_sizes[10]; +static int alt_malloc_balance = 0; +static void *alt_malloc(size_t sz) +{ + alt_malloc_sizes[alt_malloc_balance++] = sz; + if (alt_malloc_balance == 1) { + assert(sz == sizeof(UT_hash_table)); + } + return malloc(sz); +} +static void alt_free(void *ptr, size_t sz) +{ + size_t expected = alt_malloc_sizes[--alt_malloc_balance]; + if (sz != expected) { + printf("expected free of size %d, got %d\n", (int)expected, (int)sz); + } + free(ptr); +} + +static int alt_memcmp_count = 0; +static int alt_memcmp(const void *a, const void *b, size_t n) +{ + ++alt_memcmp_count; + return memcmp(a,b,n); +} + +static int alt_bzero_count = 0; +static void alt_bzero(void *a, size_t n) +{ + ++alt_bzero_count; + memset(a,0,n); +} + +static void *real_malloc(size_t n) +{ + return malloc(n); +} + +static void real_free(void *p) +{ + free(p); +} + +#undef malloc +#undef realloc +#undef free +#undef memset +#undef memcmp +#undef strlen +#define malloc ..fail_to_compile.. +#define realloc ..fail_to_compile.. +#define free ..fail_to_compile.. +#define memset ..fail_to_compile.. +#define memcmp ..fail_to_compile.. +#define strlen ..fail_to_compile.. + +int main() +{ + int i; + example_user_t *user, *tmp, *users=NULL; + + /* create elements */ + for(i=0; i<10; i++) { + user = (example_user_t*)real_malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + + /* delete each ID */ + for(i=0; i<10; i++) { + HASH_FIND_INT(users,&i,tmp); + if (tmp != NULL) { + HASH_DEL(users,tmp); + real_free(tmp); + } else { + printf("user id %d not found\n", i); + } + } + + /* show the hash */ + for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { + printf("user %d, cookie %d\n", user->id, user->cookie); + } + +#ifdef HASH_BLOOM + assert(alt_bzero_count == 3); +#else + assert(alt_bzero_count == 2); +#endif + assert(alt_memcmp_count == 10); + assert(alt_malloc_balance == 0); + return 0; +} diff --git a/tests/test60.ans b/tests/test60.ans new file mode 100644 index 000000000..e19f2f6cd --- /dev/null +++ b/tests/test60.ans @@ -0,0 +1 @@ +$items{bob}{age} = 37 diff --git a/tests/test60.c b/tests/test60.c new file mode 100644 index 000000000..138c0da86 --- /dev/null +++ b/tests/test60.c @@ -0,0 +1,51 @@ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "uthash.h" + +/* hash of hashes */ +typedef struct item { + char name[10]; + struct item *sub; + int val; + UT_hash_handle hh; +} item_t; + +int main() +{ + item_t *item1, *item2, *tmp1, *tmp2; + item_t *items=NULL; + + /* make initial element */ + item_t *i = (item_t *)malloc(sizeof(*i)); + if (i == NULL) { + exit(-1); + } + strcpy(i->name, "bob"); + i->sub = NULL; + i->val = 0; + HASH_ADD_STR(items, name, i); + + /* add a sub hash table off this element */ + item_t *s = (item_t *)malloc(sizeof(*s)); + if (s == NULL) { + exit(-1); + } + strcpy(s->name, "age"); + s->sub = NULL; + s->val = 37; + HASH_ADD_STR(i->sub, name, s); + + /* iterate over hash elements, printing and freeing them */ + HASH_ITER(hh, items, item1, tmp1) { + HASH_ITER(hh, item1->sub, item2, tmp2) { + printf("$items{%s}{%s} = %d\n", item1->name, item2->name, item2->val); + HASH_DEL(item1->sub, item2); + free(item2); + } + HASH_DEL(items, item1); + free(item1); + } + + return 0; +} diff --git a/tests/test61.ans b/tests/test61.ans new file mode 100644 index 000000000..39c63b45d --- /dev/null +++ b/tests/test61.ans @@ -0,0 +1,16 @@ +hello +world +one +two +three +sorting +finding hello + hello +finding one + one +finding three + three +finding two + two +finding world + world diff --git a/tests/test61.c b/tests/test61.c new file mode 100644 index 000000000..bbb3d1079 --- /dev/null +++ b/tests/test61.c @@ -0,0 +1,53 @@ +#include <stdio.h> +#include "utarray.h" + +static int strsort(const void *_a, const void *_b) +{ + const char *a = *(const char* const *)_a; + const char *b = *(const char* const *)_b; + return strcmp(a,b); +} + +int main() +{ + UT_array *strs; + const char *s, **p; + + utarray_new(strs,&ut_str_icd); + + s = "hello"; + utarray_push_back(strs, &s); + s = "world"; + utarray_push_back(strs, &s); + s = "one"; + utarray_push_back(strs, &s); + s = "two"; + utarray_push_back(strs, &s); + s = "three"; + utarray_push_back(strs, &s); + + p = NULL; + while ( (p=(const char**)utarray_next(strs,p)) != NULL ) { + s = *p; + printf("%s\n",s); + } + + printf("sorting\n"); + utarray_sort(strs,strsort); + + p = NULL; + while ( (p=(const char**)utarray_next(strs,p)) != NULL ) { + s = *p; + printf("finding %s\n",s); +#ifdef __cplusplus + p = (const char**)utarray_find(strs,&s,strsort); +#else + p = utarray_find(strs,&s,strsort); +#endif + printf(" %s\n", (p != NULL) ? (*p) : "failed"); + } + + utarray_free(strs); + + return 0; +} diff --git a/tests/test62.ans b/tests/test62.ans new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/test62.ans diff --git a/tests/test62.c b/tests/test62.c new file mode 100644 index 000000000..ad8ce45e6 --- /dev/null +++ b/tests/test62.c @@ -0,0 +1,80 @@ + +#include <assert.h> +#include <stdlib.h> + +#define HASH_FUNCTION(s, len, hashv) (hashv) = TrivialHash((const char *)s, len) +#include "uthash.h" + +unsigned int TrivialHash(const char *s, size_t len) +{ + unsigned int h = 0; + size_t i; + for (i=0; i < len; ++i) { + h += (unsigned char)s[i]; + } + return h; +} + +struct test_t { + int a; + int b; + UT_hash_handle hh; +}; + +struct test_t *make_test(int value) +{ + struct test_t *test = (struct test_t *)malloc(sizeof *test); + assert(test != NULL); + test->a = value; + return test; +} + +int main() +{ + struct test_t *tests = NULL; + struct test_t *test = NULL; + int x; + unsigned int h; + + x = 0x0042; + HASH_VALUE(&x, sizeof x, h); + assert(h == 0x42); + + x = 0x4002; + HASH_VALUE(&x, sizeof x, h); + assert(h == 0x42); + + test = make_test(0x0042); + HASH_ADD_INT(tests, a, test); + test = make_test(0x4002); + HASH_ADD_INT(tests, a, test); + + x = 0x4002; + test = NULL; + HASH_FIND_BYHASHVALUE(hh, tests, &x, sizeof x, 0x42, test); + assert(test != NULL); + assert(test->a == 0x4002); + + x = 0x0042; + test = NULL; + HASH_FIND_BYHASHVALUE(hh, tests, &x, sizeof x, 0x42, test); + assert(test != NULL); + assert(test->a == 0x0042); + + x = 0x4002; + test = NULL; + HASH_FIND_BYHASHVALUE(hh, tests, &x, sizeof x, 0x43, test); + assert(test == NULL); + + x = 0x0042; + test = NULL; + HASH_FIND_BYHASHVALUE(hh, tests, &x, sizeof x, 0x43, test); + assert(test == NULL); + + x = 0x4003; + test = NULL; + HASH_FIND_BYHASHVALUE(hh, tests, &x, sizeof x, 0x42, test); + assert(test == NULL); + + HASH_CLEAR(hh, tests); +} diff --git a/tests/test63.ans b/tests/test63.ans new file mode 100644 index 000000000..c570c50e2 --- /dev/null +++ b/tests/test63.ans @@ -0,0 +1,7 @@ +LL macros +a b c +d e f +a b c d e f +d e f +d e f +a b diff --git a/tests/test63.c b/tests/test63.c new file mode 100644 index 000000000..e41f695c7 --- /dev/null +++ b/tests/test63.c @@ -0,0 +1,67 @@ +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *next, *prev; +} el; + +int main() +{ + int i; + el els[10], *e; + el *headA = NULL; + el *headB = NULL; + for(i=0; i<10; i++) { + els[i].id=(int)'a'+i; + } + + /* test LL macros */ + printf("LL macros\n"); + LL_APPEND(headA,&els[0]); + LL_APPEND(headA,&els[1]); + LL_APPEND(headA,&els[2]); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + LL_APPEND(headB,&els[3]); + LL_APPEND(headB,&els[4]); + LL_APPEND(headB,&els[5]); + LL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + + LL_CONCAT(headA,headB); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* other variations */ + headA = NULL; + LL_CONCAT(headA,headB); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + headB = NULL; + LL_CONCAT(headA,headB); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + headA=NULL; + headB=NULL; + LL_APPEND(headA,&els[0]); + LL_APPEND(headB,&els[1]); + LL_CONCAT(headA,headB); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + return 0; +} diff --git a/tests/test64.ans b/tests/test64.ans new file mode 100644 index 000000000..1640241aa --- /dev/null +++ b/tests/test64.ans @@ -0,0 +1,7 @@ +DL macros +a b c +d e f +a b c d e f +d e f +d e f +a b diff --git a/tests/test64.c b/tests/test64.c new file mode 100644 index 000000000..ec5fba860 --- /dev/null +++ b/tests/test64.c @@ -0,0 +1,67 @@ +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *next, *prev; +} el; + +int main() +{ + int i; + el els[10], *e; + el *headA = NULL; + el *headB = NULL; + for(i=0; i<10; i++) { + els[i].id=(int)'a'+i; + } + + /* test DL macros */ + printf("DL macros\n"); + DL_APPEND(headA,&els[0]); + DL_APPEND(headA,&els[1]); + DL_APPEND(headA,&els[2]); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + DL_APPEND(headB,&els[3]); + DL_APPEND(headB,&els[4]); + DL_APPEND(headB,&els[5]); + DL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + + DL_CONCAT(headA,headB); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* other variations */ + headA = NULL; + DL_CONCAT(headA,headB); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + headB = NULL; + DL_CONCAT(headA,headB); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + headA=NULL; + headB=NULL; + DL_APPEND(headA,&els[0]); + DL_APPEND(headB,&els[1]); + DL_CONCAT(headA,headB); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + return 0; +} diff --git a/tests/test65.ans b/tests/test65.ans new file mode 100644 index 000000000..5312b22a2 --- /dev/null +++ b/tests/test65.ans @@ -0,0 +1,4 @@ +LRU deleting JOHN + 0 +LRU deleting WILLIAM + 1 diff --git a/tests/test65.c b/tests/test65.c new file mode 100644 index 000000000..c863d21db --- /dev/null +++ b/tests/test65.c @@ -0,0 +1,65 @@ +#include <string.h> +#include <stdio.h> +#include "uthash.h" + +// this is an example of how to do a LRU cache in C using uthash +// http://troydhanson.github.com/uthash/ +// by Jehiah Czebotar 2011 - jehiah@gmail.com +// this code is in the public domain http://unlicense.org/ + +#define MAX_CACHE_SIZE 50U /* a real value would be much larger */ + +struct CacheEntry { + char *key; + char *value; + UT_hash_handle hh; +}; +struct CacheEntry *cache = NULL; + +static void add_to_cache(const char *key, const char *value) +{ + struct CacheEntry *entry, *tmp_entry; + entry = (struct CacheEntry *)malloc(sizeof(struct CacheEntry)); + if (entry == NULL) { + exit(-1); + } + entry->key = strdup(key); + entry->value = strdup(value); + HASH_ADD_KEYPTR(hh, cache, entry->key, strlen(entry->key), entry); + + // prune the cache to MAX_CACHE_SIZE + if (HASH_COUNT(cache) >= MAX_CACHE_SIZE) { + HASH_ITER(hh, cache, entry, tmp_entry) { + // prune the first entry (loop is based on insertion order so this deletes the oldest item) + printf("LRU deleting %s %s\n", entry->key, entry->value); + HASH_DELETE(hh, cache, entry); + free(entry->key); + free(entry->value); + free(entry); + break; + } + } +} + +/* main added by Troy D. Hanson */ +int main() +{ + char linebuf[100]; + char nbuf[11]; + FILE *file; + unsigned int i=0; + + file = fopen( "test65.dat", "r" ); + if (file == NULL) { + perror("can't open: "); + exit(-1); + } + + while (fgets(linebuf,sizeof(linebuf),file) != NULL) { + snprintf(nbuf,sizeof(nbuf),"%u",i++); + add_to_cache(linebuf, nbuf); + } + + fclose(file); + return 0; +} diff --git a/tests/test65.dat b/tests/test65.dat new file mode 100644 index 000000000..bb6051b75 --- /dev/null +++ b/tests/test65.dat @@ -0,0 +1,51 @@ +JOHN +WILLIAM +WALTER +DOUGLAS +GERALD +FREDERICK +WARREN +SHANE +LESTER +RON +HARVEY +ADRIAN +CODY +NELSON +CLIFTON +WILLARD +DOUG +ORLANDO +REX +OMAR +DAMON +LOWELL +IRVING +CARROLL +LAURENCE +ROLANDO +CARY +XAVIER +ISAIAH +GUS +JARVIS +WINFRED +RAYMUNDO +LINCOLN +CORNELL +NIGEL +NORMAND +FRITZ +DONN +TRINIDAD +ODIS +DANNIE +DARIO +KENTON +CHONG +NEVILLE +TONEY +WARNER +WES +COLTON +ARNOLDO diff --git a/tests/test66.ans b/tests/test66.ans new file mode 100644 index 000000000..727f397eb --- /dev/null +++ b/tests/test66.ans @@ -0,0 +1,20 @@ +added bob (id 0) +added jack (id 1) +added gary (id 2) +added ty (id 3) +added bo (id 4) +added phil (id 5) +added art (id 6) +added gil (id 7) +added buck (id 8) +added ted (id 9) +found bob (id 0) +found jack (id 1) +found gary (id 2) +found ty (id 3) +found bo (id 4) +found phil (id 5) +found art (id 6) +found gil (id 7) +found buck (id 8) +found ted (id 9) diff --git a/tests/test66.c b/tests/test66.c new file mode 100644 index 000000000..e7ebe43d3 --- /dev/null +++ b/tests/test66.c @@ -0,0 +1,43 @@ +#include "uthash.h" +#include <stdio.h> +#include <stdlib.h> /* malloc */ + +typedef struct person_t { + char first_name[10]; + int id; + UT_hash_handle hh; +} person_t; + +int main() +{ + person_t *people=NULL, *person; + const char **name; + const char * names[] = { "bob", "jack", "gary", "ty", "bo", "phil", "art", + "gil", "buck", "ted", NULL + }; + int id=0; + + for(name=names; *name!=NULL; name++) { + person = (person_t*)malloc(sizeof(person_t)); + if (person == NULL) { + exit(-1); + } + strcpy(person->first_name, *name); + person->id = id++; + HASH_ADD_STR(people,first_name,person); + printf("added %s (id %d)\n", person->first_name, person->id); + } + + person=NULL; + person_t **p=&person; + + for(name=names; *name!=NULL; name++) { + HASH_FIND_STR(people,*name,*p); + if (person != NULL) { + printf("found %s (id %d)\n", person->first_name, person->id); + } else { + printf("failed to find %s\n", *name); + } + } + return 0; +} diff --git a/tests/test67.ans b/tests/test67.ans new file mode 100644 index 000000000..cd707691d --- /dev/null +++ b/tests/test67.ans @@ -0,0 +1,20 @@ +9 +8 +7 +6 +5 +4 +3 +2 +1 +0 +9 +8 +7 +6 +5 +4 +3 +2 +1 +0 diff --git a/tests/test67.c b/tests/test67.c new file mode 100644 index 000000000..6602c7b59 --- /dev/null +++ b/tests/test67.c @@ -0,0 +1,30 @@ +#include <stdio.h> +#include "utarray.h" + +int main() +{ + UT_array *nums; + int i, *p; + + utarray_new(nums,&ut_int_icd); + for(i=0; i < 10; i++) { + utarray_push_back(nums,&i); + } + + for(p=(int*)utarray_back(nums); + p!=NULL; + p=(int*)utarray_prev(nums,p)) { + printf("%d\n",*p); + } + + /* the other form of iteration starting from NULL (back) */ + p=NULL; + while ( (p=(int*)utarray_prev(nums,p)) != NULL ) { + printf("%d\n",*p); + } + + + utarray_free(nums); + + return 0; +} diff --git a/tests/test68.ans b/tests/test68.ans new file mode 100644 index 000000000..704cdc534 --- /dev/null +++ b/tests/test68.ans @@ -0,0 +1,10 @@ +DL replace elem +a b c d +e b c d +f b c d +f b c g +f b c h +f i j h +k l m n +s +t diff --git a/tests/test68.c b/tests/test68.c new file mode 100644 index 000000000..090f7d022 --- /dev/null +++ b/tests/test68.c @@ -0,0 +1,87 @@ +#include <stdlib.h> +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *next, *prev; +} el; + +int main() +{ + int i; + el els[20], *e, *tmp; + el *headA = NULL; + el *headB = NULL; + for(i=0; i<20; i++) { + els[i].id=(int)'a'+i; + } + + /* test DL macros */ + printf("DL replace elem\n"); + DL_APPEND(headA,&els[0]); + DL_APPEND(headA,&els[1]); + DL_APPEND(headA,&els[2]); + DL_APPEND(headA,&els[3]); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* replace head elem */ + DL_REPLACE_ELEM(headA, &els[0], &els[4]); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + DL_REPLACE_ELEM(headA, &els[4], &els[5]); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* replace last elem */ + DL_REPLACE_ELEM(headA, &els[3], &els[6]); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + DL_REPLACE_ELEM(headA, &els[6], &els[7]); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* replace middle elem */ + DL_REPLACE_ELEM(headA, &els[1], &els[8]); + DL_REPLACE_ELEM(headA, &els[2], &els[9]); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* replace all just to be sure the list is intact... */ + i = 10; + DL_FOREACH_SAFE(headA, e, tmp) { + DL_REPLACE_ELEM(headA, e, &els[i]); + i++; + } + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* single elem */ + DL_APPEND(headB, &els[18]); + DL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + DL_REPLACE_ELEM(headB, &els[18], &els[19]); + DL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + + return 0; +} diff --git a/tests/test69.ans b/tests/test69.ans new file mode 100644 index 000000000..fba8b64c6 --- /dev/null +++ b/tests/test69.ans @@ -0,0 +1,11 @@ +DL prepend elem +a b c d +e a b c d +f e a b c d +f e a b c g d +f e a b c h g d +f e a b i j c h g d +k f l e m a n b o i p j q c r h s g t d +u +v u +w v u diff --git a/tests/test69.c b/tests/test69.c new file mode 100644 index 000000000..bc851a58a --- /dev/null +++ b/tests/test69.c @@ -0,0 +1,92 @@ +#include <stdlib.h> +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *next, *prev; +} el; + +int main() +{ + int i; + el els[26], *e, *tmp; + el *headA = NULL; + el *headB = NULL; + for(i=0; i<25; i++) { + els[i].id=(int)'a'+i; + } + + /* test DL macros */ + printf("DL prepend elem\n"); + DL_APPEND(headA,&els[0]); + DL_APPEND(headA,&els[1]); + DL_APPEND(headA,&els[2]); + DL_APPEND(headA,&els[3]); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* prepend head elem */ + DL_PREPEND_ELEM(headA, &els[0], &els[4]); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + DL_PREPEND_ELEM(headA, &els[4], &els[5]); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* prepend last elem */ + DL_PREPEND_ELEM(headA, &els[3], &els[6]); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + DL_PREPEND_ELEM(headA, &els[6], &els[7]); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* prepend middle elem */ + DL_PREPEND_ELEM(headA, &els[2], &els[8]); + DL_PREPEND_ELEM(headA, &els[2], &els[9]); + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* prepend all just to be sure the list is intact... */ + i = 10; + DL_FOREACH_SAFE(headA, e, tmp) { + DL_PREPEND_ELEM(headA, e, &els[i]); + i++; + } + DL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* single elem */ + DL_APPEND(headB, &els[20]); + DL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + DL_PREPEND_ELEM(headB, &els[20], &els[21]); + DL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + DL_PREPEND_ELEM(headB, &els[21], &els[22]); + DL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + + return 0; +} diff --git a/tests/test7.ans b/tests/test7.ans new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/test7.ans diff --git a/tests/test7.c b/tests/test7.c new file mode 100644 index 000000000..01ce54749 --- /dev/null +++ b/tests/test7.c @@ -0,0 +1,44 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +int main() +{ + int i; + example_user_t *user, *tmp, *users=NULL; + + /* create elements */ + for(i=0; i<1000; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + + /* delete each ID */ + for(i=0; i<1000; i++) { + HASH_FIND_INT(users,&i,tmp); + if (tmp != NULL) { + HASH_DEL(users,tmp); + free(tmp); + } else { + printf("user id %d not found\n", i); + } + } + + /* show the hash */ + for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { + printf("user %d, cookie %d\n", user->id, user->cookie); + } + return 0; +} diff --git a/tests/test70.ans b/tests/test70.ans new file mode 100644 index 000000000..00298ec4b --- /dev/null +++ b/tests/test70.ans @@ -0,0 +1,10 @@ +LL replace elem +a b c d +e b c d +f b c d +f b c g +f b c h +f i j h +k l m n +s +t diff --git a/tests/test70.c b/tests/test70.c new file mode 100644 index 000000000..abddea1c8 --- /dev/null +++ b/tests/test70.c @@ -0,0 +1,87 @@ +#include <stdlib.h> +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *next, *prev; +} el; + +int main() +{ + int i; + el els[20], *e, *tmp; + el *headA = NULL; + el *headB = NULL; + for(i=0; i<20; i++) { + els[i].id=(int)'a'+i; + } + + /* test LL macros */ + printf("LL replace elem\n"); + LL_APPEND(headA,&els[0]); + LL_APPEND(headA,&els[1]); + LL_APPEND(headA,&els[2]); + LL_APPEND(headA,&els[3]); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* replace head elem */ + LL_REPLACE_ELEM(headA, &els[0], &els[4]); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + LL_REPLACE_ELEM(headA, &els[4], &els[5]); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* replace last elem */ + LL_REPLACE_ELEM(headA, &els[3], &els[6]); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + LL_REPLACE_ELEM(headA, &els[6], &els[7]); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* replace middle elem */ + LL_REPLACE_ELEM(headA, &els[1], &els[8]); + LL_REPLACE_ELEM(headA, &els[2], &els[9]); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* replace all just to be sure the list is intact... */ + i = 10; + LL_FOREACH_SAFE(headA, e, tmp) { + LL_REPLACE_ELEM(headA, e, &els[i]); + i++; + } + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* single elem */ + LL_APPEND(headB, &els[18]); + LL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + LL_REPLACE_ELEM(headB, &els[18], &els[19]); + LL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + + return 0; +} diff --git a/tests/test71.ans b/tests/test71.ans new file mode 100644 index 000000000..81d6b5377 --- /dev/null +++ b/tests/test71.ans @@ -0,0 +1,11 @@ +LL prepend elem +a b c d +e a b c d +f e a b c d +f e a b c g d +f e a b c h g d +f e a b i j c h g d +k f l e m a n b o i p j q c r h s g t d +u +v u +w v u diff --git a/tests/test71.c b/tests/test71.c new file mode 100644 index 000000000..8cda49935 --- /dev/null +++ b/tests/test71.c @@ -0,0 +1,92 @@ +#include <stdlib.h> +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *next, *prev; +} el; + +int main() +{ + int i; + el els[26], *e, *tmp; + el *headA = NULL; + el *headB = NULL; + for(i=0; i<25; i++) { + els[i].id=(int)'a'+i; + } + + /* test LL macros */ + printf("LL prepend elem\n"); + LL_APPEND(headA,&els[0]); + LL_APPEND(headA,&els[1]); + LL_APPEND(headA,&els[2]); + LL_APPEND(headA,&els[3]); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* prepend head elem */ + LL_PREPEND_ELEM(headA, &els[0], &els[4]); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + LL_PREPEND_ELEM(headA, &els[4], &els[5]); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* prepend last elem */ + LL_PREPEND_ELEM(headA, &els[3], &els[6]); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + LL_PREPEND_ELEM(headA, &els[6], &els[7]); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* prepend middle elem */ + LL_PREPEND_ELEM(headA, &els[2], &els[8]); + LL_PREPEND_ELEM(headA, &els[2], &els[9]); + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* prepend all just to be sure the list is intact... */ + i = 10; + LL_FOREACH_SAFE(headA, e, tmp) { + LL_PREPEND_ELEM(headA, e, &els[i]); + i++; + } + LL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* single elem */ + LL_APPEND(headB, &els[20]); + LL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + LL_PREPEND_ELEM(headB, &els[20], &els[21]); + LL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + LL_PREPEND_ELEM(headB, &els[21], &els[22]); + LL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + + return 0; +} diff --git a/tests/test72.ans b/tests/test72.ans new file mode 100644 index 000000000..b5ccb1493 --- /dev/null +++ b/tests/test72.ans @@ -0,0 +1,10 @@ +CDL replace elem +a b c d +e b c d +f b c d +f b c g +f b c h +f i j h +k l m n +s +t diff --git a/tests/test72.c b/tests/test72.c new file mode 100644 index 000000000..61ae11d15 --- /dev/null +++ b/tests/test72.c @@ -0,0 +1,87 @@ +#include <stdlib.h> +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *next, *prev; +} el; + +int main() +{ + int i; + el els[20], *e, *tmp, *tmp2; + el *headA = NULL; + el *headB = NULL; + for(i=0; i<20; i++) { + els[i].id=(int)'a'+i; + } + + /* test CDL macros */ + printf("CDL replace elem\n"); + CDL_PREPEND(headA,&els[3]); + CDL_PREPEND(headA,&els[2]); + CDL_PREPEND(headA,&els[1]); + CDL_PREPEND(headA,&els[0]); + CDL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* replace head elem */ + CDL_REPLACE_ELEM(headA, &els[0], &els[4]); + CDL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + CDL_REPLACE_ELEM(headA, &els[4], &els[5]); + CDL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* replace last elem */ + CDL_REPLACE_ELEM(headA, &els[3], &els[6]); + CDL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + CDL_REPLACE_ELEM(headA, &els[6], &els[7]); + CDL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* replace middle elem */ + CDL_REPLACE_ELEM(headA, &els[1], &els[8]); + CDL_REPLACE_ELEM(headA, &els[2], &els[9]); + CDL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* replace all just to be sure the list is intact... */ + i = 10; + CDL_FOREACH_SAFE(headA, e, tmp, tmp2) { + CDL_REPLACE_ELEM(headA, e, &els[i]); + i++; + } + CDL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* single elem */ + CDL_PREPEND(headB, &els[18]); + CDL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + CDL_REPLACE_ELEM(headB, &els[18], &els[19]); + CDL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + + return 0; +} diff --git a/tests/test73.ans b/tests/test73.ans new file mode 100644 index 000000000..2aa7bdc79 --- /dev/null +++ b/tests/test73.ans @@ -0,0 +1,11 @@ +CDL prepend elem +a b c d +e a b c d +f e a b c d +f e a b c g d +f e a b c h g d +f e a b i j c h g d +k f l e m a n b o i p j q c r h s g t d +u +v u +w v u diff --git a/tests/test73.c b/tests/test73.c new file mode 100644 index 000000000..ac7e78568 --- /dev/null +++ b/tests/test73.c @@ -0,0 +1,92 @@ +#include <stdlib.h> +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *next, *prev; +} el; + +int main() +{ + int i; + el els[26], *e, *tmp, *tmp2; + el *headA = NULL; + el *headB = NULL; + for(i=0; i<25; i++) { + els[i].id=(int)'a'+i; + } + + /* test CDL macros */ + printf("CDL prepend elem\n"); + CDL_PREPEND(headA,&els[3]); + CDL_PREPEND(headA,&els[2]); + CDL_PREPEND(headA,&els[1]); + CDL_PREPEND(headA,&els[0]); + CDL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* prepend head elem */ + CDL_PREPEND_ELEM(headA, &els[0], &els[4]); + CDL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + CDL_PREPEND_ELEM(headA, &els[4], &els[5]); + CDL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* prepend last elem */ + CDL_PREPEND_ELEM(headA, &els[3], &els[6]); + CDL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + CDL_PREPEND_ELEM(headA, &els[6], &els[7]); + CDL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* prepend middle elem */ + CDL_PREPEND_ELEM(headA, &els[2], &els[8]); + CDL_PREPEND_ELEM(headA, &els[2], &els[9]); + CDL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* prepend all just to be sure the list is intact... */ + i = 10; + CDL_FOREACH_SAFE(headA, e, tmp, tmp2) { + CDL_PREPEND_ELEM(headA, e, &els[i]); + i++; + } + CDL_FOREACH(headA,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* single elem */ + CDL_PREPEND(headB, &els[20]); + CDL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + CDL_PREPEND_ELEM(headB, &els[20], &els[21]); + CDL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + CDL_PREPEND_ELEM(headB, &els[21], &els[22]); + CDL_FOREACH(headB,e) { + printf("%c ", e->id); + } + printf("\n"); + + return 0; +} diff --git a/tests/test74.ans b/tests/test74.ans new file mode 100644 index 000000000..79a16baa2 --- /dev/null +++ b/tests/test74.ans @@ -0,0 +1,6 @@ +"There are two needle" len=55 +"needle" len=8 +utstring_find()=14 +utstring_find()=46 +utstring_find()=-1 +FindCnt=2 diff --git a/tests/test74.c b/tests/test74.c new file mode 100644 index 000000000..6cb035211 --- /dev/null +++ b/tests/test74.c @@ -0,0 +1,40 @@ +#include <stdio.h> /* printf */
+#include "utstring.h"
+
+int main()
+{
+ UT_string *s,*t;
+ char V_TestStr[] = "There are two needle\0s in this \0haystack with needle\0s.";
+ char V_NeedleStr[] = "needle\0s";
+ long V_FindPos;
+ size_t V_FindCnt;
+
+
+ utstring_new(s);
+ utstring_new(t);
+
+ utstring_bincpy(s, V_TestStr, sizeof(V_TestStr)-1);
+ printf("\"%s\" len=%u\n", utstring_body(s), (unsigned)utstring_len(s));
+ utstring_bincpy(t, V_NeedleStr, sizeof(V_NeedleStr)-1);
+ printf("\"%s\" len=%u\n", utstring_body(t), (unsigned)utstring_len(t));
+
+ V_FindCnt = 0;
+ V_FindPos = 0;
+ do {
+ V_FindPos = utstring_find(s,
+ V_FindPos,
+ utstring_body(t),
+ utstring_len(t));
+ printf("utstring_find()=%ld\n", V_FindPos);
+ if (V_FindPos >= 0) {
+ V_FindPos++;
+ V_FindCnt++;
+ }
+ } while (V_FindPos >= 0);
+ printf("FindCnt=%u\n", (unsigned)V_FindCnt);
+
+ utstring_free(s);
+ utstring_free(t);
+
+ return 0;
+}
diff --git a/tests/test75.ans b/tests/test75.ans new file mode 100644 index 000000000..8261ba353 --- /dev/null +++ b/tests/test75.ans @@ -0,0 +1,6 @@ +"There are two needle" len=55 +"needle" len=8 +utstring_findR()=46 +utstring_findR()=14 +utstring_findR()=-1 +FindCnt=2 diff --git a/tests/test75.c b/tests/test75.c new file mode 100644 index 000000000..fa3adedb8 --- /dev/null +++ b/tests/test75.c @@ -0,0 +1,40 @@ +#include <stdio.h> /* printf */
+#include "utstring.h"
+
+int main()
+{
+ UT_string *s,*t;
+ char V_TestStr[] = "There are two needle\0s in this \0haystack with needle\0s.";
+ char V_NeedleStr[] = "needle\0s";
+ long V_FindPos;
+ size_t V_FindCnt;
+
+
+ utstring_new(s);
+ utstring_new(t);
+
+ utstring_bincpy(s, V_TestStr, sizeof(V_TestStr)-1);
+ printf("\"%s\" len=%u\n", utstring_body(s), (unsigned)utstring_len(s));
+ utstring_bincpy(t, V_NeedleStr, sizeof(V_NeedleStr)-1);
+ printf("\"%s\" len=%u\n", utstring_body(t), (unsigned)utstring_len(t));
+
+ V_FindCnt = 0;
+ V_FindPos = -1;
+ do {
+ V_FindPos = utstring_findR(s,
+ V_FindPos,
+ utstring_body(t),
+ utstring_len(t));
+ printf("utstring_findR()=%ld\n", V_FindPos);
+ if (V_FindPos >= 0) {
+ V_FindPos--;
+ V_FindCnt++;
+ }
+ } while (V_FindPos >= 0);
+ printf("FindCnt=%u\n", (unsigned)V_FindCnt);
+
+ utstring_free(s);
+ utstring_free(t);
+
+ return 0;
+}
diff --git a/tests/test76.ans b/tests/test76.ans new file mode 100644 index 000000000..79a16baa2 --- /dev/null +++ b/tests/test76.ans @@ -0,0 +1,6 @@ +"There are two needle" len=55 +"needle" len=8 +utstring_find()=14 +utstring_find()=46 +utstring_find()=-1 +FindCnt=2 diff --git a/tests/test76.c b/tests/test76.c new file mode 100644 index 000000000..a18685cae --- /dev/null +++ b/tests/test76.c @@ -0,0 +1,54 @@ +#include <stdio.h> /* printf */
+#include "utstring.h"
+
+int main()
+{
+ UT_string *s,*t;
+ char V_TestStr[] = "There are two needle\0s in this \0haystack with needle\0s.";
+ char V_NeedleStr[] = "needle\0s";
+ long *V_KMP_Table;
+ long V_FindPos;
+ size_t V_StartPos;
+ size_t V_FindCnt;
+
+
+ utstring_new(s);
+ utstring_new(t);
+
+ utstring_bincpy(s, V_TestStr, sizeof(V_TestStr)-1);
+ printf("\"%s\" len=%u\n", utstring_body(s), (unsigned)utstring_len(s));
+ utstring_bincpy(t, V_NeedleStr, sizeof(V_NeedleStr)-1);
+ printf("\"%s\" len=%u\n", utstring_body(t), (unsigned)utstring_len(t));
+
+ V_KMP_Table = (long *)malloc(sizeof(long) * (utstring_len(t) + 1));
+ if (V_KMP_Table != NULL) {
+ _utstring_BuildTable(utstring_body(t), utstring_len(t), V_KMP_Table);
+
+ V_FindCnt = 0;
+ V_FindPos = 0;
+ V_StartPos = 0;
+ do {
+ V_FindPos = _utstring_find(utstring_body(s) + V_StartPos,
+ utstring_len(s) - V_StartPos,
+ utstring_body(t),
+ utstring_len(t),
+ V_KMP_Table);
+ if (V_FindPos >= 0) {
+ V_FindPos += V_StartPos;
+ V_FindCnt++;
+ V_StartPos = V_FindPos + 1;
+ }
+ printf("utstring_find()=%ld\n", V_FindPos);
+ } while (V_FindPos >= 0);
+ printf("FindCnt=%u\n", (unsigned)V_FindCnt);
+
+ free(V_KMP_Table);
+ } else {
+ printf("malloc() failed...\n");
+ }
+
+ utstring_free(s);
+ utstring_free(t);
+
+ return 0;
+}
diff --git a/tests/test77.ans b/tests/test77.ans new file mode 100644 index 000000000..3b2a10971 --- /dev/null +++ b/tests/test77.ans @@ -0,0 +1,13 @@ +"There are two needle" len=55 +"needle" len=8 +utstring_find()=46 +utstring_find()=14 +utstring_find()=-1 +FindCnt=2 +expect 15 15 +expect 4 4 +expect -1 -1 +expect 11 11 +expect 4 4 +expect 11 11 +expect 0 0 diff --git a/tests/test77.c b/tests/test77.c new file mode 100644 index 000000000..7ff97518e --- /dev/null +++ b/tests/test77.c @@ -0,0 +1,74 @@ +#include <stdio.h> /* printf */
+#include "utstring.h"
+
+int main()
+{
+ UT_string *s,*t;
+ char V_TestStr[] = "There are two needle\0s in this \0haystack with needle\0s.";
+ char V_NeedleStr[] = "needle\0s";
+ long *V_KMP_Table;
+ long V_FindPos;
+ size_t V_StartPos;
+ size_t V_FindCnt;
+
+
+ utstring_new(s);
+ utstring_new(t);
+
+ utstring_bincpy(s, V_TestStr, sizeof(V_TestStr)-1);
+ printf("\"%s\" len=%u\n", utstring_body(s), (unsigned)utstring_len(s));
+ utstring_bincpy(t, V_NeedleStr, sizeof(V_NeedleStr)-1);
+ printf("\"%s\" len=%u\n", utstring_body(t), (unsigned)utstring_len(t));
+
+ V_KMP_Table = (long *)malloc(sizeof(long) * (utstring_len(t) + 1));
+ if (V_KMP_Table != NULL) {
+ _utstring_BuildTableR(utstring_body(t), utstring_len(t), V_KMP_Table);
+
+ V_FindCnt = 0;
+ V_FindPos = 0;
+ V_StartPos = utstring_len(s) - 1;
+ do {
+ V_FindPos = _utstring_findR(utstring_body(s),
+ V_StartPos + 1,
+ utstring_body(t),
+ utstring_len(t),
+ V_KMP_Table);
+ if (V_FindPos >= 0) {
+ V_FindCnt++;
+ V_StartPos = V_FindPos - 1;
+ }
+ printf("utstring_find()=%ld\n", V_FindPos);
+ } while (V_FindPos >= 0);
+ printf("FindCnt=%u\n", (unsigned)V_FindCnt);
+
+ free(V_KMP_Table);
+ } else {
+ printf("malloc() failed...\n");
+ }
+
+ utstring_free(t);
+ utstring_clear(s);
+ utstring_printf(s,"ABC ABCDAB ABCDABCDABDE");
+ int o;
+
+ o=utstring_find( s, -9, "ABC", 3 ) ;
+ printf("expect 15 %d\n",o);
+ o=utstring_find( s, 3, "ABC", 3 ) ;
+ printf("expect 4 %d\n",o);
+ o=utstring_find( s, 16, "ABC", 3 ) ;
+ printf("expect -1 %d\n",o);
+ o=utstring_findR( s, -9, "ABC", 3 ) ;
+ printf("expect 11 %d\n",o);
+ o=utstring_findR( s, 12, "ABC", 3 ) ;
+ printf("expect 4 %d\n",o);
+ o=utstring_findR( s, 13, "ABC", 3 ) ;
+ printf("expect 11 %d\n",o);
+ o=utstring_findR( s, 2, "ABC", 3 ) ;
+ printf("expect 0 %d\n",o);
+
+
+
+ utstring_free(s);
+
+ return 0;
+}
diff --git a/tests/test78.ans b/tests/test78.ans new file mode 100644 index 000000000..5c71cdfdc --- /dev/null +++ b/tests/test78.ans @@ -0,0 +1,28 @@ +CDL macros +c b a +advancing head pointer +b a c +b a c b a c b a c b +b c a b c a b c a b +deleting b +a c +deleting (a) +c +deleting (c) + +DL macros +a b c +deleting tail c +a b +deleting head a +b +deleting head b + +LL macros +a b c +deleting tail c +a b +deleting head a +b +deleting head b + diff --git a/tests/test78.c b/tests/test78.c new file mode 100644 index 000000000..02424d543 --- /dev/null +++ b/tests/test78.c @@ -0,0 +1,130 @@ +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *Next, *Prev; +} el; + +int main() +{ + int i; + el els[10], *e; + el *head = NULL; + for(i=0; i<10; i++) { + els[i].id=(int)'a'+i; + } + + /* test CDL macros */ + printf("CDL macros\n"); + CDL_PREPEND2(head,&els[0],Prev,Next); + CDL_PREPEND2(head,&els[1],Prev,Next); + CDL_PREPEND2(head,&els[2],Prev,Next); + CDL_FOREACH2(head,e,Next) { + printf("%c ", e->id); + } + printf("\n"); + + /* point head to head->next */ + printf("advancing head pointer\n"); + head = head->Next; + CDL_FOREACH2(head,e,Next) { + printf("%c ", e->id); + } + printf("\n"); + + /* follow circular loop a few times */ + for(i=0,e=head; e && i<10; i++,e=e->Next) { + printf("%c ", e->id); + } + printf("\n"); + + /* follow circular loop backwards a few times */ + for(i=0,e=head; e && i<10; i++,e=e->Prev) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting b\n"); + CDL_DELETE2(head,&els[1],Prev,Next); + CDL_FOREACH2(head,e,Next) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (a)\n"); + CDL_DELETE2(head,&els[0],Prev,Next); + CDL_FOREACH2(head,e,Next) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (c)\n"); + CDL_DELETE2(head,&els[2],Prev,Next); + CDL_FOREACH2(head,e,Next) { + printf("%c ", e->id); + } + printf("\n"); + + /* test DL macros */ + printf("DL macros\n"); + DL_APPEND2(head,&els[0],Prev,Next); + DL_APPEND2(head,&els[1],Prev,Next); + DL_APPEND2(head,&els[2],Prev,Next); + DL_FOREACH2(head,e,Next) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting tail c\n"); + DL_DELETE2(head,&els[2],Prev,Next); + DL_FOREACH2(head,e,Next) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting head a\n"); + DL_DELETE2(head,&els[0],Prev,Next); + DL_FOREACH2(head,e,Next) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting head b\n"); + DL_DELETE2(head,&els[1],Prev,Next); + DL_FOREACH2(head,e,Next) { + printf("%c ", e->id); + } + printf("\n"); + + /* test LL macros */ + printf("LL macros\n"); + LL_APPEND2(head,&els[0],Next); + LL_APPEND2(head,&els[1],Next); + LL_APPEND2(head,&els[2],Next); + LL_FOREACH2(head,e,Next) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting tail c\n"); + LL_DELETE2(head,&els[2],Next); + LL_FOREACH2(head,e,Next) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting head a\n"); + LL_DELETE2(head,&els[0],Next); + LL_FOREACH2(head,e,Next) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting head b\n"); + LL_DELETE2(head,&els[1],Next); + LL_FOREACH2(head,e,Next) { + printf("%c ", e->id); + } + printf("\n"); + + return 0; +} diff --git a/tests/test79.ans b/tests/test79.ans new file mode 100644 index 000000000..c8737e47c --- /dev/null +++ b/tests/test79.ans @@ -0,0 +1,8 @@ +added 10 100 +id 10, tag 100 +added 11 101 +id 10, tag 100 +id 11, tag 101 +replaced 11 that had tag 101 with tag 102 +id 10, tag 100 +id 11, tag 102 diff --git a/tests/test79.c b/tests/test79.c new file mode 100644 index 000000000..4abbe94b1 --- /dev/null +++ b/tests/test79.c @@ -0,0 +1,71 @@ +#include <stdlib.h> +#include <stdio.h> +#include "uthash.h" + +typedef struct hs_t { + int id; + int tag; + UT_hash_handle hh; +} hs_t; + + +static void pr(hs_t **hdpp) +{ + hs_t *el, *tmp, *hdp = *hdpp; + HASH_ITER(hh, hdp, el, tmp) { + printf("id %d, tag %d\n",el->id,el->tag); + } +} + +int main() +{ + + hs_t *hs_head=NULL, *tmp, *replaced=NULL; + + tmp = (hs_t*)malloc(sizeof(hs_t)); + if (tmp == NULL) { + exit(-1); + } + tmp->id = 10; + tmp->tag = 100; + HASH_REPLACE_INT(hs_head,id,tmp,replaced); + if(replaced == NULL) { + printf("added %d %d\n",tmp->id,tmp->tag); + } else { + printf("ERROR, ended up replacing a value, replaced: %p\n",(void*)replaced); + } + + pr(&hs_head); + + tmp = (hs_t*)malloc(sizeof(hs_t)); + if (tmp == NULL) { + exit(-1); + } + tmp->id=11; + tmp->tag = 101; + HASH_REPLACE_INT(hs_head,id,tmp,replaced); + if(replaced == NULL) { + printf("added %d %d\n",tmp->id,tmp->tag); + } else { + printf("ERROR, ended up replacing a value, replaced: %p\n",(void*)replaced); + } + + pr(&hs_head); + + tmp = (hs_t*)malloc(sizeof(hs_t)); + if (tmp == NULL) { + exit(-1); + } + tmp->id=11; + tmp->tag = 102; + HASH_REPLACE_INT(hs_head,id,tmp,replaced); + if(replaced == NULL) { + printf("ERROR, exected to replace a value with key: %d\n",tmp->id); + } else { + printf("replaced %d that had tag %d with tag %d\n",tmp->id,replaced->tag,tmp->tag); + } + + pr(&hs_head); + + return 0; +} diff --git a/tests/test8.ans b/tests/test8.ans new file mode 100644 index 000000000..9d28857c4 --- /dev/null +++ b/tests/test8.ans @@ -0,0 +1,15 @@ +num_items in hash: 1 +num_items in hash: 2 +num_items in hash: 3 +num_items in hash: 4 +num_items in hash: 5 +num_items in hash: 6 +num_items in hash: 7 +num_items in hash: 8 +num_items in hash: 9 +num_items in hash: 10 +deleted; num_items in hash: 9 +deleted; num_items in hash: 8 +deleted; num_items in hash: 7 +deleted; num_items in hash: 6 +deleted; num_items in hash: 5 diff --git a/tests/test8.c b/tests/test8.c new file mode 100644 index 000000000..3497101b6 --- /dev/null +++ b/tests/test8.c @@ -0,0 +1,40 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +int main() +{ + int i; + example_user_t *user, *tmp, *users=NULL; + + /* create elements */ + for(i=0; i<10; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + printf("num_items in hash: %u\n", user->hh.tbl->num_items); + } + + /* delete each even ID */ + for(i=0; i<10; i+=2) { + HASH_FIND_INT(users,&i,tmp); + if (tmp != NULL) { + HASH_DEL(users,tmp); + free(tmp); + printf("deleted; num_items in hash: %u\n", user->hh.tbl->num_items); + } else { + printf("user id %d not found\n", i); + } + } + return 0; +} diff --git a/tests/test80.ans b/tests/test80.ans new file mode 100644 index 000000000..763f6377a --- /dev/null +++ b/tests/test80.ans @@ -0,0 +1,6 @@ +0 1 2 3 4 5 6 7 8 9 +len: 10 + +0 1 2 3 4 5 6 7 8 9 0 11 +len: 12 + diff --git a/tests/test80.c b/tests/test80.c new file mode 100644 index 000000000..293fac853 --- /dev/null +++ b/tests/test80.c @@ -0,0 +1,29 @@ +#include <stdio.h> +#include "utarray.h" + +int main() +{ + UT_array *a; + int i, *p; + utarray_new(a, &ut_int_icd); + for(i=0; i<10; i++) { + utarray_push_back(a,&i); + } + for(p=(int*)utarray_front(a); p!=NULL; p=(int*)utarray_next(a,p)) { + printf("%d ",*p); + } + printf("\n"); + printf("len: %u\n\n", utarray_len(a)); + + i=11; + utarray_insert(a, &i, 11); + while ( (p=(int*)utarray_next(a,p)) != NULL ) { + printf("%d ", *p); + } + printf("\n"); + printf("len: %u\n\n", utarray_len(a)); + + utarray_free(a); + return 0; +} + diff --git a/tests/test81.ans b/tests/test81.ans new file mode 100644 index 000000000..24adbd9c2 --- /dev/null +++ b/tests/test81.ans @@ -0,0 +1,6 @@ +0 1 2 3 4 5 6 7 8 9 +len: 10 + +0 1 2 3 4 5 6 7 8 9 10 +len: 11 + diff --git a/tests/test81.c b/tests/test81.c new file mode 100644 index 000000000..90494379b --- /dev/null +++ b/tests/test81.c @@ -0,0 +1,29 @@ +#include <stdio.h> +#include "utarray.h" + +int main() +{ + UT_array *a; + int i, *p; + utarray_new(a, &ut_int_icd); + for(i=0; i<10; i++) { + utarray_push_back(a,&i); + } + for(p=(int*)utarray_front(a); p!=NULL; p=(int*)utarray_next(a,p)) { + printf("%d ",*p); + } + printf("\n"); + printf("len: %u\n\n", utarray_len(a)); + + i=10; + utarray_insert(a, &i, 10); + while ( (p=(int*)utarray_next(a,p)) != NULL ) { + printf("%d ", *p); + } + printf("\n"); + printf("len: %u\n\n", utarray_len(a)); + + utarray_free(a); + return 0; +} + diff --git a/tests/test82.ans b/tests/test82.ans new file mode 100644 index 000000000..ce8f5b579 --- /dev/null +++ b/tests/test82.ans @@ -0,0 +1,9 @@ +0 1 2 3 4 5 6 7 8 9 +len: 10 + +0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 len: 20 + +0 1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 len: 30 + +0 1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 0 1 2 3 4 5 6 7 8 9 5 6 7 8 9 len: 40 + diff --git a/tests/test82.c b/tests/test82.c new file mode 100644 index 000000000..3a5d05f72 --- /dev/null +++ b/tests/test82.c @@ -0,0 +1,42 @@ +#include <stdio.h> +#include "utarray.h" + +int main() +{ + UT_array *a,*b; + int i, *p; + utarray_new(a, &ut_int_icd); + utarray_new(b, &ut_int_icd); + + for(i=0; i<10; i++) { + utarray_push_back(a,&i); + } + for(p=(int*)utarray_front(a); p!=NULL; p=(int*)utarray_next(a,p)) { + printf("%d ",*p); + } + printf("\n"); + printf("len: %u\n\n", utarray_len(a)); + + utarray_inserta(b,a,10); + for(p=(int*)utarray_front(b); p!=NULL; p=(int*)utarray_next(b,p)) { + printf("%d ",*p); + } + printf("len: %u\n\n", utarray_len(b)); + + utarray_inserta(b,a,0); + for(p=(int*)utarray_front(b); p!=NULL; p=(int*)utarray_next(b,p)) { + printf("%d ",*p); + } + printf("len: %u\n\n", utarray_len(b)); + + utarray_inserta(b,a,25); + for(p=(int*)utarray_front(b); p!=NULL; p=(int*)utarray_next(b,p)) { + printf("%d ",*p); + } + printf("len: %u\n\n", utarray_len(b)); + + utarray_free(a); + utarray_free(b); + return 0; +} + diff --git a/tests/test83.ans b/tests/test83.ans new file mode 100644 index 000000000..ada2c442b --- /dev/null +++ b/tests/test83.ans @@ -0,0 +1,41 @@ +added bob (id 0) +added jack (id 1) +added gary (id 2) +added ty (id 3) +added bo (id 4) +added phil (id 5) +added art (id 6) +added gil (id 7) +added buck (id 8) +added ted (id 9) +found bob (id 0) +replaced (y) with bob (id 0) +found jack (id 1) +replaced (y) with jack (id 10) +found gary (id 2) +replaced (y) with gary (id 20) +found ty (id 3) +replaced (y) with ty (id 30) +found bo (id 4) +replaced (y) with bo (id 40) +found phil (id 5) +replaced (y) with phil (id 50) +found art (id 6) +replaced (y) with art (id 60) +found gil (id 7) +replaced (y) with gil (id 70) +found buck (id 8) +replaced (y) with buck (id 80) +found ted (id 9) +replaced (y) with ted (id 90) +traversing... +bob (id 0) +jack (id 10) +gary (id 20) +ty (id 30) +bo (id 40) +phil (id 50) +art (id 60) +gil (id 70) +buck (id 80) +ted (id 90) diff --git a/tests/test83.c b/tests/test83.c new file mode 100644 index 000000000..b2140c54d --- /dev/null +++ b/tests/test83.c @@ -0,0 +1,61 @@ +#include "uthash.h" +#include <stdio.h> +#include <stdlib.h> /* malloc */ + +typedef struct person_t { + char first_name[10]; + int id; + UT_hash_handle hh; +} person_t; + +int main() +{ + person_t *people=NULL, *person, *new_person, *tmp; + const char **name; + const char * names[] = { "bob", "jack", "gary", "ty", "bo", "phil", "art", + "gil", "buck", "ted", NULL + }; + int id=0; + + for(name=names; *name!=NULL; name++) { + person = (person_t*)malloc(sizeof(person_t)); + if (person == NULL) { + exit(-1); + } + strcpy(person->first_name, *name); + person->id = id++; + HASH_ADD_STR(people,first_name,person); + printf("added %s (id %d)\n", person->first_name, person->id); + } + + person=NULL; + person_t **p=&person; + + for(name=names; *name!=NULL; name++) { + HASH_FIND_STR(people,*name,*p); + if (person != NULL) { + printf("found %s (id %d)\n", person->first_name, person->id); + new_person = (person_t *)malloc(sizeof(person_t)); + if (new_person == NULL) { + exit(-1); + } + memcpy(new_person, person, sizeof(person_t)); + new_person->id = person->id*10; + HASH_REPLACE_STR(people,first_name,new_person,tmp); + printf("replaced (%c) with %s (id %d)\n", (tmp!=NULL)?'y':'n', new_person->first_name, new_person->id); + if (tmp != NULL) { + free(tmp); + } + } else { + printf("failed to find %s\n", *name); + } + } + + printf("traversing... \n"); + HASH_ITER(hh, people, person, tmp) { + printf("%s (id %d)\n", person->first_name, person->id); + HASH_DEL(people,person); + free(person); + } + return 0; +} diff --git a/tests/test84.ans b/tests/test84.ans new file mode 100644 index 000000000..ada2c442b --- /dev/null +++ b/tests/test84.ans @@ -0,0 +1,41 @@ +added bob (id 0) +added jack (id 1) +added gary (id 2) +added ty (id 3) +added bo (id 4) +added phil (id 5) +added art (id 6) +added gil (id 7) +added buck (id 8) +added ted (id 9) +found bob (id 0) +replaced (y) with bob (id 0) +found jack (id 1) +replaced (y) with jack (id 10) +found gary (id 2) +replaced (y) with gary (id 20) +found ty (id 3) +replaced (y) with ty (id 30) +found bo (id 4) +replaced (y) with bo (id 40) +found phil (id 5) +replaced (y) with phil (id 50) +found art (id 6) +replaced (y) with art (id 60) +found gil (id 7) +replaced (y) with gil (id 70) +found buck (id 8) +replaced (y) with buck (id 80) +found ted (id 9) +replaced (y) with ted (id 90) +traversing... +bob (id 0) +jack (id 10) +gary (id 20) +ty (id 30) +bo (id 40) +phil (id 50) +art (id 60) +gil (id 70) +buck (id 80) +ted (id 90) diff --git a/tests/test84.c b/tests/test84.c new file mode 100644 index 000000000..cbbfdedf7 --- /dev/null +++ b/tests/test84.c @@ -0,0 +1,71 @@ +#include "uthash.h" +#include <stdio.h> +#include <stdlib.h> /* malloc */ + +typedef struct person_t { + char *first_name; + int id; + UT_hash_handle hh; +} person_t; + +int main() +{ + person_t *people=NULL, *person, *new_person, *tmp; + const char **name; + const char * names[] = { "bob", "jack", "gary", "ty", "bo", "phil", "art", + "gil", "buck", "ted", NULL + }; + int id=0; + + for(name=names; *name!=NULL; name++) { + person = (person_t*)malloc(sizeof(person_t)); + if (person == NULL) { + exit(-1); + } + person->first_name = (char*)malloc(10UL); + if (person->first_name == NULL) { + exit(-1); + } + strcpy(person->first_name, *name); + person->id = id++; + HASH_ADD_STR(people,first_name,person); + printf("added %s (id %d)\n", person->first_name, person->id); + } + + person=NULL; + person_t **p=&person; + + for(name=names; *name!=NULL; name++) { + HASH_FIND_STR(people,*name,*p); + if (person != NULL) { + printf("found %s (id %d)\n", person->first_name, person->id); + new_person = (person_t*)malloc(sizeof(person_t)); + if (new_person == NULL) { + exit(-1); + } + new_person->first_name = (char*)malloc(10UL); + if (new_person->first_name == NULL) { + exit(-1); + } + strcpy(new_person->first_name, person->first_name); + new_person->id = person->id*10; + HASH_REPLACE_STR(people,first_name,new_person,tmp); + printf("replaced (%c) with %s (id %d)\n", (tmp!=NULL)?'y':'n', new_person->first_name, new_person->id); + if (tmp != NULL) { + free(tmp->first_name); + free(tmp); + } + } else { + printf("failed to find %s\n", *name); + } + } + + printf("traversing... \n"); + HASH_ITER(hh, people, person, tmp) { + printf("%s (id %d)\n", person->first_name, person->id); + HASH_DEL(people,person); + free(person->first_name); + free(person); + } + return 0; +} diff --git a/tests/test85.ans b/tests/test85.ans new file mode 100644 index 000000000..1a0715f3d --- /dev/null +++ b/tests/test85.ans @@ -0,0 +1,2 @@ +overhead non-zero +overhead zero diff --git a/tests/test85.c b/tests/test85.c new file mode 100644 index 000000000..bb62ca636 --- /dev/null +++ b/tests/test85.c @@ -0,0 +1,35 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +int main() +{ + int i; + example_user_t *user, *users=NULL; + + /* create elements */ + for(i=0; i<10; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + + size_t s = HASH_OVERHEAD(hh,users); + printf("overhead %s\n", (s==0U)?"zero":"non-zero"); + HASH_CLEAR(hh,users); + // should free those elements + // but this test is not concerned with that + s = HASH_OVERHEAD(hh,users); + printf("overhead %s\n", (s==0U)?"zero":"non-zero"); + return 0; +} diff --git a/tests/test86.ans b/tests/test86.ans new file mode 100644 index 000000000..6533053eb --- /dev/null +++ b/tests/test86.ans @@ -0,0 +1,79 @@ +CDL appends +a b c +count = 3 +Test CDL_PREPEND_ELEM d with elt NULL +a b c d +Test CDL_PREPEND_ELEM e before item b +a e b c d +Test CDL_APPEND_ELEM f with elt NULL +f a e b c d +Test CDL_APPEND_ELEM g after item b +f a e b g c d +count = 7 +advancing head pointer +a e b g c d f +a e b g c d f a e b g c d f a e b g c d +a f d c g b e a f d +deleting (b) +a e g c d f +deleting (a) +e g c d f +deleting (c) +e g d f +deleting (g) +e d f +deleting (e) +d f +deleting (d) +f deleting (f) + +DL appends +a b c +count = 3 +Test DL_PREPEND_ELEM d with elt NULL +a b c d +Test DL_PREPEND_ELEM e before item b +a e b c d +Test DL_APPEND_ELEM f with elt NULL +f a e b c d +Test DL_APPEND_ELEM g after item b +f a e b g c d +count = 7 +deleting (b) +f a e g c d +deleting (a) +f e g c d +deleting (c) +f e g d +deleting (g) +f e d +deleting (e) +f d +deleting (d) +f deleting (f) + +LL appends +a b c +count = 3 +Test LL_PREPEND_ELEM d with elt NULL +a b c d +Test LL_PREPEND_ELEM e before item b +a e b c d +Test LL_APPEND_ELEM f with elt NULL +f a e b c d +Test LL_APPEND_ELEM g after item b +f a e b g c d +count = 7 +deleting (b) +f a e g c d +deleting (a) +f e g c d +deleting (c) +f e g d +deleting (g) +f e d +deleting (e) +f d +deleting (d) +f deleting (f) + diff --git a/tests/test86.c b/tests/test86.c new file mode 100644 index 000000000..fb5723f32 --- /dev/null +++ b/tests/test86.c @@ -0,0 +1,296 @@ +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id; + struct el *next, *prev; +} el; + +int main() +{ + int i; + int count; + el els[10], *e; + el *head = NULL; + el *zeroptr = NULL; + for(i=0; i<10; i++) { + els[i].id=(int)'a'+i; + } + + /* test CDL macros */ + printf("CDL appends\n"); + CDL_APPEND(head,&els[0]); + CDL_APPEND(head,&els[1]); + CDL_APPEND(head,&els[2]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + CDL_COUNT(head,e, count); + printf("count = %d\n", count); + + printf("Test CDL_PREPEND_ELEM %c with elt NULL\n", els[3].id); + CDL_PREPEND_ELEM(head, zeroptr, &els[3]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("Test CDL_PREPEND_ELEM %c before item %c\n", els[4].id, els[1].id); + CDL_PREPEND_ELEM(head, &els[1], &els[4]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("Test CDL_APPEND_ELEM %c with elt NULL\n", els[5].id); + CDL_APPEND_ELEM(head, zeroptr, &els[5]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("Test CDL_APPEND_ELEM %c after item %c\n", els[6].id, els[1].id); + CDL_APPEND_ELEM(head, &els[1], &els[6]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + CDL_COUNT(head,e, count); + printf("count = %d\n", count); + + /* point head to head->next */ + printf("advancing head pointer\n"); + head = head->next; + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* follow circular loop a few times */ + for(i=0,e=head; e && i<20; i++,e=e->next) { + printf("%c ", e->id); + } + printf("\n"); + + /* follow circular loop backwards a few times */ + for(i=0,e=head; e && i<10; i++,e=e->prev) { + printf("%c ", e->id); + } + printf("\n"); + + printf("deleting (b)\n"); + CDL_DELETE(head,&els[1]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (a)\n"); + CDL_DELETE(head,&els[0]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (c)\n"); + CDL_DELETE(head,&els[2]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (g)\n"); + CDL_DELETE(head,&els[6]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (e)\n"); + CDL_DELETE(head,&els[4]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (d)\n"); + CDL_DELETE(head,&els[3]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("deleting (f)\n"); + CDL_DELETE(head,&els[5]); + CDL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + /* test DL macros */ + printf("DL appends\n"); + + DL_APPEND(head,&els[0]); + DL_APPEND(head,&els[1]); + DL_APPEND(head,&els[2]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + DL_COUNT(head,e, count); + printf("count = %d\n", count); + + printf("Test DL_PREPEND_ELEM %c with elt NULL\n", els[3].id); + DL_PREPEND_ELEM(head, zeroptr, &els[3]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("Test DL_PREPEND_ELEM %c before item %c\n", els[4].id, els[1].id); + DL_PREPEND_ELEM(head, &els[1], &els[4]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("Test DL_APPEND_ELEM %c with elt NULL\n", els[5].id); + DL_APPEND_ELEM(head, zeroptr, &els[5]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("Test DL_APPEND_ELEM %c after item %c\n", els[6].id, els[1].id); + DL_APPEND_ELEM(head, &els[1], &els[6]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + DL_COUNT(head,e, count); + printf("count = %d\n", count); + + printf("deleting (b)\n"); + DL_DELETE(head,&els[1]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (a)\n"); + DL_DELETE(head,&els[0]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (c)\n"); + DL_DELETE(head,&els[2]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (g)\n"); + DL_DELETE(head,&els[6]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (e)\n"); + DL_DELETE(head,&els[4]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (d)\n"); + DL_DELETE(head,&els[3]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("deleting (f)\n"); + DL_DELETE(head,&els[5]); + DL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + + /* test LL macros */ + printf("LL appends\n"); + + LL_APPEND(head,&els[0]); + LL_APPEND(head,&els[1]); + LL_APPEND(head,&els[2]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + LL_COUNT(head,e, count); + printf("count = %d\n", count); + + printf("Test LL_PREPEND_ELEM %c with elt NULL\n", els[3].id); + LL_PREPEND_ELEM(head, zeroptr, &els[3]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("Test LL_PREPEND_ELEM %c before item %c\n", els[4].id, els[1].id); + LL_PREPEND_ELEM(head, &els[1], &els[4]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("Test LL_APPEND_ELEM %c with elt NULL\n", els[5].id); + LL_APPEND_ELEM(head, zeroptr, &els[5]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("Test LL_APPEND_ELEM %c after item %c\n", els[6].id, els[1].id); + LL_APPEND_ELEM(head, &els[1], &els[6]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + LL_COUNT(head,e, count); + printf("count = %d\n", count); + + printf("deleting (b)\n"); + LL_DELETE(head,&els[1]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (a)\n"); + LL_DELETE(head,&els[0]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (c)\n"); + LL_DELETE(head,&els[2]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (g)\n"); + LL_DELETE(head,&els[6]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (e)\n"); + LL_DELETE(head,&els[4]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + printf("deleting (d)\n"); + LL_DELETE(head,&els[3]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("deleting (f)\n"); + LL_DELETE(head,&els[5]); + LL_FOREACH(head,e) { + printf("%c ", e->id); + } + printf("\n"); + + return 0; +} diff --git a/tests/test87.ans b/tests/test87.ans new file mode 100644 index 000000000..32fc95e09 --- /dev/null +++ b/tests/test87.ans @@ -0,0 +1,78 @@ +1: muh3 +2: muh1 +3: muh5 +5: muh6 +6: muh7 +6: muh9 +8: muh2 +8: muh4 +9: muh10 +10: muh11 +15: muh8 +43: muh12 +### +1: muh3 +2: muh1 +3: muh5 +5: muh6 +6: muh7 +6: muh9 +7: muh12 +8: muh2 +8: muh4 +9: muh10 +10: muh11 +15: muh8 +### +2: muh1 +3: muh5 +5: muh6 +6: muh7 +6: muh9 +7: muh12 +8: muh2 +8: muh4 +9: muh10 +9: muh3 +10: muh11 +15: muh8 +### +2: muh1 +3: muh5 +5: muh6 +6: muh9 +7: muh12 +8: muh2 +8: muh4 +9: muh10 +9: muh3 +10: muh11 +15: muh8 +16: muh7 +### +2: muh1 +3: muh5 +5: muh6 +6: muh9 +7: muh12 +8: muh4 +9: muh10 +9: muh3 +10: muh11 +15: muh8 +16: muh7 +### +2: muh1 +3: muh5 +5: muh6 +6: muh9 +7: muh12 +8: muh4 +8: muh2 +9: muh10 +9: muh3 +10: muh11 +15: muh8 +16: muh7 +### +### diff --git a/tests/test87.c b/tests/test87.c new file mode 100644 index 000000000..c17275ebc --- /dev/null +++ b/tests/test87.c @@ -0,0 +1,116 @@ +#include <assert.h> +#include <stdio.h> +#include "uthash.h" + +typedef struct { + char name[32]; + int weight; + UT_hash_handle hh; +} hstruct_t; + +static int cmpfunc(const hstruct_t *s1, const hstruct_t *s2) +{ + return (s1->weight < s2->weight) ? -1 : (s1->weight > s2->weight); +} + +// Test that CMPFUNC can safely be a macro. +#define CMPFUNC(a,b) cmpfunc(a,b) + +void printtable(const hstruct_t *hTable) +{ + const hstruct_t *search, *tmp; + HASH_ITER(hh, hTable, search, tmp) { + printf("%d: %s\n", search->weight, search->name); + } + printf("###\n"); +} + +void delitem(hstruct_t **hTable, const char *name) +{ + hstruct_t *item; + HASH_FIND_STR(*hTable, name, item); + HASH_DEL(*hTable, item); +} + +int main() +{ + hstruct_t *hTable = NULL; + hstruct_t *replaced = NULL; + unsigned hashvalue; + + hstruct_t tst[] = { + {"muh1", 2, {0}}, + {"muh2", 8, {0}}, + {"muh3", 1, {0}}, + {"muh4", 8, {0}}, + {"muh5", 3, {0}}, + {"muh6", 5, {0}}, + {"muh7", 6, {0}}, + {"muh8", 15, {0}}, + {"muh9", 6, {0}}, + {"muh10", 9, {0}}, + {"muh11", 10, {0}}, + {"muh12", 43, {0}}, + {"muh12", 7, {0}} + }; + + int index; + for (index = 0; index < 11; ++index) { + HASH_ADD_INORDER(hh, hTable, name[0], strlen(tst[index].name), &tst[index], CMPFUNC); + } + + // test HASH_ADD_BYHASHVALUE_INORDER + HASH_VALUE(tst[11].name, strlen(tst[11].name), hashvalue); + HASH_ADD_BYHASHVALUE_INORDER(hh, hTable, name[0], strlen(tst[11].name), hashvalue, &tst[11], CMPFUNC); + + printtable(hTable); + + // replace "43: muh12" with "7: muh12" + HASH_REPLACE_INORDER(hh, hTable, name[0], strlen(tst[11].name), &tst[12], replaced, CMPFUNC); + assert(replaced == &tst[11]); + + printtable(hTable); + + // rehash "1: muh3" to "9: muh3" + tst[2].weight = 9; + HASH_REPLACE_INORDER(hh, hTable, name[0], strlen(tst[2].name), &tst[2], replaced, CMPFUNC); + assert(replaced == &tst[2]); + + printtable(hTable); + + // rehash "6: muh7" to "16: muh7" + tst[6].weight = 16; + HASH_VALUE(&tst[6].name[0], strlen(tst[6].name), hashvalue); + HASH_REPLACE_BYHASHVALUE_INORDER(hh, hTable, name[0], strlen(tst[6].name), hashvalue, &tst[6], replaced, CMPFUNC); + assert(replaced == &tst[6]); + + printtable(hTable); + + // remove "8: muh2"... + HASH_DELETE(hh, hTable, &tst[1]); + + printtable(hTable); + + // ...and then reinsert "8: muh2" + HASH_VALUE(tst[1].name, strlen(tst[1].name), hashvalue); + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, hTable, tst[1].name, strlen(tst[1].name), hashvalue, &tst[1], CMPFUNC); + + printtable(hTable); + + delitem(&hTable, "muh1"); + delitem(&hTable, "muh7"); + delitem(&hTable, "muh3"); + delitem(&hTable, "muh9"); + delitem(&hTable, "muh2"); + delitem(&hTable, "muh11"); + delitem(&hTable, "muh4"); + delitem(&hTable, "muh6"); + delitem(&hTable, "muh5"); + delitem(&hTable, "muh8"); + delitem(&hTable, "muh10"); + delitem(&hTable, "muh12"); + + printtable(hTable); + + return 0; +} diff --git a/tests/test88.ans b/tests/test88.ans new file mode 100644 index 000000000..6f35d6e98 --- /dev/null +++ b/tests/test88.ans @@ -0,0 +1,30 @@ +alt_strlen +alt_strlen +alt_strlen +alt_strlen +alt_strlen +alt_strlen +alt_strlen +alt_strlen +alt_strlen +alt_strlen +alt_strlen +alt_memcmp +alt_strlen +alt_memcmp +alt_strlen +alt_memcmp +alt_strlen +alt_memcmp +alt_strlen +alt_memcmp +alt_strlen +alt_memcmp +alt_strlen +alt_memcmp +alt_strlen +alt_memcmp +alt_strlen +alt_memcmp +alt_strlen +alt_memcmp diff --git a/tests/test88.c b/tests/test88.c new file mode 100644 index 000000000..46f3ee76f --- /dev/null +++ b/tests/test88.c @@ -0,0 +1,68 @@ +#ifdef HASH_FUNCTION +#undef HASH_FUNCTION /* this test's output depends on the pattern of hash collisions */ +#endif + +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +/* This is mostly a copy of test6.c. */ + +#undef uthash_memcmp +#undef uthash_strlen +#define uthash_memcmp(a,b,n) alt_memcmp(a,b,n) +#define uthash_strlen(s) alt_strlen(s) + +typedef struct example_user_t { + char id[3]; + int cookie; + UT_hash_handle hh; +} example_user_t; + +static int alt_memcmp(const void *a, const void *b, size_t n) +{ + puts("alt_memcmp"); + return memcmp(a,b,n); +} + +static size_t alt_strlen(const char *s) +{ + puts("alt_strlen"); + return strlen(s); +} + +int main() +{ + int i; + example_user_t *user, *tmp, *users=NULL; + + /* create elements */ + for (i=0; i<10; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + sprintf(user->id, "%d", i); + user->cookie = i*i; + HASH_ADD_STR(users,id,user); + } + + /* delete each ID */ + for (i=0; i<10; i++) { + char buffer[3]; + sprintf(buffer, "%d", i); + HASH_FIND_STR(users,buffer,tmp); + if (tmp != NULL) { + HASH_DEL(users,tmp); + free(tmp); + } else { + printf("user id %d not found\n", i); + } + } + + /* show the hash */ + for (user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { + printf("user %s, cookie %d\n", user->id, user->cookie); + } + return 0; +} diff --git a/tests/test89.ans b/tests/test89.ans new file mode 100644 index 000000000..8e63ada73 --- /dev/null +++ b/tests/test89.ans @@ -0,0 +1,5 @@ +node #0, timeout: 100 +node #1, timeout: 200 +node #2, timeout: 300 +node #3, timeout: 400 +node #4, timeout: 500 diff --git a/tests/test89.c b/tests/test89.c new file mode 100644 index 000000000..74d7ec488 --- /dev/null +++ b/tests/test89.c @@ -0,0 +1,65 @@ +/* Minified version of code from tinydtls 0.9 */ +/* See https://projects.eclipse.org/projects/iot.tinydtls */ + +#include "utlist.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +typedef int clock_time_t; + +typedef struct netq_t { + struct netq_t *next; + clock_time_t t; +} netq_t; + +void dump_queue(struct netq_t *queue) +{ + struct netq_t *p; + int i = 0; + + if (!queue) { + printf("(null)\n"); + } else { + LL_FOREACH(queue, p) { + printf("node #%d, timeout: %d\n", i++, p->t); + } + } +} + +int netq_insert_node(netq_t **queue, netq_t *node) +{ + netq_t *p = *queue; + while (p && p->t <= node->t) { + p = p->next; + } + /* *INDENT-OFF* */ + if (p) + LL_PREPEND_ELEM(*queue, p, node); + else + LL_APPEND(*queue, node); + /* *INDENT-ON* */ + return 1; +} + +int main() +{ + struct netq_t *nq = NULL; + size_t i; + + clock_time_t timestamps[] = { 300, 100, 200, 400, 500 }; + + for (i = 0; i < sizeof(timestamps)/sizeof(clock_time_t); i++) { + struct netq_t *node = (struct netq_t *)malloc(sizeof *node); + memset(node, '\0', sizeof *node); + node->t = timestamps[i]; + + if (netq_insert_node(&nq, node) != 1) { + puts("ERROR"); + } + } + + dump_queue(nq); + return 0; +} diff --git a/tests/test9.ans b/tests/test9.ans new file mode 100644 index 000000000..13a9402ed --- /dev/null +++ b/tests/test9.ans @@ -0,0 +1,500 @@ +user 0, cookie 0 +user 2, cookie 4 +user 4, cookie 16 +user 6, cookie 36 +user 8, cookie 64 +user 10, cookie 100 +user 12, cookie 144 +user 14, cookie 196 +user 16, cookie 256 +user 18, cookie 324 +user 20, cookie 400 +user 22, cookie 484 +user 24, cookie 576 +user 26, cookie 676 +user 28, cookie 784 +user 30, cookie 900 +user 32, cookie 1024 +user 34, cookie 1156 +user 36, cookie 1296 +user 38, cookie 1444 +user 40, cookie 1600 +user 42, cookie 1764 +user 44, cookie 1936 +user 46, cookie 2116 +user 48, cookie 2304 +user 50, cookie 2500 +user 52, cookie 2704 +user 54, cookie 2916 +user 56, cookie 3136 +user 58, cookie 3364 +user 60, cookie 3600 +user 62, cookie 3844 +user 64, cookie 4096 +user 66, cookie 4356 +user 68, cookie 4624 +user 70, cookie 4900 +user 72, cookie 5184 +user 74, cookie 5476 +user 76, cookie 5776 +user 78, cookie 6084 +user 80, cookie 6400 +user 82, cookie 6724 +user 84, cookie 7056 +user 86, cookie 7396 +user 88, cookie 7744 +user 90, cookie 8100 +user 92, cookie 8464 +user 94, cookie 8836 +user 96, cookie 9216 +user 98, cookie 9604 +user 100, cookie 10000 +user 102, cookie 10404 +user 104, cookie 10816 +user 106, cookie 11236 +user 108, cookie 11664 +user 110, cookie 12100 +user 112, cookie 12544 +user 114, cookie 12996 +user 116, cookie 13456 +user 118, cookie 13924 +user 120, cookie 14400 +user 122, cookie 14884 +user 124, cookie 15376 +user 126, cookie 15876 +user 128, cookie 16384 +user 130, cookie 16900 +user 132, cookie 17424 +user 134, cookie 17956 +user 136, cookie 18496 +user 138, cookie 19044 +user 140, cookie 19600 +user 142, cookie 20164 +user 144, cookie 20736 +user 146, cookie 21316 +user 148, cookie 21904 +user 150, cookie 22500 +user 152, cookie 23104 +user 154, cookie 23716 +user 156, cookie 24336 +user 158, cookie 24964 +user 160, cookie 25600 +user 162, cookie 26244 +user 164, cookie 26896 +user 166, cookie 27556 +user 168, cookie 28224 +user 170, cookie 28900 +user 172, cookie 29584 +user 174, cookie 30276 +user 176, cookie 30976 +user 178, cookie 31684 +user 180, cookie 32400 +user 182, cookie 33124 +user 184, cookie 33856 +user 186, cookie 34596 +user 188, cookie 35344 +user 190, cookie 36100 +user 192, cookie 36864 +user 194, cookie 37636 +user 196, cookie 38416 +user 198, cookie 39204 +user 200, cookie 40000 +user 202, cookie 40804 +user 204, cookie 41616 +user 206, cookie 42436 +user 208, cookie 43264 +user 210, cookie 44100 +user 212, cookie 44944 +user 214, cookie 45796 +user 216, cookie 46656 +user 218, cookie 47524 +user 220, cookie 48400 +user 222, cookie 49284 +user 224, cookie 50176 +user 226, cookie 51076 +user 228, cookie 51984 +user 230, cookie 52900 +user 232, cookie 53824 +user 234, cookie 54756 +user 236, cookie 55696 +user 238, cookie 56644 +user 240, cookie 57600 +user 242, cookie 58564 +user 244, cookie 59536 +user 246, cookie 60516 +user 248, cookie 61504 +user 250, cookie 62500 +user 252, cookie 63504 +user 254, cookie 64516 +user 256, cookie 65536 +user 258, cookie 66564 +user 260, cookie 67600 +user 262, cookie 68644 +user 264, cookie 69696 +user 266, cookie 70756 +user 268, cookie 71824 +user 270, cookie 72900 +user 272, cookie 73984 +user 274, cookie 75076 +user 276, cookie 76176 +user 278, cookie 77284 +user 280, cookie 78400 +user 282, cookie 79524 +user 284, cookie 80656 +user 286, cookie 81796 +user 288, cookie 82944 +user 290, cookie 84100 +user 292, cookie 85264 +user 294, cookie 86436 +user 296, cookie 87616 +user 298, cookie 88804 +user 300, cookie 90000 +user 302, cookie 91204 +user 304, cookie 92416 +user 306, cookie 93636 +user 308, cookie 94864 +user 310, cookie 96100 +user 312, cookie 97344 +user 314, cookie 98596 +user 316, cookie 99856 +user 318, cookie 101124 +user 320, cookie 102400 +user 322, cookie 103684 +user 324, cookie 104976 +user 326, cookie 106276 +user 328, cookie 107584 +user 330, cookie 108900 +user 332, cookie 110224 +user 334, cookie 111556 +user 336, cookie 112896 +user 338, cookie 114244 +user 340, cookie 115600 +user 342, cookie 116964 +user 344, cookie 118336 +user 346, cookie 119716 +user 348, cookie 121104 +user 350, cookie 122500 +user 352, cookie 123904 +user 354, cookie 125316 +user 356, cookie 126736 +user 358, cookie 128164 +user 360, cookie 129600 +user 362, cookie 131044 +user 364, cookie 132496 +user 366, cookie 133956 +user 368, cookie 135424 +user 370, cookie 136900 +user 372, cookie 138384 +user 374, cookie 139876 +user 376, cookie 141376 +user 378, cookie 142884 +user 380, cookie 144400 +user 382, cookie 145924 +user 384, cookie 147456 +user 386, cookie 148996 +user 388, cookie 150544 +user 390, cookie 152100 +user 392, cookie 153664 +user 394, cookie 155236 +user 396, cookie 156816 +user 398, cookie 158404 +user 400, cookie 160000 +user 402, cookie 161604 +user 404, cookie 163216 +user 406, cookie 164836 +user 408, cookie 166464 +user 410, cookie 168100 +user 412, cookie 169744 +user 414, cookie 171396 +user 416, cookie 173056 +user 418, cookie 174724 +user 420, cookie 176400 +user 422, cookie 178084 +user 424, cookie 179776 +user 426, cookie 181476 +user 428, cookie 183184 +user 430, cookie 184900 +user 432, cookie 186624 +user 434, cookie 188356 +user 436, cookie 190096 +user 438, cookie 191844 +user 440, cookie 193600 +user 442, cookie 195364 +user 444, cookie 197136 +user 446, cookie 198916 +user 448, cookie 200704 +user 450, cookie 202500 +user 452, cookie 204304 +user 454, cookie 206116 +user 456, cookie 207936 +user 458, cookie 209764 +user 460, cookie 211600 +user 462, cookie 213444 +user 464, cookie 215296 +user 466, cookie 217156 +user 468, cookie 219024 +user 470, cookie 220900 +user 472, cookie 222784 +user 474, cookie 224676 +user 476, cookie 226576 +user 478, cookie 228484 +user 480, cookie 230400 +user 482, cookie 232324 +user 484, cookie 234256 +user 486, cookie 236196 +user 488, cookie 238144 +user 490, cookie 240100 +user 492, cookie 242064 +user 494, cookie 244036 +user 496, cookie 246016 +user 498, cookie 248004 +user 500, cookie 250000 +user 502, cookie 252004 +user 504, cookie 254016 +user 506, cookie 256036 +user 508, cookie 258064 +user 510, cookie 260100 +user 512, cookie 262144 +user 514, cookie 264196 +user 516, cookie 266256 +user 518, cookie 268324 +user 520, cookie 270400 +user 522, cookie 272484 +user 524, cookie 274576 +user 526, cookie 276676 +user 528, cookie 278784 +user 530, cookie 280900 +user 532, cookie 283024 +user 534, cookie 285156 +user 536, cookie 287296 +user 538, cookie 289444 +user 540, cookie 291600 +user 542, cookie 293764 +user 544, cookie 295936 +user 546, cookie 298116 +user 548, cookie 300304 +user 550, cookie 302500 +user 552, cookie 304704 +user 554, cookie 306916 +user 556, cookie 309136 +user 558, cookie 311364 +user 560, cookie 313600 +user 562, cookie 315844 +user 564, cookie 318096 +user 566, cookie 320356 +user 568, cookie 322624 +user 570, cookie 324900 +user 572, cookie 327184 +user 574, cookie 329476 +user 576, cookie 331776 +user 578, cookie 334084 +user 580, cookie 336400 +user 582, cookie 338724 +user 584, cookie 341056 +user 586, cookie 343396 +user 588, cookie 345744 +user 590, cookie 348100 +user 592, cookie 350464 +user 594, cookie 352836 +user 596, cookie 355216 +user 598, cookie 357604 +user 600, cookie 360000 +user 602, cookie 362404 +user 604, cookie 364816 +user 606, cookie 367236 +user 608, cookie 369664 +user 610, cookie 372100 +user 612, cookie 374544 +user 614, cookie 376996 +user 616, cookie 379456 +user 618, cookie 381924 +user 620, cookie 384400 +user 622, cookie 386884 +user 624, cookie 389376 +user 626, cookie 391876 +user 628, cookie 394384 +user 630, cookie 396900 +user 632, cookie 399424 +user 634, cookie 401956 +user 636, cookie 404496 +user 638, cookie 407044 +user 640, cookie 409600 +user 642, cookie 412164 +user 644, cookie 414736 +user 646, cookie 417316 +user 648, cookie 419904 +user 650, cookie 422500 +user 652, cookie 425104 +user 654, cookie 427716 +user 656, cookie 430336 +user 658, cookie 432964 +user 660, cookie 435600 +user 662, cookie 438244 +user 664, cookie 440896 +user 666, cookie 443556 +user 668, cookie 446224 +user 670, cookie 448900 +user 672, cookie 451584 +user 674, cookie 454276 +user 676, cookie 456976 +user 678, cookie 459684 +user 680, cookie 462400 +user 682, cookie 465124 +user 684, cookie 467856 +user 686, cookie 470596 +user 688, cookie 473344 +user 690, cookie 476100 +user 692, cookie 478864 +user 694, cookie 481636 +user 696, cookie 484416 +user 698, cookie 487204 +user 700, cookie 490000 +user 702, cookie 492804 +user 704, cookie 495616 +user 706, cookie 498436 +user 708, cookie 501264 +user 710, cookie 504100 +user 712, cookie 506944 +user 714, cookie 509796 +user 716, cookie 512656 +user 718, cookie 515524 +user 720, cookie 518400 +user 722, cookie 521284 +user 724, cookie 524176 +user 726, cookie 527076 +user 728, cookie 529984 +user 730, cookie 532900 +user 732, cookie 535824 +user 734, cookie 538756 +user 736, cookie 541696 +user 738, cookie 544644 +user 740, cookie 547600 +user 742, cookie 550564 +user 744, cookie 553536 +user 746, cookie 556516 +user 748, cookie 559504 +user 750, cookie 562500 +user 752, cookie 565504 +user 754, cookie 568516 +user 756, cookie 571536 +user 758, cookie 574564 +user 760, cookie 577600 +user 762, cookie 580644 +user 764, cookie 583696 +user 766, cookie 586756 +user 768, cookie 589824 +user 770, cookie 592900 +user 772, cookie 595984 +user 774, cookie 599076 +user 776, cookie 602176 +user 778, cookie 605284 +user 780, cookie 608400 +user 782, cookie 611524 +user 784, cookie 614656 +user 786, cookie 617796 +user 788, cookie 620944 +user 790, cookie 624100 +user 792, cookie 627264 +user 794, cookie 630436 +user 796, cookie 633616 +user 798, cookie 636804 +user 800, cookie 640000 +user 802, cookie 643204 +user 804, cookie 646416 +user 806, cookie 649636 +user 808, cookie 652864 +user 810, cookie 656100 +user 812, cookie 659344 +user 814, cookie 662596 +user 816, cookie 665856 +user 818, cookie 669124 +user 820, cookie 672400 +user 822, cookie 675684 +user 824, cookie 678976 +user 826, cookie 682276 +user 828, cookie 685584 +user 830, cookie 688900 +user 832, cookie 692224 +user 834, cookie 695556 +user 836, cookie 698896 +user 838, cookie 702244 +user 840, cookie 705600 +user 842, cookie 708964 +user 844, cookie 712336 +user 846, cookie 715716 +user 848, cookie 719104 +user 850, cookie 722500 +user 852, cookie 725904 +user 854, cookie 729316 +user 856, cookie 732736 +user 858, cookie 736164 +user 860, cookie 739600 +user 862, cookie 743044 +user 864, cookie 746496 +user 866, cookie 749956 +user 868, cookie 753424 +user 870, cookie 756900 +user 872, cookie 760384 +user 874, cookie 763876 +user 876, cookie 767376 +user 878, cookie 770884 +user 880, cookie 774400 +user 882, cookie 777924 +user 884, cookie 781456 +user 886, cookie 784996 +user 888, cookie 788544 +user 890, cookie 792100 +user 892, cookie 795664 +user 894, cookie 799236 +user 896, cookie 802816 +user 898, cookie 806404 +user 900, cookie 810000 +user 902, cookie 813604 +user 904, cookie 817216 +user 906, cookie 820836 +user 908, cookie 824464 +user 910, cookie 828100 +user 912, cookie 831744 +user 914, cookie 835396 +user 916, cookie 839056 +user 918, cookie 842724 +user 920, cookie 846400 +user 922, cookie 850084 +user 924, cookie 853776 +user 926, cookie 857476 +user 928, cookie 861184 +user 930, cookie 864900 +user 932, cookie 868624 +user 934, cookie 872356 +user 936, cookie 876096 +user 938, cookie 879844 +user 940, cookie 883600 +user 942, cookie 887364 +user 944, cookie 891136 +user 946, cookie 894916 +user 948, cookie 898704 +user 950, cookie 902500 +user 952, cookie 906304 +user 954, cookie 910116 +user 956, cookie 913936 +user 958, cookie 917764 +user 960, cookie 921600 +user 962, cookie 925444 +user 964, cookie 929296 +user 966, cookie 933156 +user 968, cookie 937024 +user 970, cookie 940900 +user 972, cookie 944784 +user 974, cookie 948676 +user 976, cookie 952576 +user 978, cookie 956484 +user 980, cookie 960400 +user 982, cookie 964324 +user 984, cookie 968256 +user 986, cookie 972196 +user 988, cookie 976144 +user 990, cookie 980100 +user 992, cookie 984064 +user 994, cookie 988036 +user 996, cookie 992016 +user 998, cookie 996004 diff --git a/tests/test9.c b/tests/test9.c new file mode 100644 index 000000000..93dd7db70 --- /dev/null +++ b/tests/test9.c @@ -0,0 +1,37 @@ +#include "uthash.h" +#include <stdlib.h> /* malloc */ +#include <stdio.h> /* printf */ + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +int main() +{ + int i; + example_user_t *user, *tmp, *users=NULL; + + /* create elements */ + for(i=0; i<1000; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + if (user == NULL) { + exit(-1); + } + user->id = i; + user->cookie = i*i; + HASH_ADD_INT(users,id,user); + } + + /* delete each ID */ + for(i=0; i<1000; i+=2) { + HASH_FIND_INT(users,&i,tmp); + if (tmp != NULL) { + printf("user %d, cookie %d\n", tmp->id, tmp->cookie); + } else { + printf("user id %d not found\n", i); + } + } + return 0; +} diff --git a/tests/test90.ans b/tests/test90.ans new file mode 100644 index 000000000..e9d17d7db --- /dev/null +++ b/tests/test90.ans @@ -0,0 +1,2 @@ +filling in is ok +cleanup is ok diff --git a/tests/test90.c b/tests/test90.c new file mode 100644 index 000000000..6fce121ff --- /dev/null +++ b/tests/test90.c @@ -0,0 +1,53 @@ +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include "uthash.h" + +struct item { + unsigned char *sort_field; + size_t sort_field_len; /** Sort field length, in bytes */ + int some_user_data; + UT_hash_handle hh; +}; + +int sort_func(const struct item *a, const struct item *b) +{ + int va = *(int*)(void*)a->sort_field; + int vb = *(int*)(void*)b->sort_field; + return (va < vb) ? -1 : (va > vb); +} + +int main() +{ + size_t i; + struct item *p, *tmp; + int total = 0; + + /** The sorted list */ + struct item *list = NULL; + int counter = 0; + + /* fill in the sorted list */ + for(i=0; i<100; i++) { + p = (struct item *)malloc(sizeof *p); + + p->sort_field_len = sizeof(int); + p->sort_field = (unsigned char *)malloc(p->sort_field_len); + *(int*)(void*)p->sort_field = counter++; + + HASH_ADD_KEYPTR_INORDER(hh, list, p->sort_field, p->sort_field_len, p, sort_func); + } + + printf("filling in is ok\n"); + + HASH_ITER(hh, list, p, tmp) { + total += *(int*)(void*)p->sort_field; + HASH_DEL(list, p); + free(p->sort_field); + free(p); + } + assert(total == 4950); // sum of 0 through 99 + + printf("cleanup is ok\n"); + return 0; +} diff --git a/tests/test91.ans b/tests/test91.ans new file mode 100644 index 000000000..6f21be083 --- /dev/null +++ b/tests/test91.ans @@ -0,0 +1,6 @@ +n g m f l e k d j c i b o h a +DL_INSERT_INORDER +n g m f l e k d j c i b o h a +CDL_INSERT_INORDER +n g m f l e k d j c i b o h a +n a h o b i c j d k e l f m g diff --git a/tests/test91.c b/tests/test91.c new file mode 100644 index 000000000..8c8f63e48 --- /dev/null +++ b/tests/test91.c @@ -0,0 +1,54 @@ +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id, score; + struct el *next, *prev; +} el; + +static int order_desc(el *a, el *b) +{ + return (a->score > b->score) ? -1 : (a->score < b->score); +} + +int main() +{ + int i; + el *head = NULL; + el els[15], *e; + + for (i=0; i<15; i++) { + els[i].id = (int)'a'+i; + els[i].score = i%7; + LL_INSERT_INORDER(head, &els[i], order_desc); + } + LL_FOREACH(head, e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("DL_INSERT_INORDER\n"); + head = NULL; + for (i=0; i<15; i++) { + DL_INSERT_INORDER(head, &els[i], order_desc); + } + DL_FOREACH(head, e) { + printf("%c ", e->id); + } + printf("\n"); + + printf("CDL_INSERT_INORDER\n"); + head = NULL; + for (i=0; i<15; i++) { + CDL_INSERT_INORDER(head, &els[i], order_desc); + } + CDL_FOREACH(head, e) { + printf("%c ", e->id); + } + printf("\n"); + CDL_FOREACH2(head, e, prev) { + printf("%c ", e->id); + } + printf("\n"); + return 0; +} diff --git a/tests/test92.ans b/tests/test92.ans new file mode 100644 index 000000000..528694d82 --- /dev/null +++ b/tests/test92.ans @@ -0,0 +1 @@ +End diff --git a/tests/test92.c b/tests/test92.c new file mode 100644 index 000000000..106819451 --- /dev/null +++ b/tests/test92.c @@ -0,0 +1,245 @@ +#include <stdio.h> + +#define HASH_NONFATAL_OOM 1 + +#include "uthash.h" + +#undef uthash_malloc +#undef uthash_free +#undef uthash_nonfatal_oom +#define uthash_malloc(sz) alt_malloc(sz) +#define uthash_free(ptr,sz) alt_free(ptr) +#define uthash_nonfatal_oom(e) do{(e)->mem_failed=1;}while(0) +#define all_select(a) 1 + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; + UT_hash_handle hh2; + int mem_failed; +} example_user_t; + +static int malloc_cnt = 0; +static int malloc_failed = 0; +static int free_cnt = 0; + +static void *alt_malloc(size_t sz) +{ + if (--malloc_cnt <= 0) { + malloc_failed = 1; + return 0; + } + malloc_failed = 0; + return malloc(sz); +} + +static void alt_free(void *ptr) { + free_cnt++; + free(ptr); +} + +static void complain(int index, example_user_t *users, example_user_t *user) +{ + int expected_frees = (3 - index); + if (users) { + printf("%d: users hash must be empty\n", index); + } + if (user->hh.tbl) { + printf("%d hash table must be empty\n", index); + } + if (free_cnt != expected_frees) { + printf("%d Expected %d frees, only had %d\n", index, expected_frees, free_cnt); + } + if (user->mem_failed != 1) { + printf("%d Expected user->mem_failed(%d) to be 1\n", index, user->mem_failed); + } +} + +int main() +{ + example_user_t *users = NULL; + example_user_t *user = (example_user_t*)malloc(sizeof(example_user_t)); + example_user_t *test; + example_user_t *users2 = NULL; + int id = 0; + int i; + int saved_cnt; + + user->id = id; + +#ifdef HASH_BLOOM + malloc_cnt = 3; // bloom filter must fail + user->mem_failed = 0; + user->hh.tbl = (UT_hash_table*)1; + free_cnt = 0; + HASH_ADD_INT(users, id, user); + complain(1, users, user); +#endif /* HASH_BLOOM */ + + malloc_cnt = 2; // bucket creation must fail + user->mem_failed = 0; + free_cnt = 0; + user->hh.tbl = (UT_hash_table*)1; + HASH_ADD_INT(users, id, user); + complain(2, users, user); + + malloc_cnt = 1; // table creation must fail + user->mem_failed = 0; + free_cnt = 0; + user->hh.tbl = (UT_hash_table*)1; + HASH_ADD_INT(users, id, user); + complain(3, users, user); + + malloc_cnt = 4; // hash must create OK + user->mem_failed = 0; + HASH_ADD_INT(users, id, user); + if (user->mem_failed) { + printf("mem_failed must be 0, not %d\n", user->mem_failed); + } + HASH_FIND_INT(users,&id,test); + if (!test) { + printf("test user ID %d not found\n", id); + } + + if (HASH_COUNT(users) != 1) { + printf("Got HASH_COUNT(users)=%d, should be 1\n", HASH_COUNT(users)); + } + + // let's add users until expansion fails. + malloc_failed = 0; + free_cnt = 0; + malloc_cnt = 1; + for (id = 1; 1; ++id) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + user->id = id; + if (id >= 1000) { + // prevent infinite, or too long of a loop here + puts("too many allocs before memory request"); + break; + } + user->hh.tbl = (UT_hash_table*)1; + HASH_ADD_INT(users, id, user); + if (malloc_failed) { + if (id < 10) { + puts("there is no way your bucket size is <= 10"); + } + + if (user->hh.tbl) { + puts("user->hh.tbl should be NULL after failure"); + } else if (user->mem_failed != 1) { + printf("mem_failed should be 1 after failure, not %d\n", user->mem_failed); + } + + if (free_cnt != 0) { + printf("Expected 0 frees, had %d\n", free_cnt); + } + + // let's make sure all previous IDs are there. + for (i=0; i<id; ++i) { + HASH_FIND_INT(users,&i,test); + if (test == NULL) { + printf("test user ID %d not found\n", i); + } + } + + // let's try to add again, but with mem_failed set to 0 + user->hh.tbl = NULL; + user->mem_failed = 0; + malloc_failed = 0; + HASH_ADD_INT(users, id, user); + if (!malloc_failed) { + puts("malloc should have been attempted"); + } + if (user->hh.tbl) { + puts("user->hh.tbl should be NULL after second failure"); + } else if (user->mem_failed != 1) { + printf("mem_failed should be 1 after second failure, not %d\n", user->mem_failed); + } + + break; + } + } + + // let's test HASH_SELECT. + // let's double the size of the table we've already built. + saved_cnt = id; + + if (HASH_COUNT(users) != (unsigned)saved_cnt) { + printf("Got HASH_COUNT(users)=%d, should be %d\n", HASH_COUNT(users), saved_cnt); + } + + for (i=0; i < saved_cnt; i++) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + user->id = ++id; + malloc_cnt = 20; // don't fail + HASH_ADD_INT(users, id, user); + } + + HASH_ITER(hh, users, user, test) { + user->mem_failed = 0; + } + +// HASH_SELECT calls uthash_nonfatal_oom() with an argument of type (void*). +#undef uthash_nonfatal_oom +#define uthash_nonfatal_oom(e) do{((example_user_t*)e)->mem_failed=1;}while(0) + + malloc_cnt = 0; + free_cnt = 0; + HASH_SELECT(hh2, users2, hh, users, all_select); + if (users2) { + puts("Nothing should have been copied into users2"); + } + HASH_ITER(hh, users, user, test) { + if (user->hh2.tbl) { + printf("User ID %d has tbl at %p\n", user->id, (void*)user->hh2.tbl); + } + if (user->mem_failed != 1) { + printf("User ID %d has mem_failed(%d), should be 1\n", user->id, user->mem_failed); + } + user->mem_failed = 0; + } + + malloc_cnt = 4; + HASH_SELECT(hh2, users2, hh, users, all_select); + + // note about the above. + // we tried to stick up to 1,000 entries into users, + // and the malloc failed after saved_cnt. The bucket threshold must have + // been triggered. We then doubled the amount of entries in user, + // and just ran HASH_SELECT, trying to copy them into users2. + // because the order is different, and because we continue after + // failures, the bucket threshold may get triggered on arbitrary + // elements, depending on the hash function. + + saved_cnt = 0; + HASH_ITER(hh, users, user, test) { + example_user_t * user2; + HASH_FIND(hh2, users2, &user->id, sizeof(int), user2); + if (user2) { + if (!user->hh2.tbl) { + printf("User ID %d has tbl==NULL\n", user->id); + } + if (user->mem_failed != 0) { + printf("User ID %d has mem_failed(%d), expected 0\n", user->id, user->mem_failed); + } + } else { + saved_cnt++; + if (user->hh2.tbl) { + printf("User ID %d has tbl at %p, expected 0\n", user->id, (void*)user->hh2.tbl); + } + if (user->mem_failed != 1) { + printf("User ID %d has mem_failed(%d), expected is 1\n", user->id, user->mem_failed); + } + } + } + + if (saved_cnt + HASH_CNT(hh2, users2) != HASH_COUNT(users)) { + printf("Selected elements : %d + %d != %d\n", + saved_cnt, HASH_CNT(hh2, users2), HASH_COUNT(users)); + } + + puts("End"); + + return 0; +} diff --git a/tests/test93.ans b/tests/test93.ans new file mode 100644 index 000000000..528694d82 --- /dev/null +++ b/tests/test93.ans @@ -0,0 +1 @@ +End diff --git a/tests/test93.c b/tests/test93.c new file mode 100644 index 000000000..4afe7d51e --- /dev/null +++ b/tests/test93.c @@ -0,0 +1,119 @@ +#include <stdio.h> +#include <setjmp.h> + +#define HASH_BLOOM 16 + +#include "uthash.h" + +#undef uthash_malloc +#undef uthash_fatal +#define uthash_malloc(sz) alt_malloc(sz) +#define uthash_fatal(s) alt_fatal(s) + +typedef struct example_user_t { + int id; + int cookie; + UT_hash_handle hh; +} example_user_t; + +static int malloc_cnt = 0; +static int malloc_failed; +static int is_fatal; +static jmp_buf j_buf; +static example_user_t * users; +static int user_id = 0; + +static void *alt_malloc(size_t sz) +{ + if (--malloc_cnt <= 0) { + malloc_failed = 1; + return 0; + } + malloc_failed = 0; + return malloc(sz); +} + +static void alt_fatal(char const * s) { + (void)s; + is_fatal = 1; + longjmp(j_buf, 1); +} + +static example_user_t * init_user(int need_malloc_cnt) { + users = 0; + example_user_t * user = (example_user_t*)malloc(sizeof(example_user_t)); + user->id = user_id; + is_fatal = 0; + malloc_cnt = need_malloc_cnt; + /* printf("adding to hash...\n"); */ + if (!setjmp(j_buf)) { + HASH_ADD_INT(users, id, user); + } + return user; +} + +int main() +{ + +#define init(a) do { \ +} while(0) + + example_user_t * user; + + user = init_user(3); /* bloom filter must fail */ + if (!is_fatal) { + printf("fatal not called after bloom failure\n"); + } + + user = init_user(2); /* bucket creation must fail */ + if (!is_fatal) { + printf("fatal not called after bucket creation failure\n"); + } + + user = init_user(1); /* table creation must fail */ + if (!is_fatal) { + printf("fatal not called after table creation failure\n"); + } + + user = init_user(4); /* hash must create OK */ + if (is_fatal) { + printf("fatal error when creating hash normally\n"); + /* bad idea to continue running */ + return 1; + } + + /* let's add users until expansion fails */ + users = 0; + malloc_cnt = 4; + while (1) { + user = (example_user_t*)malloc(sizeof(example_user_t)); + user->id = user_id; + if (user_id++ == 1000) { + printf("there is no way 1000 iterations didn't require realloc\n"); + break; + } + if (!setjmp(j_buf)) { + HASH_ADD_INT(users, id, user); + } + malloc_cnt = 0; + if (malloc_failed) { + + if (!is_fatal) { + printf("fatal not called after bucket not extended\n"); + } + if (user_id < 10) { + printf("there is no way your bucket size is 10\n"); + } + + /* we can't really do anything, the hash is not in consistent + * state, so assume this is a success. */ + break; + + } + } + + printf("End\n"); + + return 0; + +} diff --git a/tests/test94.ans b/tests/test94.ans new file mode 100644 index 000000000..9ce194240 --- /dev/null +++ b/tests/test94.ans @@ -0,0 +1,13 @@ +LL_INSERT_INORDER +list1: n g m f l e k d j c i b o h a +list2: o h a i b j c k d l e m f n g +DL_INSERT_INORDER +list1: n g m f l e k d j c i b o h a +list2: o h a i b j c k d l e m f n g +CDL_INSERT_INORDER +list1: +n g m f l e k d j c i b o h a +n a h o b i c j d k e l f m g +list2: +o h a i b j c k d l e m f n g +o g n f m e l d k c j b i a h diff --git a/tests/test94.c b/tests/test94.c new file mode 100644 index 000000000..b51acc51b --- /dev/null +++ b/tests/test94.c @@ -0,0 +1,93 @@ +#include <stdio.h> +#include "utlist.h" + +typedef struct el { + int id, score; + struct el *next, *prev; + struct el *next_list2, *prev_list2; +} el; + +static int order_desc(el *a, el *b) +{ + return (a->score > b->score) ? -1 : (a->score < b->score); +} + +static int order_asc(el *a, el *b) +{ + return -order_desc(a, b); +} + +int main() +{ + int i; + el *head = NULL; + el *head2 = NULL; + el els[15], *e; + + for (i=0; i<15; i++) { + els[i].id = (int)'a'+i; + els[i].score = i%7; + LL_INSERT_INORDER(head, &els[i], order_desc); + LL_INSERT_INORDER2(head2, &els[i], order_asc, next_list2); + } + + printf("LL_INSERT_INORDER\n"); + printf("list1: "); + LL_FOREACH(head, e) { + printf("%c ", e->id); + } + printf("\n"); + printf("list2: "); + LL_FOREACH2(head2, e, next_list2) { + printf("%c ", e->id); + } + printf("\n"); + + printf("DL_INSERT_INORDER\n"); + head = NULL; + head2 = NULL; + for (i=0; i<15; i++) { + DL_INSERT_INORDER(head, &els[i], order_desc); + DL_INSERT_INORDER2(head2, &els[i], order_asc, prev_list2, next_list2); + } + + printf("list1: "); + DL_FOREACH(head, e) { + printf("%c ", e->id); + } + printf("\n"); + printf("list2: "); + DL_FOREACH2(head2, e, next_list2) { + printf("%c ", e->id); + } + printf("\n"); + + printf("CDL_INSERT_INORDER\n"); + head = NULL; + head2 = NULL; + for (i=0; i<15; i++) { + CDL_INSERT_INORDER(head, &els[i], order_desc); + CDL_INSERT_INORDER2(head2, &els[i], order_asc, prev_list2, next_list2); + } + printf("list1:\n"); + CDL_FOREACH(head, e) { + printf("%c ", e->id); + } + printf("\n"); + CDL_FOREACH2(head, e, prev) { + printf("%c ", e->id); + } + printf("\n"); + + printf("list2:\n"); + CDL_FOREACH2(head2, e, next_list2) { + printf("%c ", e->id); + } + printf("\n"); + CDL_FOREACH2(head2, e, prev_list2) { + printf("%c ", e->id); + } + printf("\n"); + + return 0; +} diff --git a/tests/test95.ans b/tests/test95.ans new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/test95.ans diff --git a/tests/test95.c b/tests/test95.c new file mode 100644 index 000000000..7e715b582 --- /dev/null +++ b/tests/test95.c @@ -0,0 +1,66 @@ +#include <assert.h> +#include <stddef.h> /* size_t, NULL */ +#include "utstack.h" + +typedef struct el { + int id, score; + struct el *next; + struct el *next2; +} el; + +int main() +{ + el alpha = {1, 100, NULL, NULL}; + el beta = {2, 100, NULL, NULL}; + el gamma = {3, 100, NULL, NULL}; + el delta = {4, 100, NULL, NULL}; + + el *stack1 = NULL; + el *stack2 = NULL; + el *dummy; + int size1; + size_t size2; + + STACK_COUNT(stack1, dummy, size1); assert(size1 == 0); + STACK_COUNT(stack2, dummy, size2); assert(size2 == 0); + assert(STACK_EMPTY(stack1)); + assert(STACK_EMPTY(stack2)); + + STACK_PUSH(stack1, &alpha); + STACK_COUNT(stack1, dummy, size1); assert(size1 == 1); + STACK_PUSH(stack1, &beta); + STACK_COUNT(stack1, dummy, size1); assert(size1 == 2); + STACK_PUSH(stack1, &gamma); + STACK_PUSH2(stack1, &delta, next); + STACK_COUNT(stack1, dummy, size1); assert(size1 == 4); + assert(stack1 == &delta); + + STACK_PUSH2(stack2, &alpha, next2); + assert(stack2 == &alpha); + assert(alpha.next2 == NULL); + STACK_PUSH2(stack2, &delta, next2); + assert(stack2 == &delta); + assert(delta.next2 == &alpha); + STACK_COUNT2(stack2, dummy, size2, next2); assert(size2 == 2); + assert(!STACK_EMPTY(stack2)); + assert(stack2 == &delta); + + assert(!STACK_EMPTY(stack1)); + assert(!STACK_EMPTY(stack2)); + + STACK_POP(stack1, dummy); assert(stack1 == &gamma); assert(dummy == &delta); + STACK_POP(stack1, dummy); assert(stack1 == &beta); assert(dummy == &gamma); + STACK_POP(stack1, dummy); assert(stack1 == &alpha); assert(dummy == &beta); + STACK_COUNT(stack1, dummy, size1); assert(size1 == 1); + STACK_POP(stack1, dummy); assert(stack1 == NULL); assert(dummy == &alpha); + + assert(STACK_TOP(stack2) == &delta); + while (!STACK_EMPTY(stack2)) { + STACK_POP2(stack2, dummy, next2); + } + + assert(STACK_EMPTY(stack1)); + assert(STACK_EMPTY(stack2)); + + return 0; +} diff --git a/tests/threads/Makefile b/tests/threads/Makefile new file mode 100644 index 000000000..01060060a --- /dev/null +++ b/tests/threads/Makefile @@ -0,0 +1,31 @@ +HASHDIR = ../../src +PROGS = test1 test2 + +# Thread support requires compiler-specific options +# ---------------------------------------------------------------------------- +# GNU +CFLAGS += -I$(HASHDIR) -g -pthread +# Solaris (Studio 11) +#CFLAGS = -I$(HASHDIR) -g -mt +# ---------------------------------------------------------------------------- + +ifeq ($(HASH_DEBUG),1) +CFLAGS += -DHASH_DEBUG=1 +endif + +all: $(PROGS) run_tests + +$(PROGS) : $(HASHDIR)/uthash.h + $(CC) $(CPPLFAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(@).c + +debug: + $(MAKE) all HASH_DEBUG=1 + +run_tests: $(PROGS) + perl ../do_tests + +.PHONY: clean + +clean: + rm -f $(PROGS) test*.out + rm -rf test*.dSYM diff --git a/tests/threads/README b/tests/threads/README new file mode 100644 index 000000000..e49a62eed --- /dev/null +++ b/tests/threads/README @@ -0,0 +1,2 @@ +test1: exercise a two-reader, one-writer, rwlock-protected hash. +test2: a template for a nthread, nloop kind of program diff --git a/tests/threads/do_tests b/tests/threads/do_tests new file mode 100755 index 000000000..e6809a157 --- /dev/null +++ b/tests/threads/do_tests @@ -0,0 +1,22 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +my @tests; +for (glob "test*[0-9]") { + push @tests, $_ if -e "$_.ans"; +} + +my $num_failed=0; + +for my $test (@tests) { + `./$test > $test.out 2> $test.err`; + `diff $test.out $test.ans`; + print "$test failed\n" if $?; + $num_failed++ if $?; + unlink "$test.err" if -z "$test.err"; +} + +print scalar @tests . " tests conducted, $num_failed failed.\n"; +exit $num_failed; diff --git a/tests/threads/test1.c b/tests/threads/test1.c new file mode 100644 index 000000000..8d6cb6747 --- /dev/null +++ b/tests/threads/test1.c @@ -0,0 +1,116 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <pthread.h> +#include "uthash.h" + +#undef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) fprintf(stderr,"warning: bucket expansion inhibited\n") + +#define LOOPS 100000 + +typedef struct { + int i; + UT_hash_handle hh; +} elt; + +elt *elts=NULL; /* this is our hash table which two threads will use */ +pthread_rwlock_t lock; + +void *thread_routine_r( void *arg ) { + int i; + long num_found=0; + elt *e; + + for(i=0;i<LOOPS;i++) { + if (pthread_rwlock_rdlock(&lock) != 0) { + fprintf(stderr,"can't acquire read lock\n"); + exit(-1); + } + HASH_FIND_INT(elts, &i, e); + if (e) num_found++; + pthread_rwlock_unlock(&lock); + } + return (void*)num_found; +} +void *thread_routine_w( void *arg ) { + int i; + long num_deld=0; + elt *e; + + for(i=0;i<LOOPS;i++) { + if (pthread_rwlock_wrlock(&lock) != 0) { + fprintf(stderr,"can't acquire write lock\n"); + exit(-1); + } + HASH_FIND_INT(elts, &i, e); + if (e) { + /* HASH_DEL(elts, e); */ + /* num_deld++; */ + } else { + e = malloc(sizeof(elt)); + if (!e) exit(-1); + e->i = i; + HASH_ADD_INT(elts, i, e); + } + pthread_rwlock_unlock(&lock); + } + return (void*)num_deld; +} + +int main() { + unsigned i; + long num_added=0; + int status; + pthread_t thread_r1,thread_r2,thread_w1,thread_w2; + void *thread_result; + elt tmp, *e; + + if (pthread_rwlock_init(&lock,NULL) != 0) { + fprintf(stderr,"lock init failed\n"); + exit(-1); + } + + if (( status = pthread_create( &thread_r1, NULL, thread_routine_r, NULL) )) { + printf("failure: status %d\n", status); + exit(-1); + } + if (( status = pthread_create( &thread_r2, NULL, thread_routine_r, NULL) )) { + printf("failure: status %d\n", status); + exit(-1); + } + if (( status = pthread_create( &thread_w1, NULL, thread_routine_w, NULL) )) { + printf("failure: status %d\n", status); + exit(-1); + } + if (( status = pthread_create( &thread_w2, NULL, thread_routine_w, NULL) )) { + printf("failure: status %d\n", status); + exit(-1); + } + + status = pthread_join( thread_r1, &thread_result ); + printf("thread result: %d %ld\n", status, (long)thread_result); + + status = pthread_join( thread_r2, &thread_result ); + printf("thread result: %d %ld\n", status, (long)thread_result); + + status = pthread_join( thread_w1, &thread_result ); + printf("thread result: %d %ld\n", status, (long)thread_result); + + status = pthread_join( thread_w2, &thread_result ); + printf("thread result: %d %ld\n", status, (long)thread_result); + + i = HASH_COUNT(elts); + printf("final count of items in hash: %u\n", i); + + if (pthread_rwlock_destroy(&lock) != 0) { + fprintf(stderr,"lock destroy failed\n"); + exit(-1); + } +} diff --git a/tests/threads/test2.c b/tests/threads/test2.c new file mode 100644 index 000000000..316b7e699 --- /dev/null +++ b/tests/threads/test2.c @@ -0,0 +1,75 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <pthread.h> +#include "uthash.h" + +#undef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) fprintf(stderr,"warning: bucket expansion inhibited\n"); + +#define LOOPS 100000 +#define NTHREADS 2 + +typedef struct { + int i; + int v; + UT_hash_handle hh; +} elt; + +elt *elts=NULL; /* this is our hash table which two threads will use */ +pthread_rwlock_t lock; + +void *thread_routine( void *arg ) { + int keepgoing=0; + /* TODO write me */ + return NULL; +} + +int main() { + unsigned i; + long num_added=0; + int status; + pthread_t thread[NTHREADS]; + void *thread_result; + elt tmp, *e; + + if (pthread_rwlock_init(&lock,NULL) != 0) { + fprintf(stderr,"lock init failed\n"); + exit(-1); + } + + /* populate it to start */ + for(i=0; i<LOOPS; i++) { + e = malloc(sizeof(elt)); + if (!e) exit(-1); + e->i = i; + e->v = 0; + HASH_ADD_INT(elts, i, e); + } + + for(i=0; i<NTHREADS; i++) { + if (( status = pthread_create( &thread[i], NULL, thread_routine, NULL) )) { + printf("failure: status %d\n", status); + exit(-1); + } + } + + for(i=0; i<NTHREADS; i++) { + status = pthread_join( thread[i], &thread_result ); + printf("thread result: %d %ld\n", status, (long)thread_result); + } + + i = HASH_COUNT(elts); + printf("final count of items in hash: %u\n", i); + + if (pthread_rwlock_destroy(&lock) != 0) { + fprintf(stderr,"lock destroy failed\n"); + exit(-1); + } +} |