├── .github └── workflows │ └── build.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── doc ├── .gitignore ├── ChangeLog.txt ├── Makefile ├── banner.png ├── banner.svg ├── google315d692c9c632ed0.html ├── index.html ├── license.html ├── rss.png ├── styles.css ├── userguide.txt ├── utarray.txt ├── uthash-mini.png ├── uthash-mini.svg ├── uthash.png ├── utlist.txt ├── utringbuffer.txt ├── utstack.txt └── utstring.txt ├── include ├── package.json ├── src ├── utarray.h ├── uthash.h ├── utlist.h ├── utringbuffer.h ├── utstack.h └── utstring.h └── tests ├── Makefile ├── README ├── all_funcs ├── bloom_perf.c ├── bloom_perf.sh ├── do_tests ├── do_tests.cygwin ├── do_tests.mingw ├── do_tests_win32.cmd ├── emit_keys.c ├── example.c ├── hashscan.c ├── keystat.c ├── keystats ├── lru_cache ├── Makefile ├── cache.c ├── cache.h └── main.c ├── simkeys.pl ├── sleep_test.c ├── tdiff.cpp ├── test1.ans ├── test1.c ├── test10.ans ├── test10.c ├── test100.ans ├── test100.c ├── test11.ans ├── test11.c ├── test11.dat ├── test12.ans ├── test12.c ├── test13.ans ├── test13.c ├── test14.ans ├── test14.c ├── test14.dat ├── test15.ans ├── test15.c ├── test16.ans ├── test16.c ├── test17.ans ├── test17.c ├── test18.ans ├── test18.c ├── test19.ans ├── test19.c ├── test2.ans ├── test2.c ├── test20.ans ├── test20.c ├── test21.ans ├── test21.c ├── test22.ans ├── test22.c ├── test23.ans ├── test23.c ├── test24.ans ├── test24.c ├── test25.ans ├── test25.c ├── test26.ans ├── test26.c ├── test27.ans ├── test27.c ├── test28.ans ├── test28.c ├── test29.ans ├── test29.c ├── test3.ans ├── test3.c ├── test30.ans ├── test30.c ├── test31.ans ├── test31.c ├── test32.ans ├── test32.c ├── test33.ans ├── test33.c ├── test34.ans ├── test34.c ├── test35.ans ├── test35.c ├── test36.ans ├── test36.c ├── test37.ans ├── test37.c ├── test38.ans ├── test38.c ├── test39.ans ├── test39.c ├── test4.ans ├── test4.c ├── test40.ans ├── test40.c ├── test41.ans ├── test41.c ├── test42.ans ├── test42.c ├── test43.ans ├── test43.c ├── test44.ans ├── test44.c ├── test45.ans ├── test45.c ├── test46.ans ├── test46.c ├── test47.ans ├── test47.c ├── test48.ans ├── test48.c ├── test49.ans ├── test49.c ├── test5.ans ├── test5.c ├── test50.ans ├── test50.c ├── test51.ans ├── test51.c ├── test52.ans ├── test52.c ├── test53.ans ├── test53.c ├── test54.ans ├── test54.c ├── test55.ans ├── test55.c ├── test56.ans ├── test56.c ├── test57.ans ├── test57.c ├── test58.ans ├── test58.c ├── test59.ans ├── test59.c ├── test6.ans ├── test6.c ├── test60.ans ├── test60.c ├── test61.ans ├── test61.c ├── test62.ans ├── test62.c ├── test63.ans ├── test63.c ├── test64.ans ├── test64.c ├── test65.ans ├── test65.c ├── test65.dat ├── test66.ans ├── test66.c ├── test67.ans ├── test67.c ├── test68.ans ├── test68.c ├── test69.ans ├── test69.c ├── test7.ans ├── test7.c ├── test70.ans ├── test70.c ├── test71.ans ├── test71.c ├── test72.ans ├── test72.c ├── test73.ans ├── test73.c ├── test74.ans ├── test74.c ├── test75.ans ├── test75.c ├── test76.ans ├── test76.c ├── test77.ans ├── test77.c ├── test78.ans ├── test78.c ├── test79.ans ├── test79.c ├── test8.ans ├── test8.c ├── test80.ans ├── test80.c ├── test81.ans ├── test81.c ├── test82.ans ├── test82.c ├── test83.ans ├── test83.c ├── test84.ans ├── test84.c ├── test85.ans ├── test85.c ├── test86.ans ├── test86.c ├── test87.ans ├── test87.c ├── test88.ans ├── test88.c ├── test89.ans ├── test89.c ├── test9.ans ├── test9.c ├── test90.ans ├── test90.c ├── test91.ans ├── test91.c ├── test92.ans ├── test92.c ├── test93.ans ├── test93.c ├── test94.ans ├── test94.c ├── test95.ans ├── test95.c ├── test96.ans ├── test96.c ├── test97.ans ├── test97.c ├── test98.ans ├── test98.c ├── test99.ans ├── test99.c └── threads ├── Makefile ├── README ├── do_tests ├── test1.c └── test2.c /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build # This name shows up in badge.svg 2 | 3 | on: 4 | push: # any branch 5 | pull_request: 6 | branches: [ "master" ] 7 | 8 | jobs: 9 | build-gcc: 10 | strategy: 11 | matrix: 12 | os: [ubuntu-latest, macos-latest] 13 | runs-on: ${{ matrix.os }} 14 | steps: 15 | - uses: actions/checkout@v3 16 | - run: make -C tests EXTRA_CFLAGS="-W -Wall -Wextra -Wswitch-default" 17 | - run: make -C tests clean ; make -C tests pedantic 18 | - run: make -C tests clean ; make -C tests pedantic EXTRA_CFLAGS=-DNO_DECLTYPE 19 | - run: make -C tests clean ; make -C tests cplusplus 20 | - run: make -C tests clean ; make -C tests cplusplus EXTRA_CFLAGS=-DNO_DECLTYPE 21 | build-clang: 22 | strategy: 23 | matrix: 24 | os: [ubuntu-latest, macos-latest] 25 | runs-on: ${{ matrix.os }} 26 | env: 27 | CC: clang 28 | CXX: clang++ 29 | steps: 30 | - uses: actions/checkout@v3 31 | - run: make -C tests EXTRA_CFLAGS="-W -Wall -Wextra -Wswitch-default" 32 | - run: make -C tests clean ; make -C tests pedantic 33 | - run: make -C tests clean ; make -C tests pedantic EXTRA_CFLAGS=-DNO_DECLTYPE 34 | - run: make -C tests clean ; make -C tests cplusplus 35 | - run: make -C tests clean ; make -C tests cplusplus EXTRA_CFLAGS=-DNO_DECLTYPE 36 | build-asciidoc: 37 | runs-on: ubuntu-latest 38 | steps: 39 | - uses: actions/checkout@v3 40 | - run: sudo apt-get update && sudo apt-get install asciidoc -y 41 | - run: make -C doc 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.out 3 | keystat.* 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | matrix: 3 | include: 4 | - os: linux 5 | compiler: gcc 6 | - os: linux 7 | compiler: clang 8 | - os: osx 9 | script: 10 | - make -C tests EXTRA_CFLAGS="-W -Wall -Wextra -Wswitch-default" 11 | - make -C tests clean ; make -C tests pedantic 12 | - make -C tests clean ; make -C tests pedantic EXTRA_CFLAGS=-DNO_DECLTYPE 13 | - make -C tests clean ; make -C tests cplusplus 14 | - make -C tests clean ; make -C tests cplusplus EXTRA_CFLAGS=-DNO_DECLTYPE 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2005-2025, Troy D. Hanson https://troydhanson.github.io/uthash/ 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 11 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 12 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 13 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 14 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 15 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 16 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 17 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 19 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 20 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![Build status](https://api.travis-ci.org/troydhanson/uthash.svg?branch=master)](https://travis-ci.org/troydhanson/uthash) 3 | [![GitHub CI status](https://github.com/troydhanson/uthash/actions/workflows/build.yml/badge.svg)](https://github.com/troydhanson/uthash/actions/workflows/build.yml) 4 | 5 | Documentation for uthash is available at: 6 | 7 | https://troydhanson.github.io/uthash/ 8 | 9 | 10 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | ChangeLog.html 2 | userguide.html 3 | utarray.html 4 | utlist.html 5 | utringbuffer.html 6 | utstack.html 7 | utstring.html 8 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | HTML=$(patsubst %.txt,%.html,$(wildcard *.txt)) 2 | 3 | all: $(HTML) 4 | 5 | # when each target of a multi-target rule has its own prereq 6 | # we use a static pattern rule. 7 | $(HTML): %.html: %.txt 8 | asciidoc -a toc2 $< 9 | 10 | TMP=/tmp/uthash-gh-pages 11 | stage: 12 | mkdir -p ${TMP} 13 | rm -if ${TMP}/* 14 | cp *.html *.css *.png ${TMP} 15 | 16 | .PHONY: clean 17 | clean: 18 | $(RM) $(HTML) 19 | -------------------------------------------------------------------------------- /doc/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/troydhanson/uthash/af6e637f19c102167fb914b9ebcc171389270b48/doc/banner.png -------------------------------------------------------------------------------- /doc/google315d692c9c632ed0.html: -------------------------------------------------------------------------------- 1 | google-site-verification: google315d692c9c632ed0.html -------------------------------------------------------------------------------- /doc/license.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | uthash: a hash table for C structures 8 | 9 | 10 | 11 | 14 | 15 |
16 | uthash home > 17 | BSD license 18 |
19 | 20 |
21 |
22 |
23 |
24 | Copyright (c) 2005-2025, Troy D. Hanson  https://troydhanson.github.io/uthash/
25 | All rights reserved.
26 | 
27 | Redistribution and use in source and binary forms, with or without
28 | modification, are permitted provided that the following conditions are met:
29 | 
30 |     * Redistributions of source code must retain the above copyright
31 |       notice, this list of conditions and the following disclaimer.
32 | 
33 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
34 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
35 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
36 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
37 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
38 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
39 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
40 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
41 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
42 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
43 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 | 
45 |
46 |
47 | 48 |
49 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /doc/rss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/troydhanson/uthash/af6e637f19c102167fb914b9ebcc171389270b48/doc/rss.png -------------------------------------------------------------------------------- /doc/styles.css: -------------------------------------------------------------------------------- 1 | #banner { 2 | /* font-size: x-large; */ 3 | /* background: #ff00ff; */ 4 | /* height: 100px; */ 5 | } 6 | 7 | #topnav { 8 | /* background-image: url(img/grad_topnav.png); */ 9 | /* background-repeat: repeat-y; */ 10 | /* background-color: #af00af; */ 11 | /* height: 25px; */ 12 | margin-top: 5px; 13 | margin-bottom: 10px; 14 | padding: 3px; 15 | font-size: 9pt; 16 | font-family: sans-serif; 17 | /* border-style: solid; */ 18 | /* border-width: 1px; */ 19 | } 20 | 21 | #topnav a { 22 | padding: 8px; 23 | } 24 | 25 | h1,p { margin: 0; } /* non-0 margin on firefox */ 26 | 27 | #mid { 28 | /* background-image: url(img/grad_blue.png); */ 29 | background-repeat: repeat-y; 30 | /* background-color: #ffddaa; */ 31 | padding-top: 20px; 32 | padding-top: 20px; 33 | margin-bottom: 10px; 34 | } 35 | 36 | #mid img { 37 | padding-left: 10px; 38 | vertical-align: middle; 39 | } 40 | 41 | a img { 42 | border: 0 43 | } 44 | 45 | .twitter-share-button { 46 | float: right; 47 | } 48 | 49 | .twitter-follow-button { 50 | padding: 5px; 51 | } 52 | 53 | #nav { 54 | background-color: #fff8f1; 55 | margin-left: 10px; 56 | margin-top: 20px; 57 | margin-right: 20px; 58 | float: left; 59 | padding: 10px; 60 | border-style: solid; 61 | border-width: 2px; 62 | font-family: sans-serif; 63 | } 64 | 65 | 66 | #nav h2 { 67 | font-weight: bold; 68 | font-size: 10pt; 69 | } 70 | 71 | #nav h3 { 72 | /* font-weight: bold; */ 73 | padding-left: 5px; 74 | /* font-style: oblique; */ 75 | font-family: sans-serif; 76 | font-size: 7pt; 77 | } 78 | 79 | #nav div { 80 | font-size: 9pt; 81 | padding-left: 15px; 82 | } 83 | 84 | #main { 85 | background: #ffffff; 86 | margin-top: 20px; 87 | margin-left: 170px; 88 | padding-left: 20px; 89 | height: 100%; 90 | } 91 | 92 | #main h1 { 93 | font-family: sans-serif; 94 | } 95 | 96 | .listing { 97 | margin: 20px; 98 | font-family: sans-serif; 99 | font-weight: bold; 100 | } 101 | 102 | .code { 103 | padding: 10px; 104 | margin: 10px; 105 | font-size: 8pt; 106 | font-weight: normal; 107 | background: #f3f3f3; 108 | width: 100%; 109 | border-style: solid; 110 | border-width: 1px; 111 | } 112 | 113 | #footer { 114 | /* background: #00ffff; */ 115 | margin-top: 5px; 116 | font-size: small; 117 | font-family: sans-serif; 118 | } 119 | 120 | hr { 121 | height: 0.04em; 122 | background: black; 123 | margin: 0 10% 0 0; 124 | } 125 | 126 | #footer { 127 | width: 90%; 128 | } 129 | 130 | #footer img { 131 | margin-right: 5px; 132 | float: right; 133 | } 134 | 135 | #footer #support { 136 | float: right; 137 | } 138 | 139 | body { 140 | width: 80%; 141 | } 142 | -------------------------------------------------------------------------------- /doc/uthash-mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/troydhanson/uthash/af6e637f19c102167fb914b9ebcc171389270b48/doc/uthash-mini.png -------------------------------------------------------------------------------- /doc/uthash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/troydhanson/uthash/af6e637f19c102167fb914b9ebcc171389270b48/doc/uthash.png -------------------------------------------------------------------------------- /include: -------------------------------------------------------------------------------- 1 | src -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "C macros for hash tables and more", 3 | 4 | "keywords": [ 5 | "array", 6 | "data", 7 | "hash", 8 | "list", 9 | "macro", 10 | "string", 11 | "structure", 12 | "uthash" 13 | ], 14 | 15 | "name": "uthash", 16 | "repo": "troydhanson/uthash", 17 | 18 | "src": [ 19 | "src/utarray.h", 20 | "src/uthash.h", 21 | "src/utlist.h", 22 | "src/utringbuffer.h", 23 | "src/utstack.h", 24 | "src/utstring.h" 25 | ], 26 | 27 | "version": "2.3.0" 28 | } 29 | -------------------------------------------------------------------------------- /tests/all_funcs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function proceed { 4 | read -p "proceed ? [n] " response 5 | if [ "$response" != "y" ]; then exit -1; fi 6 | } 7 | 8 | make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_BER'; proceed 9 | make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_FNV'; proceed 10 | make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_JEN'; proceed 11 | make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_OAT'; proceed 12 | make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_SAX'; proceed 13 | make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_SFH'; proceed 14 | -------------------------------------------------------------------------------- /tests/bloom_perf.c: -------------------------------------------------------------------------------- 1 | #include /* malloc */ 2 | #include /* gettimeofday */ 3 | #include /* perror */ 4 | #include /* printf */ 5 | #include "uthash.h" 6 | 7 | #define BUFLEN 20 8 | #if 0 9 | #undef uthash_expand_fyi 10 | #define uthash_expand_fyi(tbl) printf("expanding to %d buckets\n", tbl->num_buckets) 11 | #endif 12 | 13 | typedef struct name_rec { 14 | char boy_name[BUFLEN]; 15 | UT_hash_handle hh; 16 | } name_rec; 17 | 18 | int main(int argc,char *argv[]) 19 | { 20 | name_rec *name, *names=NULL; 21 | char linebuf[BUFLEN]; 22 | FILE *file; 23 | int i=0,j,nloops=3,loopnum=0,miss; 24 | struct timeval tv1,tv2; 25 | long elapsed_usec; 26 | if (argc > 1) { 27 | nloops = atoi(argv[1]); 28 | } 29 | 30 | if ( (file = fopen( "test14.dat", "r" )) == NULL ) { 31 | perror("can't open: "); 32 | exit(-1); 33 | } 34 | 35 | while (fgets(linebuf,BUFLEN,file) != NULL) { 36 | i++; 37 | if ( (name = (name_rec*)malloc(sizeof(name_rec))) == NULL) { 38 | exit(-1); 39 | } 40 | strcpy(name->boy_name, linebuf); 41 | HASH_ADD_STR(names,boy_name,name); 42 | } 43 | 44 | again: 45 | if (fseek(file,0,SEEK_SET) == -1) { 46 | fprintf(stderr,"fseek failed: %s\n", strerror(errno)); 47 | } 48 | j=0; 49 | 50 | if (gettimeofday(&tv1,NULL) == -1) { 51 | perror("gettimeofday: "); 52 | } 53 | while (fgets(linebuf,BUFLEN,file) != NULL) { 54 | /* if we do 10 loops, the first has a 0% miss rate, 55 | * the second has a 10% miss rate, etc */ 56 | miss = ((rand()*1.0/RAND_MAX) < (loopnum*1.0/nloops)) ? 1 : 0; 57 | /* generate a miss if we want one */ 58 | if (miss) { 59 | linebuf[0]++; 60 | if (linebuf[1] != '\0') { 61 | linebuf[1]++; 62 | } 63 | } 64 | HASH_FIND_STR(names,linebuf,name); 65 | if (name) { 66 | j++; 67 | } 68 | } 69 | if (gettimeofday(&tv2,NULL) == -1) { 70 | perror("gettimeofday: "); 71 | } 72 | elapsed_usec = ((tv2.tv_sec - tv1.tv_sec) * 1000000) + (tv2.tv_usec - tv1.tv_usec); 73 | printf("lookup on %d of %d (%.2f%%) names succeeded (%.2f usec)\n", j, i, 74 | j*100.0/i, (double)(elapsed_usec)); 75 | if (++loopnum < nloops) { 76 | goto again; 77 | } 78 | fclose(file); 79 | 80 | return 0; 81 | } 82 | 83 | -------------------------------------------------------------------------------- /tests/bloom_perf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | BITS="16" 4 | 5 | cc -I../src -O3 -Wall -m64 bloom_perf.c -o bloom_perf.none 6 | for bits in $BITS 7 | do 8 | cc -I../src -DHASH_BLOOM=$bits -O3 -Wall -m64 bloom_perf.c -o bloom_perf.$bits 9 | done 10 | 11 | for bits in none $BITS 12 | do 13 | echo 14 | echo "using $bits-bit filter:" 15 | ./bloom_perf.$bits 10 16 | done 17 | 18 | -------------------------------------------------------------------------------- /tests/do_tests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | my @tests; 7 | for (glob "test*[0-9]") { 8 | push @tests, $_ if -e "$_.ans"; 9 | } 10 | 11 | my $num_failed=0; 12 | 13 | for my $test (@tests) { 14 | `./$test > $test.out`; 15 | `diff $test.out $test.ans`; 16 | print "$test failed\n" if $?; 17 | $num_failed++ if $?; 18 | } 19 | 20 | print scalar @tests . " tests conducted, $num_failed failed.\n"; 21 | exit $num_failed; 22 | -------------------------------------------------------------------------------- /tests/do_tests.cygwin: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | my @tests; 7 | for (glob "test*[0-9].exe") { 8 | push @tests, "$_" if -e substr($_, 0, - 4).".ans"; 9 | } 10 | 11 | my $num_failed=0; 12 | 13 | for my $test (@tests) { 14 | `./$test > $test.out`; 15 | my $ansfile = substr($test, 0, - 4).".ans"; 16 | `diff $test.out $ansfile`; 17 | print "$test failed\n" if $?; 18 | $num_failed++ if $?; 19 | } 20 | 21 | print scalar @tests . " tests conducted, $num_failed failed.\n"; 22 | exit $num_failed; 23 | -------------------------------------------------------------------------------- /tests/do_tests.mingw: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "MinGW test script starting" 4 | 5 | for f in test*.exe 6 | do 7 | t=`echo $f | sed s/.exe//` 8 | "./$f" > "$t.out" 9 | diff -qb "$t.out" "$t.ans" 10 | if [ $? -eq 1 ] 11 | then 12 | echo "$f failed" 13 | else 14 | true # can't have empty else 15 | #echo "$f passed" 16 | fi 17 | done 18 | 19 | echo 20 | echo "All tests complete" 21 | -------------------------------------------------------------------------------- /tests/do_tests_win32.cmd: -------------------------------------------------------------------------------- 1 | :: this compiles and runs the test suite under Visual Studio 2008 2 | ::@echo off 3 | call "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat" > vc.out 4 | ::call "C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat" > vc.out 5 | set "COMPILE=cl.exe /I ..\src /EHsc /nologo" 6 | echo compiling... 7 | %COMPILE% tdiff.cpp > compile.out 8 | ::for %%f in (test*.c) do %COMPILE% /Tp %%f >> compile.out 9 | for %%f in (test*.c) do %COMPILE% /Tc %%f >> compile.out 10 | echo running tests... 11 | for %%f in (test*.exe) do %%f > %%~nf.out 12 | echo scanning for failures... 13 | for %%f in (test*.out) do tdiff %%f %%~nf.ans 14 | echo tests completed 15 | ::for %%f in (test*.out test*.obj test*.exe vc.out compile.out tdiff.obj tdiff.exe) do del %%f 16 | pause 17 | -------------------------------------------------------------------------------- /tests/emit_keys.c: -------------------------------------------------------------------------------- 1 | #include /* malloc */ 2 | #include /* perror */ 3 | #include /* printf */ 4 | #include /* write */ 5 | 6 | /* this define must precede uthash.h */ 7 | #define HASH_EMIT_KEYS 1 8 | #include "uthash.h" 9 | 10 | #define BUFLEN 30 11 | 12 | typedef struct name_rec { 13 | char boy_name[BUFLEN]; 14 | UT_hash_handle hh; 15 | } name_rec; 16 | 17 | int main(int argc,char *argv[]) 18 | { 19 | name_rec *name, *names=NULL; 20 | char linebuf[BUFLEN]; 21 | FILE *file; 22 | int i=0; 23 | 24 | if (argc != 2) { 25 | fprintf(stderr,"usage: %s file\n", argv[0]); 26 | exit(-1); 27 | } 28 | 29 | if ( (file = fopen( argv[1], "r" )) == NULL ) { 30 | perror("can't open: "); 31 | exit(-1); 32 | } 33 | 34 | while (fgets(linebuf,BUFLEN,file) != NULL) { 35 | name = (name_rec*)malloc(sizeof(name_rec)); 36 | if (name == NULL) { 37 | exit(-1); 38 | } 39 | strcpy(name->boy_name, linebuf); 40 | HASH_ADD_STR(names,boy_name,name); 41 | i++; 42 | } 43 | 44 | fprintf(stderr,"%d keys emitted.\n", i); 45 | fclose(file); 46 | return 0; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /tests/keystats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | use FindBin; 6 | 7 | sub usage { 8 | print "usage: keystats [-v] keyfile\n"; 9 | print "usage: keystats [-p [-v]] keyfile\n"; 10 | exit -1; 11 | } 12 | 13 | usage if ((@ARGV == 0) or ($ARGV[0] eq '-h')); 14 | 15 | my @exes = glob "'$FindBin::Bin/keystat.???'"; 16 | 17 | my %stats; 18 | for my $exe (@exes) { 19 | $exe =~ s/\ /\\ /g; 20 | $stats{$exe} = `$exe @ARGV`; 21 | delete $stats{$exe} if ($? != 0); # omit hash functions that fail to produce stats (nx) 22 | } 23 | 24 | print( "fcn ideal% #items #buckets dup% fl add_usec find_usec del-all usec\n"); 25 | printf("--- ------ ---------- ---------- ----- -- ---------- ---------- ------------\n"); 26 | for my $exe (sort statsort keys %stats) { 27 | my ($ideal,$items,$bkts,$dups,$ok,$add,$find,$del) = split /,/, $stats{$exe}; 28 | 29 | # convert 0-1 values to percentages 30 | $dups = $items ? (100.0 * $dups / $items) : 0.0; 31 | $ideal = 100.0 * $ideal; 32 | 33 | printf("%3s %5.1f%% %10d %10d %4.0f%% %2s %10d %10d %12d\n", substr($exe,-3,3), 34 | $ideal,$items,$bkts,$dups,$ok,$add,$find,$del); 35 | } 36 | 37 | # sort on hash_q (desc) then by find_usec (asc) 38 | sub statsort { 39 | my @a_stats = split /,/, $stats{$a}; 40 | my @b_stats = split /,/, $stats{$b}; 41 | return ($b_stats[0] <=> $a_stats[0]) || ($a_stats[-1] <=> $b_stats[-1]); 42 | } 43 | -------------------------------------------------------------------------------- /tests/lru_cache/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | 3 | CFLAGS+=-W -Werror -Wall -Wextra -std=c99 \ 4 | -D_FORTIFY_SOURCE=2 -fstack-protector -g \ 5 | -Wformat=2 -pedantic -pedantic-errors \ 6 | -D_GNU_SOURCE=1 -D_BSD_SOURCE=1 \ 7 | -I../../src 8 | 9 | LDFLAGS+=-pthread 10 | 11 | cache: main.o cache.o 12 | $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) main.o cache.o -o cache 13 | 14 | main.o: main.c 15 | $(CC) $(CPPFLAGS) $(CFLAGS) -c main.c -o main.o 16 | 17 | cache.o: cache.c 18 | $(CC) $(CPPFLAGS) $(CFLAGS) -c cache.c -o cache.o 19 | 20 | clean: 21 | rm -f cache *.o 22 | -------------------------------------------------------------------------------- /tests/lru_cache/cache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: cache.h 5 | * 6 | * Description: A simple cache 7 | * 8 | * Version: 1.0 9 | * Created: 04/11/2013 02:30:46 PM 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: Oliver Lorenz (ol), olli@olorenz.org 14 | * Company: https://olorenz.org 15 | * License: This is licensed under the same terms as uthash itself 16 | * 17 | * ===================================================================================== 18 | */ 19 | 20 | #ifndef _CACHE_ 21 | #define _CACHE_ 22 | 23 | struct foo_cache; 24 | 25 | extern int foo_cache_create(struct foo_cache **dst, const size_t capacity, 26 | void (*free_cb) (void *element)); 27 | extern int foo_cache_delete(struct foo_cache *cache, int keep_data); 28 | extern int foo_cache_lookup(struct foo_cache *cache, char *key, void *result); 29 | extern int foo_cache_insert(struct foo_cache *cache, char *key, void *data); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /tests/simkeys.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # This program generates a simkey10.dat (100, 1000, etc) each 4 | # containing 100 random keys of length 10 (100, 1000, etc). 5 | # These files can then be fed into keystats to observe that 6 | # the time to add or find the keys is directly proportional to 7 | # keylength n [in other words, O(n)]. 8 | # 9 | # The conclusion is that really long keys (e.g. 100k) are not 10 | # efficient. TDH 23Jan07 11 | 12 | use strict; 13 | use warnings; 14 | 15 | 16 | #for my $len (10,100,1000,10000,100000,1000000) { 17 | for my $len (100) { 18 | open OUTFILE, ">simkeys$len.dat" or die "can't open: $!\n"; 19 | # we'll do 100 keys of $len 20 | print "keylen $len\n"; 21 | for my $i (0..99) { 22 | my $key = pack "I", $len; 23 | $key .= pack "C", (int(rand(256))) for (1..$len); 24 | print OUTFILE $key; 25 | } 26 | close OUTFILE; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /tests/sleep_test.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | #include /* getpid */ 5 | 6 | typedef struct example_user_t { 7 | int id; 8 | int cookie; 9 | UT_hash_handle hh; 10 | } example_user_t; 11 | 12 | int main() 13 | { 14 | int i; 15 | example_user_t *user, *users=NULL; 16 | 17 | /* create elements */ 18 | for(i=0; i<10000; i++) { 19 | if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) { 20 | exit(-1); 21 | } 22 | user->id = i; 23 | user->cookie = i*i; 24 | HASH_ADD_INT(users,id,user); 25 | } 26 | 27 | printf("pid: %u\n", (unsigned)getpid()); 28 | /* printf("sig: %p\n", &users->hh.tbl->signature); */ 29 | /* printf("bbv: %p\n", &users->hh.tbl->bloom_bv); */ 30 | sleep(60*10); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /tests/tdiff.cpp: -------------------------------------------------------------------------------- 1 | // Windows does not have unix diff so this is a simple replacement 2 | #include 3 | #include 4 | using namespace std; 5 | int main(int argc, char *argv[] ) { 6 | int rc=-1; 7 | if (argc != 3) { 8 | cout << "usage: " << argv[0] << " file1 file2\n"; 9 | return -1; 10 | } 11 | char *file1 = argv[1]; 12 | char *file2 = argv[2]; 13 | ifstream is1(file1, ios::in); 14 | ifstream is2(file2, ios::in); 15 | if (is1.fail()) {cerr << "failed to open " << file1 << "\n"; goto done;} 16 | if (is2.fail()) {cerr << "failed to open " << file2 << "\n"; goto done;} 17 | char d1[256], d2[256]; 18 | do { 19 | is1.read(d1,sizeof(d1)); 20 | is2.read(d2,sizeof(d2)); 21 | if ((is1.gcount() != is2.gcount()) || memcmp(d1,d2,is1.gcount())) { 22 | cout << file1 << " and " << file2 << " differ\n"; 23 | goto done; 24 | } 25 | } while (!is1.eof() && !is2.eof()); 26 | 27 | rc=0; 28 | 29 | done: 30 | is1.close(); 31 | is2.close(); 32 | return rc; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /tests/test1.ans: -------------------------------------------------------------------------------- 1 | user 0, cookie 0 2 | user 1, cookie 1 3 | user 2, cookie 4 4 | user 3, cookie 9 5 | user 4, cookie 16 6 | user 5, cookie 25 7 | user 6, cookie 36 8 | user 7, cookie 49 9 | user 8, cookie 64 10 | user 9, cookie 81 11 | -------------------------------------------------------------------------------- /tests/test1.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct example_user_t { 6 | int id; 7 | int cookie; 8 | UT_hash_handle hh; 9 | } example_user_t; 10 | 11 | int main() 12 | { 13 | int i; 14 | example_user_t *user, *users=NULL; 15 | 16 | /* create elements */ 17 | for(i=0; i<10; i++) { 18 | user = (example_user_t*)malloc(sizeof(example_user_t)); 19 | if (user == NULL) { 20 | exit(-1); 21 | } 22 | user->id = i; 23 | user->cookie = i*i; 24 | HASH_ADD_INT(users,id,user); 25 | } 26 | 27 | for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { 28 | printf("user %d, cookie %d\n", user->id, user->cookie); 29 | } 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /tests/test10.ans: -------------------------------------------------------------------------------- 1 | 9 found in hh 2 | 9 found in alth 3 | 10 not found in hh 4 | 10 found in alth 5 | -------------------------------------------------------------------------------- /tests/test10.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct example_user_t { 6 | int id; 7 | int cookie; 8 | UT_hash_handle hh; 9 | UT_hash_handle alth; 10 | } example_user_t; 11 | 12 | int main() 13 | { 14 | int i; 15 | example_user_t *user, *tmp, *users=NULL, *altusers=NULL; 16 | 17 | /* create elements */ 18 | for(i=0; i<1000; i++) { 19 | user = (example_user_t*)malloc(sizeof(example_user_t)); 20 | if (user == NULL) { 21 | exit(-1); 22 | } 23 | user->id = i; 24 | user->cookie = i*i; 25 | if (i<10) { 26 | HASH_ADD_INT(users,id,user); 27 | } 28 | HASH_ADD(alth,altusers,id,sizeof(int),user); 29 | } 30 | 31 | /* 32 | printf("hh items: %d, alth items: %d\n", 33 | users->hh.tbl->num_items, users->alth.tbl->num_items); 34 | printf("hh buckets: %d, alth buckets: %d\n", 35 | users->hh.tbl->num_buckets, users->alth.tbl->num_buckets); 36 | */ 37 | 38 | i=9; 39 | HASH_FIND_INT(users,&i,tmp); 40 | printf("%d %s in hh\n", i, (tmp != NULL) ? "found" : "not found"); 41 | HASH_FIND(alth,altusers,&i,sizeof(int),tmp); 42 | printf("%d %s in alth\n", i, (tmp != NULL) ? "found" : "not found"); 43 | 44 | i=10; 45 | HASH_FIND_INT(users,&i,tmp); 46 | printf("%d %s in hh\n", i, (tmp != NULL) ? "found" : "not found"); 47 | HASH_FIND(alth,altusers,&i,sizeof(int),tmp); 48 | printf("%d %s in alth\n", i, (tmp != NULL) ? "found" : "not found"); 49 | 50 | HASH_CLEAR(hh, users); 51 | HASH_CLEAR(alth, altusers); 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /tests/test100.ans: -------------------------------------------------------------------------------- 1 | id: 0 dept: A 2 | id: 1 dept: B 3 | id: 2 dept: C 4 | id: 3 dept: D 5 | id: 4 dept: E 6 | id: 25 dept: Z 7 | id: 6 dept: G 8 | id: 7 dept: H 9 | id: 8 dept: I 10 | id: 9 dept: J 11 | -------------------------------------------------------------------------------- /tests/test100.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "utarray.h" 5 | 6 | typedef struct { 7 | int id; 8 | char *dept; 9 | } Data; 10 | 11 | void Data_copy(void* vdst, const void* vsrc) { 12 | Data *dst = (Data*)vdst; 13 | Data *src = (Data*)vsrc; 14 | dst->id = src->id; 15 | dst->dept = strdup(src->dept); 16 | } 17 | 18 | void Data_deinit(void* vdata) { 19 | Data *data = (Data*)vdata; 20 | free(data->dept); 21 | } 22 | 23 | int main(void) { 24 | UT_array *datas; 25 | int i; 26 | Data d, *dp; 27 | char tmp[2] = "A"; 28 | 29 | UT_icd data_icd = {sizeof(Data), NULL, Data_copy, Data_deinit}; 30 | utarray_new(datas, &data_icd); 31 | 32 | for(i = 0; i < 10; i++) { 33 | d.id = i; 34 | d.dept = strdup(tmp); 35 | utarray_push_back(datas, &d); 36 | Data_deinit(&d); 37 | tmp[0] += 1; 38 | } 39 | 40 | d.id = 25; 41 | d.dept = strdup("Z"); 42 | utarray_replace(datas, &d, 5); 43 | Data_deinit(&d); 44 | 45 | for(dp = (Data*)utarray_front(datas); 46 | dp != NULL; 47 | dp = (Data*)utarray_next(datas, dp)) { 48 | printf("id: %d dept: %s\n", dp->id, dp->dept); 49 | } 50 | 51 | utarray_free(datas); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /tests/test11.ans: -------------------------------------------------------------------------------- 1 | ADRIAN 2 | ARNOLDO 3 | CARROLL 4 | CARY 5 | CHONG 6 | CLIFTON 7 | CODY 8 | COLTON 9 | CORNELL 10 | DAMON 11 | DANNIE 12 | DARIO 13 | DONN 14 | DOUG 15 | DOUGLAS 16 | FREDERICK 17 | FRITZ 18 | GERALD 19 | GUS 20 | HARVEY 21 | IRVING 22 | ISAIAH 23 | JARVIS 24 | JOHN 25 | KENTON 26 | LAURENCE 27 | LESTER 28 | LINCOLN 29 | LOWELL 30 | NELSON 31 | NEVILLE 32 | NIGEL 33 | NORMAND 34 | ODIS 35 | OMAR 36 | ORLANDO 37 | RAYMUNDO 38 | REX 39 | ROLANDO 40 | RON 41 | SHANE 42 | TONEY 43 | TRINIDAD 44 | WALTER 45 | WARNER 46 | WARREN 47 | WES 48 | WILLARD 49 | WILLIAM 50 | WINFRED 51 | XAVIER 52 | -------------------------------------------------------------------------------- /tests/test11.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* perror */ 4 | #include /* printf */ 5 | 6 | #define BUFLEN 20 7 | 8 | #if 0 9 | /* Print a message if the hash's no-expand flag is set. */ 10 | #undef uthash_noexpand_fyi 11 | #undef uthash_expand_fyi 12 | #define uthash_noexpand_fyi(tbl) printf("noexpand set\n"); 13 | #define uthash_expand_fyi(tbl) printf("hash expanded\n"); 14 | #endif 15 | 16 | typedef struct name_rec { 17 | char boy_name[BUFLEN]; 18 | UT_hash_handle hh; 19 | } name_rec; 20 | 21 | static int namecmp(void *_a, void *_b) 22 | { 23 | name_rec *a = (name_rec*)_a; 24 | name_rec *b = (name_rec*)_b; 25 | return strcmp(a->boy_name,b->boy_name); 26 | } 27 | 28 | int main() 29 | { 30 | name_rec *name, *names=NULL; 31 | char linebuf[BUFLEN]; 32 | FILE *file; 33 | 34 | file = fopen( "test11.dat", "r" ); 35 | if (file == NULL) { 36 | perror("can't open: "); 37 | exit(-1); 38 | } 39 | 40 | while (fgets(linebuf,BUFLEN,file) != NULL) { 41 | name = (name_rec*)malloc(sizeof(name_rec)); 42 | if (name == NULL) { 43 | exit(-1); 44 | } 45 | strcpy(name->boy_name, linebuf); 46 | HASH_ADD_STR(names,boy_name,name); 47 | } 48 | 49 | fclose(file); 50 | HASH_SORT(names,namecmp); 51 | for(name=names; name!=NULL; name=(name_rec*)(name->hh.next)) { 52 | printf("%s",name->boy_name); 53 | } 54 | 55 | return 0; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /tests/test11.dat: -------------------------------------------------------------------------------- 1 | JOHN 2 | WILLIAM 3 | WALTER 4 | DOUGLAS 5 | GERALD 6 | FREDERICK 7 | WARREN 8 | SHANE 9 | LESTER 10 | RON 11 | HARVEY 12 | ADRIAN 13 | CODY 14 | NELSON 15 | CLIFTON 16 | WILLARD 17 | DOUG 18 | ORLANDO 19 | REX 20 | OMAR 21 | DAMON 22 | LOWELL 23 | IRVING 24 | CARROLL 25 | LAURENCE 26 | ROLANDO 27 | CARY 28 | XAVIER 29 | ISAIAH 30 | GUS 31 | JARVIS 32 | WINFRED 33 | RAYMUNDO 34 | LINCOLN 35 | CORNELL 36 | NIGEL 37 | NORMAND 38 | FRITZ 39 | DONN 40 | TRINIDAD 41 | ODIS 42 | DANNIE 43 | DARIO 44 | KENTON 45 | CHONG 46 | NEVILLE 47 | TONEY 48 | WARNER 49 | WES 50 | COLTON 51 | ARNOLDO 52 | -------------------------------------------------------------------------------- /tests/test12.ans: -------------------------------------------------------------------------------- 1 | added bob (id 0) 2 | added jack (id 1) 3 | added gary (id 2) 4 | added ty (id 3) 5 | added bo (id 4) 6 | added phil (id 5) 7 | added art (id 6) 8 | added gil (id 7) 9 | added buck (id 8) 10 | added ted (id 9) 11 | found bob (id 0) 12 | found jack (id 1) 13 | found gary (id 2) 14 | found ty (id 3) 15 | found bo (id 4) 16 | found phil (id 5) 17 | found art (id 6) 18 | found gil (id 7) 19 | found buck (id 8) 20 | found ted (id 9) 21 | -------------------------------------------------------------------------------- /tests/test12.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include 3 | #include /* malloc */ 4 | 5 | typedef struct person_t { 6 | char first_name[10]; 7 | int id; 8 | UT_hash_handle hh; 9 | } person_t; 10 | 11 | int main() 12 | { 13 | person_t *people=NULL, *person; 14 | const char **name; 15 | const char * names[] = { "bob", "jack", "gary", "ty", "bo", "phil", "art", 16 | "gil", "buck", "ted", NULL 17 | }; 18 | int id=0; 19 | 20 | for(name=names; *name != NULL; name++) { 21 | person = (person_t*)malloc(sizeof(person_t)); 22 | if (person == NULL) { 23 | exit(-1); 24 | } 25 | strcpy(person->first_name, *name); 26 | person->id = id++; 27 | HASH_ADD_STR(people,first_name,person); 28 | printf("added %s (id %d)\n", person->first_name, person->id); 29 | } 30 | 31 | for(name=names; *name != NULL; name++) { 32 | HASH_FIND_STR(people,*name,person); 33 | if (person != NULL) { 34 | printf("found %s (id %d)\n", person->first_name, person->id); 35 | } else { 36 | printf("failed to find %s\n", *name); 37 | } 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /tests/test13.ans: -------------------------------------------------------------------------------- 1 | id 9, following prev... 2 | id 7, following prev... 3 | id 5, following prev... 4 | id 3, following prev... 5 | id 1, following prev... 6 | -------------------------------------------------------------------------------- /tests/test13.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct example_user_t { 6 | int id; 7 | int cookie; 8 | UT_hash_handle hh; 9 | } example_user_t; 10 | 11 | int main() 12 | { 13 | int i; 14 | example_user_t *user, *tmp, *users=NULL; 15 | 16 | /* create elements */ 17 | for(i=0; i<10; i++) { 18 | user = (example_user_t*)malloc(sizeof(example_user_t)); 19 | if (user == NULL) { 20 | exit(-1); 21 | } 22 | user->id = i; 23 | user->cookie = i*i; 24 | HASH_ADD_INT(users,id,user); 25 | } 26 | 27 | /* delete each even ID */ 28 | for(i=0; i<10; i+=2) { 29 | HASH_FIND_INT(users,&i,tmp); 30 | if (tmp != NULL) { 31 | HASH_DEL(users,tmp); 32 | free(tmp); 33 | } else { 34 | printf("user id %d not found\n", i); 35 | } 36 | } 37 | 38 | i=9; 39 | HASH_FIND_INT(users,&i,tmp); 40 | if (tmp != NULL) { 41 | while (tmp != NULL) { 42 | printf("id %d, following prev...\n", tmp->id); 43 | tmp = (example_user_t*)tmp->hh.prev; 44 | } 45 | } else { 46 | printf("user id %d not found\n", i); 47 | } 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /tests/test14.ans: -------------------------------------------------------------------------------- 1 | lookup on 1219 of 1219 names succeeded 2 | -------------------------------------------------------------------------------- /tests/test14.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* perror */ 4 | #include /* printf */ 5 | 6 | #define BUFLEN 20 7 | #if 0 8 | #undef uthash_expand_fyi 9 | #define uthash_expand_fyi(tbl) printf("expanding to %d buckets\n", tbl->num_buckets) 10 | #endif 11 | 12 | typedef struct name_rec { 13 | char boy_name[BUFLEN]; 14 | UT_hash_handle hh; 15 | } name_rec; 16 | 17 | int main() 18 | { 19 | name_rec *name, *names=NULL; 20 | char linebuf[BUFLEN]; 21 | FILE *file; 22 | int i=0,j=0; 23 | 24 | file = fopen( "test14.dat", "r" ); 25 | if (file == NULL ) { 26 | perror("can't open: "); 27 | exit(-1); 28 | } 29 | 30 | while (fgets(linebuf,BUFLEN,file) != NULL) { 31 | i++; 32 | name = (name_rec*)malloc(sizeof(name_rec)); 33 | if (name == NULL) { 34 | exit(-1); 35 | } 36 | strcpy(name->boy_name, linebuf); 37 | HASH_ADD_STR(names,boy_name,name); 38 | } 39 | 40 | fseek(file,0L,SEEK_SET); 41 | 42 | while (fgets(linebuf,BUFLEN,file) != NULL) { 43 | HASH_FIND_STR(names,linebuf,name); 44 | if (!name) { 45 | printf("failed to find: %s", linebuf); 46 | } else { 47 | j++; 48 | } 49 | } 50 | fclose(file); 51 | printf("lookup on %d of %d names succeeded\n", j, i); 52 | return 0; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /tests/test15.ans: -------------------------------------------------------------------------------- 1 | betty's id is 2 2 | -------------------------------------------------------------------------------- /tests/test15.c: -------------------------------------------------------------------------------- 1 | #include /* strcpy */ 2 | #include /* malloc */ 3 | #include /* printf */ 4 | #include "uthash.h" 5 | 6 | struct my_struct { 7 | char name[10]; /* key */ 8 | int id; 9 | UT_hash_handle hh; /* makes this structure hashable */ 10 | }; 11 | 12 | 13 | int main() 14 | { 15 | const char **n, *names[] = { "joe", "bob", "betty", NULL }; 16 | struct my_struct *s, *tmp, *users = NULL; 17 | int i=0; 18 | 19 | for (n = names; *n != NULL; n++) { 20 | s = (struct my_struct*)malloc(sizeof(struct my_struct)); 21 | if (s == NULL) { 22 | exit(-1); 23 | } 24 | strcpy(s->name, *n); 25 | s->id = i++; 26 | HASH_ADD_STR( users, name, s ); 27 | } 28 | 29 | HASH_FIND_STR( users, "betty", s); 30 | if (s != NULL) { 31 | printf("betty's id is %d\n", s->id); 32 | } 33 | 34 | /* free the hash table contents */ 35 | HASH_ITER(hh, users, s, tmp) { 36 | HASH_DEL(users, s); 37 | free(s); 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /tests/test16.ans: -------------------------------------------------------------------------------- 1 | found: user 5, unix time 157680000 2 | -------------------------------------------------------------------------------- /tests/test16.c: -------------------------------------------------------------------------------- 1 | #include /* malloc */ 2 | #include /* offsetof */ 3 | #include /* printf */ 4 | #include /* memset */ 5 | #include "uthash.h" 6 | 7 | struct inner { 8 | int a; 9 | int b; 10 | }; 11 | 12 | struct my_event { 13 | struct inner is; /* key is aggregate of this field */ 14 | char event_code; /* and this field. */ 15 | int user_id; 16 | UT_hash_handle hh; /* makes this structure hashable */ 17 | }; 18 | 19 | 20 | int main() 21 | { 22 | struct my_event *e, ev, *events = NULL; 23 | unsigned keylen; 24 | int i; 25 | 26 | keylen = offsetof(struct my_event, event_code) + sizeof(char) 27 | - offsetof(struct my_event, is); 28 | 29 | for(i = 0; i < 10; i++) { 30 | e = (struct my_event*)malloc(sizeof(struct my_event)); 31 | if (e == NULL) { 32 | exit(-1); 33 | } 34 | memset(e,0,sizeof(struct my_event)); 35 | e->is.a = i * (60*60*24*365); /* i years (sec)*/ 36 | e->is.b = 0; 37 | e->event_code = 'a'+(i%2); /* meaningless */ 38 | e->user_id = i; 39 | 40 | HASH_ADD( hh, events, is, keylen, e); 41 | } 42 | 43 | /* look for one specific event */ 44 | memset(&ev,0,sizeof(struct my_event)); 45 | ev.is.a = 5 * (60*60*24*365); 46 | ev.is.b = 0; 47 | ev.event_code = 'b'; 48 | HASH_FIND( hh, events, &ev.is, keylen , e); 49 | if (e != NULL) { 50 | printf("found: user %d, unix time %d\n", e->user_id, e->is.a); 51 | } 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /tests/test17.ans: -------------------------------------------------------------------------------- 1 | user 9, cookie 81 2 | user 8, cookie 64 3 | user 7, cookie 49 4 | user 6, cookie 36 5 | user 5, cookie 25 6 | user 4, cookie 16 7 | user 3, cookie 9 8 | user 2, cookie 4 9 | user 1, cookie 1 10 | user 0, cookie 0 11 | sorting 12 | called for a:9, b:8 13 | called for a:7, b:6 14 | called for a:5, b:4 15 | called for a:3, b:2 16 | called for a:1, b:0 17 | called for a:8, b:6 18 | called for a:8, b:7 19 | called for a:4, b:2 20 | called for a:4, b:3 21 | called for a:6, b:2 22 | called for a:6, b:3 23 | called for a:6, b:4 24 | called for a:6, b:5 25 | called for a:2, b:0 26 | called for a:2, b:1 27 | user 0, cookie 0 28 | user 1, cookie 1 29 | user 2, cookie 4 30 | user 3, cookie 9 31 | user 4, cookie 16 32 | user 5, cookie 25 33 | user 6, cookie 36 34 | user 7, cookie 49 35 | user 8, cookie 64 36 | user 9, cookie 81 37 | adding 10-20 38 | user 0, cookie 0 39 | user 1, cookie 1 40 | user 2, cookie 4 41 | user 3, cookie 9 42 | user 4, cookie 16 43 | user 5, cookie 25 44 | user 6, cookie 36 45 | user 7, cookie 49 46 | user 8, cookie 64 47 | user 9, cookie 81 48 | user 20, cookie 400 49 | user 19, cookie 361 50 | user 18, cookie 324 51 | user 17, cookie 289 52 | user 16, cookie 256 53 | user 15, cookie 225 54 | user 14, cookie 196 55 | user 13, cookie 169 56 | user 12, cookie 144 57 | user 11, cookie 121 58 | user 10, cookie 100 59 | sorting 60 | called for a:0, b:1 61 | called for a:2, b:3 62 | called for a:4, b:5 63 | called for a:6, b:7 64 | called for a:8, b:9 65 | called for a:20, b:19 66 | called for a:18, b:17 67 | called for a:16, b:15 68 | called for a:14, b:13 69 | called for a:12, b:11 70 | called for a:0, b:2 71 | called for a:1, b:2 72 | called for a:4, b:6 73 | called for a:5, b:6 74 | called for a:8, b:19 75 | called for a:9, b:19 76 | called for a:17, b:15 77 | called for a:17, b:16 78 | called for a:13, b:11 79 | called for a:13, b:12 80 | called for a:0, b:4 81 | called for a:1, b:4 82 | called for a:2, b:4 83 | called for a:3, b:4 84 | called for a:8, b:15 85 | called for a:9, b:15 86 | called for a:19, b:15 87 | called for a:19, b:16 88 | called for a:19, b:17 89 | called for a:19, b:18 90 | called for a:11, b:10 91 | called for a:0, b:8 92 | called for a:1, b:8 93 | called for a:2, b:8 94 | called for a:3, b:8 95 | called for a:4, b:8 96 | called for a:5, b:8 97 | called for a:6, b:8 98 | called for a:7, b:8 99 | called for a:0, b:10 100 | called for a:1, b:10 101 | called for a:2, b:10 102 | called for a:3, b:10 103 | called for a:4, b:10 104 | called for a:5, b:10 105 | called for a:6, b:10 106 | called for a:7, b:10 107 | called for a:8, b:10 108 | called for a:9, b:10 109 | called for a:15, b:10 110 | called for a:15, b:11 111 | called for a:15, b:12 112 | called for a:15, b:13 113 | called for a:15, b:14 114 | user 0, cookie 0 115 | user 1, cookie 1 116 | user 2, cookie 4 117 | user 3, cookie 9 118 | user 4, cookie 16 119 | user 5, cookie 25 120 | user 6, cookie 36 121 | user 7, cookie 49 122 | user 8, cookie 64 123 | user 9, cookie 81 124 | user 10, cookie 100 125 | user 11, cookie 121 126 | user 12, cookie 144 127 | user 13, cookie 169 128 | user 14, cookie 196 129 | user 15, cookie 225 130 | user 16, cookie 256 131 | user 17, cookie 289 132 | user 18, cookie 324 133 | user 19, cookie 361 134 | user 20, cookie 400 135 | -------------------------------------------------------------------------------- /tests/test17.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct example_user_t { 6 | int id; 7 | int cookie; 8 | UT_hash_handle hh; 9 | } example_user_t; 10 | 11 | static int rev(void *_a, void *_b) 12 | { 13 | example_user_t *a = (example_user_t*)_a; 14 | example_user_t *b = (example_user_t*)_b; 15 | printf("called for a:%d, b:%d\n",a->id, b->id); 16 | return (a->id - b->id); 17 | } 18 | 19 | int main() 20 | { 21 | int i; 22 | example_user_t *user, *users=NULL; 23 | 24 | /* create elements */ 25 | for(i=9; i>=0; i--) { 26 | user = (example_user_t*)malloc(sizeof(example_user_t)); 27 | if (user == NULL) { 28 | exit(-1); 29 | } 30 | user->id = i; 31 | user->cookie = i*i; 32 | HASH_ADD_INT(users,id,user); 33 | } 34 | 35 | for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { 36 | printf("user %d, cookie %d\n", user->id, user->cookie); 37 | } 38 | printf("sorting\n"); 39 | HASH_SORT(users,rev); 40 | for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { 41 | printf("user %d, cookie %d\n", user->id, user->cookie); 42 | } 43 | 44 | printf("adding 10-20\n"); 45 | for(i=20; i>=10; i--) { 46 | user = (example_user_t*)malloc(sizeof(example_user_t)); 47 | if (user == NULL) { 48 | exit(-1); 49 | } 50 | user->id = i; 51 | user->cookie = i*i; 52 | HASH_ADD_INT(users,id,user); 53 | } 54 | for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { 55 | printf("user %d, cookie %d\n", user->id, user->cookie); 56 | } 57 | printf("sorting\n"); 58 | HASH_SORT(users,rev); 59 | for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { 60 | printf("user %d, cookie %d\n", user->id, user->cookie); 61 | } 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /tests/test18.ans: -------------------------------------------------------------------------------- 1 | user 0, cookie 0 2 | user 1, cookie 1 3 | user 2, cookie 4 4 | user 3, cookie 9 5 | user 4, cookie 16 6 | user 5, cookie 25 7 | user 6, cookie 36 8 | user 7, cookie 49 9 | user 8, cookie 64 10 | user 9, cookie 81 11 | deleting id 0 12 | deleting id 1 13 | deleting id 2 14 | deleting id 3 15 | deleting id 4 16 | deleting id 5 17 | deleting id 6 18 | deleting id 7 19 | deleting id 8 20 | deleting id 9 21 | -------------------------------------------------------------------------------- /tests/test18.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct example_user_t { 6 | int id; 7 | int cookie; 8 | UT_hash_handle hh; 9 | } example_user_t; 10 | 11 | int main() 12 | { 13 | int i; 14 | example_user_t *user, *users=NULL; 15 | 16 | /* create elements */ 17 | for(i=0; i<10; i++) { 18 | user = (example_user_t*)malloc(sizeof(example_user_t)); 19 | if (user == NULL) { 20 | exit(-1); 21 | } 22 | user->id = i; 23 | user->cookie = i*i; 24 | HASH_ADD_INT(users,id,user); 25 | } 26 | 27 | for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { 28 | printf("user %d, cookie %d\n", user->id, user->cookie); 29 | } 30 | 31 | /* delete them all, pathologically */ 32 | while(users != NULL) { 33 | printf("deleting id %i\n", users->id); 34 | HASH_DEL(users,users); /* single head/deletee var! */ 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /tests/test19.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct example_user_t { 6 | int id; 7 | int cookie; 8 | UT_hash_handle hh; 9 | UT_hash_handle alth; 10 | } example_user_t; 11 | 12 | static int ascending_sort(void *_a, void *_b) 13 | { 14 | example_user_t *a = (example_user_t*)_a; 15 | example_user_t *b = (example_user_t*)_b; 16 | if (a->id == b->id) { 17 | return 0; 18 | } 19 | return (a->id < b->id) ? -1 : 1; 20 | } 21 | 22 | static int descending_sort(void *_a, void *_b) 23 | { 24 | example_user_t *a = (example_user_t*)_a; 25 | example_user_t *b = (example_user_t*)_b; 26 | if (a->id == b->id) { 27 | return 0; 28 | } 29 | return (a->id < b->id) ? 1 : -1; 30 | } 31 | 32 | int main() 33 | { 34 | int i; 35 | example_user_t *user, *users=NULL, *altusers=NULL; 36 | 37 | /* create elements */ 38 | for(i=0; i<1000; i++) { 39 | user = (example_user_t*)malloc(sizeof(example_user_t)); 40 | if (user == NULL) { 41 | exit(-1); 42 | } 43 | user->id = i; 44 | user->cookie = i*i; 45 | if (i<10) { 46 | HASH_ADD_INT(users,id,user); 47 | } 48 | HASH_ADD(alth,altusers,id,sizeof(int),user); 49 | } 50 | 51 | printf("sorting users ascending\n"); 52 | HASH_SRT(hh,users,ascending_sort); 53 | for(user=users; user!=NULL; user=(example_user_t*)user->hh.next) { 54 | printf("user %d\n", user->id); 55 | } 56 | 57 | printf("sorting altusers descending\n"); 58 | HASH_SRT(alth,altusers,descending_sort); 59 | for(user=altusers; user!=NULL; user=(example_user_t*)user->alth.next) { 60 | printf("altuser %d\n", user->id); 61 | } 62 | 63 | /* HASH_FSCK(hh,users); */ 64 | /* HASH_FSCK(alth,altusers); */ 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /tests/test2.ans: -------------------------------------------------------------------------------- 1 | user id 0 found, cookie 0 2 | user id 2 found, cookie 4 3 | user id 4 found, cookie 16 4 | user id 6 found, cookie 36 5 | user id 8 found, cookie 64 6 | -------------------------------------------------------------------------------- /tests/test2.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include 3 | #include /* malloc */ 4 | #include /* printf */ 5 | 6 | typedef struct example_user_t { 7 | int id; 8 | int cookie; 9 | UT_hash_handle hh; 10 | } example_user_t; 11 | 12 | int main() 13 | { 14 | int i; 15 | example_user_t *user, *tmp, *users=NULL; 16 | 17 | /* create elements */ 18 | for(i=0; i<10; i++) { 19 | user = (example_user_t*)malloc(sizeof(example_user_t)); 20 | if (user == NULL) { 21 | exit(-1); 22 | } 23 | user->id = i; 24 | user->cookie = i*i; 25 | HASH_ADD_INT(users,id,user); 26 | } 27 | 28 | /* find each even ID */ 29 | for(i=0; i<10; i+=2) { 30 | HASH_FIND_INT(users,&i,tmp); 31 | if (tmp != NULL) { 32 | printf("user id %d found, cookie %d\n", tmp->id, tmp->cookie); 33 | } else { 34 | printf("user id %d not found\n", i); 35 | } 36 | } 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /tests/test20.ans: -------------------------------------------------------------------------------- 1 | found 2 | -------------------------------------------------------------------------------- /tests/test20.c: -------------------------------------------------------------------------------- 1 | #include /* memcpy */ 2 | #include /* malloc */ 3 | #include /* printf */ 4 | #include "uthash.h" 5 | 6 | struct my_struct { 7 | char bkey[5]; /* "binary" key */ 8 | int data; 9 | UT_hash_handle hh; 10 | }; 11 | 12 | int main() 13 | { 14 | struct my_struct *s, *t, *bins = NULL; 15 | char binary[5] = {'\3','\1','\4','\1','\6'}; 16 | 17 | /* allocate our structure. initialize to some values */ 18 | s = (struct my_struct*)calloc(1UL,sizeof(struct my_struct)); 19 | if (s == NULL) { 20 | exit(-1); 21 | } 22 | memcpy(s->bkey, binary, sizeof(binary)); 23 | 24 | /* add to hash table using general macro */ 25 | HASH_ADD( hh, bins, bkey, sizeof(binary), s); 26 | 27 | /* look up the structure we just added */ 28 | HASH_FIND( hh, bins, binary, sizeof(binary), t ); 29 | 30 | if (t != NULL) { 31 | printf("found\n"); 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /tests/test21.ans: -------------------------------------------------------------------------------- 1 | found a 1 2 | -------------------------------------------------------------------------------- /tests/test21.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "uthash.h" 4 | 5 | typedef struct { 6 | char a; 7 | int b; 8 | } record_key_t; 9 | 10 | typedef struct { 11 | record_key_t key; 12 | /* ... other data ... */ 13 | UT_hash_handle hh; 14 | } record_t; 15 | 16 | int main() 17 | { 18 | record_t l, *p, *r, *tmp, *records = NULL; 19 | 20 | r = (record_t*)malloc( sizeof(record_t) ); 21 | if (r == NULL) { 22 | exit(-1); 23 | } 24 | memset(r, 0, sizeof(record_t)); 25 | r->key.a = 'a'; 26 | r->key.b = 1; 27 | HASH_ADD(hh, records, key, sizeof(record_key_t), r); 28 | 29 | memset(&l, 0, sizeof(record_t)); 30 | l.key.a = 'a'; 31 | l.key.b = 1; 32 | HASH_FIND(hh, records, &l.key, sizeof(record_key_t), p); 33 | 34 | if (p != NULL) { 35 | printf("found %c %d\n", p->key.a, p->key.b); 36 | } 37 | 38 | HASH_ITER(hh, records, p, tmp) { 39 | HASH_DEL(records, p); 40 | free(p); 41 | } 42 | return 0; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /tests/test22.ans: -------------------------------------------------------------------------------- 1 | found 2 | -------------------------------------------------------------------------------- /tests/test22.c: -------------------------------------------------------------------------------- 1 | #include /* malloc */ 2 | #include /* offsetof */ 3 | #include /* printf */ 4 | #include /* memset */ 5 | #include "uthash.h" 6 | 7 | #define UTF32 '\x1' 8 | 9 | typedef struct { 10 | UT_hash_handle hh; 11 | size_t len; 12 | char encoding; /* these two fields */ 13 | int text[]; /* comprise the key */ 14 | } msg_t; 15 | 16 | typedef struct { 17 | char encoding; 18 | int text[]; 19 | } lookup_key_t; 20 | 21 | int main() 22 | { 23 | unsigned keylen; 24 | msg_t *msg, *tmp, *msgs = NULL; 25 | lookup_key_t *lookup_key; 26 | 27 | int beijing[] = {0x5317, 0x4eac}; /* UTF-32LE for 北京 */ 28 | 29 | /* allocate and initialize our structure */ 30 | msg = (msg_t*)malloc( sizeof(msg_t) + sizeof(beijing) ); 31 | if (msg == NULL) { 32 | exit(-1); 33 | } 34 | memset(msg, 0, sizeof(msg_t)+sizeof(beijing)); /* zero fill */ 35 | msg->len = sizeof(beijing); 36 | msg->encoding = UTF32; 37 | memcpy(msg->text, beijing, sizeof(beijing)); 38 | 39 | /* calculate the key length including padding, using formula */ 40 | keylen = offsetof(msg_t, text) /* offset of last key field */ 41 | + sizeof(beijing) /* size of last key field */ 42 | - offsetof(msg_t, encoding); /* offset of first key field */ 43 | 44 | /* add our structure to the hash table */ 45 | HASH_ADD( hh, msgs, encoding, keylen, msg); 46 | 47 | /* look it up to prove that it worked :-) */ 48 | msg=NULL; 49 | 50 | lookup_key = (lookup_key_t*)malloc(sizeof(*lookup_key) + sizeof(beijing)); 51 | if (lookup_key == NULL) { 52 | exit(-1); 53 | } 54 | memset(lookup_key, 0, sizeof(*lookup_key) + sizeof(beijing)); 55 | lookup_key->encoding = UTF32; 56 | memcpy(lookup_key->text, beijing, sizeof(beijing)); 57 | HASH_FIND( hh, msgs, &lookup_key->encoding, keylen, msg ); 58 | if (msg != NULL) { 59 | printf("found \n"); 60 | } 61 | free(lookup_key); 62 | 63 | HASH_ITER(hh, msgs, msg, tmp) { 64 | HASH_DEL(msgs, msg); 65 | free(msg); 66 | } 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /tests/test23.ans: -------------------------------------------------------------------------------- 1 | found 12345 2 | found 6789 3 | found 98765 4 | deleting 12345 5 | deleting 6789 6 | deleting 98765 7 | -------------------------------------------------------------------------------- /tests/test23.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "uthash.h" 4 | 5 | typedef struct { 6 | int key; 7 | int data; 8 | UT_hash_handle hh; 9 | } item; 10 | 11 | int main() 12 | { 13 | item *i, *j, *items=NULL; 14 | int k; 15 | 16 | /* first item */ 17 | k = 12345; 18 | i = (item*)malloc(sizeof(item)); 19 | if (i == NULL) { 20 | exit(-1); 21 | } 22 | i->key = k; 23 | i->data = 0; 24 | HASH_ADD_INT(items,key,i); 25 | 26 | /* second item */ 27 | k = 6789; 28 | i = (item*)malloc(sizeof(item)); 29 | if (i == NULL) { 30 | exit(-1); 31 | } 32 | i->key = k; 33 | i->data = 0; 34 | HASH_ADD_INT(items,key,i); 35 | 36 | /* third item */ 37 | k = 98765; 38 | i = (item*)malloc(sizeof(item)); 39 | if (i == NULL) { 40 | exit(-1); 41 | } 42 | i->key = k; 43 | i->data = 0; 44 | HASH_ADD_INT(items,key,i); 45 | 46 | /* look them all up */ 47 | k = 12345; 48 | HASH_FIND_INT(items, &k, j); 49 | if (j != NULL) { 50 | printf("found %d\n",k); 51 | } 52 | k = 6789; 53 | HASH_FIND_INT(items, &k, j); 54 | if (j != NULL) { 55 | printf("found %d\n",k); 56 | } 57 | k = 98765; 58 | HASH_FIND_INT(items, &k, j); 59 | if (j != NULL) { 60 | printf("found %d\n",k); 61 | } 62 | 63 | /* delete them not the way we prefer but it works */ 64 | for(j=items; j != NULL; j=(item*)j->hh.next) { 65 | printf("deleting %d\n", j->key); 66 | HASH_DEL(items,j); 67 | } 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /tests/test24.ans: -------------------------------------------------------------------------------- 1 | hash contains 10 items 2 | -------------------------------------------------------------------------------- /tests/test24.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct example_user_t { 6 | int id; 7 | int cookie; 8 | UT_hash_handle hh; 9 | } example_user_t; 10 | 11 | int main() 12 | { 13 | int i; 14 | example_user_t *user, *users=NULL; 15 | 16 | /* create elements */ 17 | for(i=0; i<10; i++) { 18 | user = (example_user_t*)malloc(sizeof(example_user_t)); 19 | if (user == NULL) { 20 | exit(-1); 21 | } 22 | user->id = i; 23 | user->cookie = i*i; 24 | HASH_ADD_INT(users,id,user); 25 | } 26 | 27 | printf("hash contains %u items\n", HASH_COUNT(users)); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /tests/test25.ans: -------------------------------------------------------------------------------- 1 | CDL macros 2 | c b a 3 | count = 3 4 | advancing head pointer 5 | b a c 6 | b a c b a c b a c b 7 | b c a b c a b c a b 8 | deleting b 9 | a c 10 | deleting (a) 11 | c 12 | deleting (c) 13 | 14 | DL macros 15 | a b c 16 | count = 3 17 | deleting tail c 18 | a b 19 | deleting head a 20 | b 21 | deleting head b 22 | 23 | LL macros 24 | a b c 25 | count = 3 26 | deleting tail c 27 | a b 28 | deleting head a 29 | b 30 | deleting head b 31 | 32 | -------------------------------------------------------------------------------- /tests/test25.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utlist.h" 3 | 4 | typedef struct el { 5 | int id; 6 | struct el *next, *prev; 7 | } el; 8 | 9 | int main() 10 | { 11 | int i; 12 | int count; 13 | el els[10], *e; 14 | el *head = NULL; 15 | for(i=0; i<10; i++) { 16 | els[i].id=(int)'a'+i; 17 | } 18 | 19 | /* test CDL macros */ 20 | printf("CDL macros\n"); 21 | CDL_PREPEND(head,&els[0]); 22 | CDL_PREPEND(head,&els[1]); 23 | CDL_PREPEND(head,&els[2]); 24 | CDL_FOREACH(head,e) { 25 | printf("%c ", e->id); 26 | } 27 | printf("\n"); 28 | CDL_COUNT(head,e, count); 29 | printf("count = %d\n", count); 30 | 31 | /* point head to head->next */ 32 | printf("advancing head pointer\n"); 33 | head = head->next; 34 | CDL_FOREACH(head,e) { 35 | printf("%c ", e->id); 36 | } 37 | printf("\n"); 38 | 39 | /* follow circular loop a few times */ 40 | for(i=0,e=head; e && i<10; i++,e=e->next) { 41 | printf("%c ", e->id); 42 | } 43 | printf("\n"); 44 | 45 | /* follow circular loop backwards a few times */ 46 | for(i=0,e=head; e && i<10; i++,e=e->prev) { 47 | printf("%c ", e->id); 48 | } 49 | printf("\n"); 50 | 51 | printf("deleting b\n"); 52 | CDL_DELETE(head,&els[1]); 53 | CDL_FOREACH(head,e) { 54 | printf("%c ", e->id); 55 | } 56 | printf("\n"); 57 | printf("deleting (a)\n"); 58 | CDL_DELETE(head,&els[0]); 59 | CDL_FOREACH(head,e) { 60 | printf("%c ", e->id); 61 | } 62 | printf("\n"); 63 | printf("deleting (c)\n"); 64 | CDL_DELETE(head,&els[2]); 65 | CDL_FOREACH(head,e) { 66 | printf("%c ", e->id); 67 | } 68 | printf("\n"); 69 | 70 | /* test DL macros */ 71 | printf("DL macros\n"); 72 | DL_APPEND(head,&els[0]); 73 | DL_APPEND(head,&els[1]); 74 | DL_APPEND(head,&els[2]); 75 | DL_FOREACH(head,e) { 76 | printf("%c ", e->id); 77 | } 78 | printf("\n"); 79 | DL_COUNT(head,e, count); 80 | printf("count = %d\n", count); 81 | 82 | printf("deleting tail c\n"); 83 | DL_DELETE(head,&els[2]); 84 | DL_FOREACH(head,e) { 85 | printf("%c ", e->id); 86 | } 87 | printf("\n"); 88 | 89 | printf("deleting head a\n"); 90 | DL_DELETE(head,&els[0]); 91 | DL_FOREACH(head,e) { 92 | printf("%c ", e->id); 93 | } 94 | printf("\n"); 95 | 96 | printf("deleting head b\n"); 97 | DL_DELETE(head,&els[1]); 98 | DL_FOREACH(head,e) { 99 | printf("%c ", e->id); 100 | } 101 | printf("\n"); 102 | 103 | /* test LL macros */ 104 | printf("LL macros\n"); 105 | LL_APPEND(head,&els[0]); 106 | LL_APPEND(head,&els[1]); 107 | LL_APPEND(head,&els[2]); 108 | LL_FOREACH(head,e) { 109 | printf("%c ", e->id); 110 | } 111 | printf("\n"); 112 | 113 | LL_COUNT(head,e,count); 114 | printf("count = %d\n", count); 115 | 116 | printf("deleting tail c\n"); 117 | LL_DELETE(head,&els[2]); 118 | LL_FOREACH(head,e) { 119 | printf("%c ", e->id); 120 | } 121 | printf("\n"); 122 | 123 | printf("deleting head a\n"); 124 | LL_DELETE(head,&els[0]); 125 | LL_FOREACH(head,e) { 126 | printf("%c ", e->id); 127 | } 128 | printf("\n"); 129 | 130 | printf("deleting head b\n"); 131 | LL_DELETE(head,&els[1]); 132 | LL_FOREACH(head,e) { 133 | printf("%c ", e->id); 134 | } 135 | printf("\n"); 136 | 137 | return 0; 138 | } 139 | -------------------------------------------------------------------------------- /tests/test26.ans: -------------------------------------------------------------------------------- 1 | ADRIAN 2 | ARNOLDO 3 | CARROLL 4 | CARY 5 | CHONG 6 | CLIFTON 7 | CODY 8 | COLTON 9 | CORNELL 10 | DAMON 11 | DANNIE 12 | DARIO 13 | DONN 14 | DOUG 15 | DOUGLAS 16 | FREDERICK 17 | FRITZ 18 | GERALD 19 | GUS 20 | HARVEY 21 | IRVING 22 | ISAIAH 23 | JARVIS 24 | JOHN 25 | KENTON 26 | LAURENCE 27 | LESTER 28 | LINCOLN 29 | LOWELL 30 | NELSON 31 | NEVILLE 32 | NIGEL 33 | NORMAND 34 | ODIS 35 | OMAR 36 | ORLANDO 37 | RAYMUNDO 38 | REX 39 | ROLANDO 40 | RON 41 | SHANE 42 | TONEY 43 | TRINIDAD 44 | WALTER 45 | WARNER 46 | WARREN 47 | WES 48 | WILLARD 49 | WILLIAM 50 | WINFRED 51 | XAVIER 52 | found WES 53 | 54 | -------------------------------------------------------------------------------- /tests/test26.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "utlist.h" 5 | 6 | #define BUFLEN 20 7 | 8 | typedef struct el { 9 | char bname[BUFLEN]; 10 | struct el *next, *prev; 11 | } el; 12 | 13 | static int namecmp(void *_a, void *_b) 14 | { 15 | el *a = (el*)_a; 16 | el *b = (el*)_b; 17 | return strcmp(a->bname,b->bname); 18 | } 19 | 20 | int main() 21 | { 22 | el *name, *elt, *tmp, etmp; 23 | el *head = NULL; /* important- initialize to NULL! */ 24 | 25 | char linebuf[BUFLEN]; 26 | FILE *file; 27 | 28 | file = fopen( "test11.dat", "r" ); 29 | if (file == NULL) { 30 | perror("can't open: "); 31 | exit(-1); 32 | } 33 | 34 | while (fgets(linebuf,BUFLEN,file) != NULL) { 35 | name = (el*)malloc(sizeof(el)); 36 | if (name == NULL) { 37 | exit(-1); 38 | } 39 | strcpy(name->bname, linebuf); 40 | DL_APPEND(head, name); 41 | } 42 | DL_SORT(head, namecmp); 43 | DL_FOREACH(head,elt) { 44 | printf("%s", elt->bname); 45 | } 46 | 47 | memcpy(etmp.bname, "WES\n", 5UL); 48 | DL_SEARCH(head,elt,&etmp,namecmp); 49 | if (elt != NULL) { 50 | printf("found %s\n", elt->bname); 51 | } 52 | 53 | /* now delete each element, use the safe iterator */ 54 | DL_FOREACH_SAFE(head,elt,tmp) { 55 | DL_DELETE(head,elt); 56 | } 57 | 58 | fclose(file); 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /tests/test27.ans: -------------------------------------------------------------------------------- 1 | CDL macros 2 | c b a 3 | advancing head pointer 4 | b a c 5 | b a c b a c b a c b 6 | b c a b c a b c a b 7 | deleting b 8 | a c 9 | deleting head (a) 10 | c 11 | deleting new head (c) 12 | 13 | DL macros 14 | c b a 15 | deleting c 16 | b a 17 | deleting a 18 | b 19 | deleting b 20 | 21 | LL macros 22 | c b a 23 | deleting c 24 | b a 25 | deleting a 26 | b 27 | deleting b 28 | 29 | -------------------------------------------------------------------------------- /tests/test27.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utlist.h" 3 | 4 | typedef struct el { 5 | int id; 6 | struct el *next, *prev; 7 | } el; 8 | 9 | int main() 10 | { 11 | int i; 12 | el els[10], *e; 13 | el *head = NULL; 14 | for(i=0; i<10; i++) { 15 | els[i].id=(int)'a'+i; 16 | } 17 | 18 | /* test CDL macros */ 19 | printf("CDL macros\n"); 20 | CDL_PREPEND(head,&els[0]); 21 | CDL_PREPEND(head,&els[1]); 22 | CDL_PREPEND(head,&els[2]); 23 | CDL_FOREACH(head,e) { 24 | printf("%c ", e->id); 25 | } 26 | printf("\n"); 27 | 28 | /* point head to head->next */ 29 | printf("advancing head pointer\n"); 30 | head = head->next; 31 | CDL_FOREACH(head,e) { 32 | printf("%c ", e->id); 33 | } 34 | printf("\n"); 35 | 36 | /* follow circular loop a few times */ 37 | for(i=0,e=head; e && i<10; i++,e=e->next) { 38 | printf("%c ", e->id); 39 | } 40 | printf("\n"); 41 | 42 | /* follow circular loop backwards a few times */ 43 | for(i=0,e=head; e && i<10; i++,e=e->prev) { 44 | printf("%c ", e->id); 45 | } 46 | printf("\n"); 47 | 48 | printf("deleting b\n"); 49 | CDL_DELETE(head,&els[1]); 50 | CDL_FOREACH(head,e) { 51 | printf("%c ", e->id); 52 | } 53 | printf("\n"); 54 | printf("deleting head (a)\n"); 55 | CDL_DELETE(head,&els[0]); 56 | CDL_FOREACH(head,e) { 57 | printf("%c ", e->id); 58 | } 59 | printf("\n"); 60 | printf("deleting new head (c)\n"); 61 | CDL_DELETE(head,&els[2]); 62 | CDL_FOREACH(head,e) { 63 | printf("%c ", e->id); 64 | } 65 | printf("\n"); 66 | 67 | /* test DL macros */ 68 | printf("DL macros\n"); 69 | DL_PREPEND(head,&els[0]); 70 | DL_PREPEND(head,&els[1]); 71 | DL_PREPEND(head,&els[2]); 72 | DL_FOREACH(head,e) { 73 | printf("%c ", e->id); 74 | } 75 | printf("\n"); 76 | 77 | printf("deleting c\n"); 78 | DL_DELETE(head,&els[2]); 79 | DL_FOREACH(head,e) { 80 | printf("%c ", e->id); 81 | } 82 | printf("\n"); 83 | 84 | printf("deleting a\n"); 85 | DL_DELETE(head,&els[0]); 86 | DL_FOREACH(head,e) { 87 | printf("%c ", e->id); 88 | } 89 | printf("\n"); 90 | 91 | printf("deleting b\n"); 92 | DL_DELETE(head,&els[1]); 93 | DL_FOREACH(head,e) { 94 | printf("%c ", e->id); 95 | } 96 | printf("\n"); 97 | 98 | /* test LL macros */ 99 | printf("LL macros\n"); 100 | LL_PREPEND(head,&els[0]); 101 | LL_PREPEND(head,&els[1]); 102 | LL_PREPEND(head,&els[2]); 103 | LL_FOREACH(head,e) { 104 | printf("%c ", e->id); 105 | } 106 | printf("\n"); 107 | 108 | printf("deleting c\n"); 109 | LL_DELETE(head,&els[2]); 110 | LL_FOREACH(head,e) { 111 | printf("%c ", e->id); 112 | } 113 | printf("\n"); 114 | 115 | printf("deleting a\n"); 116 | LL_DELETE(head,&els[0]); 117 | LL_FOREACH(head,e) { 118 | printf("%c ", e->id); 119 | } 120 | printf("\n"); 121 | 122 | printf("deleting b\n"); 123 | LL_DELETE(head,&els[1]); 124 | LL_FOREACH(head,e) { 125 | printf("%c ", e->id); 126 | } 127 | printf("\n"); 128 | 129 | return 0; 130 | } 131 | -------------------------------------------------------------------------------- /tests/test28.ans: -------------------------------------------------------------------------------- 1 | CDL macros 2 | d c b a 3 | advancing head pointer 4 | c b a d 5 | c b a d c b a d c b 6 | c d a b c d a b c d 7 | deleting b 8 | c a d 9 | deleting (a) 10 | c d 11 | deleting (c) 12 | d 13 | deleting (d) 14 | 15 | DL macros 16 | c b a d 17 | deleting c 18 | b a d 19 | deleting a 20 | b d 21 | deleting b 22 | d 23 | deleting d 24 | 25 | LL macros 26 | c b a d 27 | deleting c 28 | b a d 29 | deleting a 30 | b d 31 | deleting b 32 | d 33 | deleting d 34 | 35 | -------------------------------------------------------------------------------- /tests/test29.ans: -------------------------------------------------------------------------------- 1 | ADRIAN 2 | ARNOLDO 3 | CARROLL 4 | CARY 5 | CHONG 6 | CLIFTON 7 | CODY 8 | COLTON 9 | CORNELL 10 | DAMON 11 | DANNIE 12 | DARIO 13 | DONN 14 | DOUG 15 | DOUGLAS 16 | FREDERICK 17 | FRITZ 18 | GERALD 19 | GUS 20 | HARVEY 21 | IRVING 22 | ISAIAH 23 | JARVIS 24 | JOHN 25 | KENTON 26 | LAURENCE 27 | LESTER 28 | LINCOLN 29 | LOWELL 30 | NELSON 31 | NEVILLE 32 | NIGEL 33 | NORMAND 34 | ODIS 35 | OMAR 36 | ORLANDO 37 | RAYMUNDO 38 | REX 39 | ROLANDO 40 | RON 41 | SHANE 42 | TONEY 43 | TRINIDAD 44 | WALTER 45 | WARNER 46 | WARREN 47 | WES 48 | WILLARD 49 | WILLIAM 50 | WINFRED 51 | XAVIER 52 | deleting head ADRIAN 53 | head->prev: XAVIER 54 | ARNOLDO 55 | CARROLL 56 | CARY 57 | CHONG 58 | CLIFTON 59 | CODY 60 | COLTON 61 | CORNELL 62 | DAMON 63 | DANNIE 64 | DARIO 65 | DONN 66 | DOUG 67 | DOUGLAS 68 | FREDERICK 69 | FRITZ 70 | GERALD 71 | GUS 72 | HARVEY 73 | IRVING 74 | ISAIAH 75 | JARVIS 76 | JOHN 77 | KENTON 78 | LAURENCE 79 | LESTER 80 | LINCOLN 81 | LOWELL 82 | NELSON 83 | NEVILLE 84 | NIGEL 85 | NORMAND 86 | ODIS 87 | OMAR 88 | ORLANDO 89 | RAYMUNDO 90 | REX 91 | ROLANDO 92 | RON 93 | SHANE 94 | TONEY 95 | TRINIDAD 96 | WALTER 97 | WARNER 98 | WARREN 99 | WES 100 | WILLARD 101 | WILLIAM 102 | WINFRED 103 | XAVIER 104 | -------------------------------------------------------------------------------- /tests/test29.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "utlist.h" 5 | 6 | #define BUFLEN 20 7 | 8 | typedef struct el { 9 | char bname[BUFLEN]; 10 | struct el *next, *prev; 11 | } el; 12 | 13 | static int namecmp(void *_a, void *_b) 14 | { 15 | el *a = (el*)_a; 16 | el *b = (el*)_b; 17 | return strcmp(a->bname,b->bname); 18 | } 19 | 20 | int main() 21 | { 22 | el *name, *tmp; 23 | el *head = NULL; 24 | 25 | char linebuf[BUFLEN]; 26 | FILE *file; 27 | 28 | file = fopen( "test11.dat", "r" ); 29 | if (file == NULL) { 30 | perror("can't open: "); 31 | exit(-1); 32 | } 33 | 34 | while (fgets(linebuf,BUFLEN,file) != NULL) { 35 | name = (el*)malloc(sizeof(el)); 36 | if (name == NULL) { 37 | exit(-1); 38 | } 39 | strcpy(name->bname, linebuf); 40 | DL_APPEND(head, name); 41 | } 42 | DL_SORT(head, namecmp); 43 | DL_FOREACH(head,tmp) { 44 | printf("%s", tmp->bname); 45 | } 46 | 47 | /* now delete the list head */ 48 | printf("deleting head %shead->prev: %s", head->bname, head->prev->bname); 49 | DL_DELETE(head,head); 50 | DL_FOREACH(head,tmp) { 51 | printf("%s", tmp->bname); 52 | } 53 | 54 | fclose(file); 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /tests/test3.ans: -------------------------------------------------------------------------------- 1 | user 1, cookie 1 2 | user 3, cookie 9 3 | user 5, cookie 25 4 | user 7, cookie 49 5 | user 9, cookie 81 6 | -------------------------------------------------------------------------------- /tests/test3.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct example_user_t { 6 | int id; 7 | int cookie; 8 | UT_hash_handle hh; 9 | } example_user_t; 10 | 11 | int main() 12 | { 13 | int i; 14 | example_user_t *user, *tmp, *users=NULL; 15 | 16 | /* create elements */ 17 | for(i=0; i<10; i++) { 18 | user = (example_user_t*)malloc(sizeof(example_user_t)); 19 | if (user == NULL) { 20 | exit(-1); 21 | } 22 | user->id = i; 23 | user->cookie = i*i; 24 | HASH_ADD_INT(users,id,user); 25 | } 26 | 27 | /* delete each even ID */ 28 | for(i=0; i<10; i+=2) { 29 | HASH_FIND_INT(users,&i,tmp); 30 | if (tmp != NULL) { 31 | HASH_DEL(users,tmp); 32 | free(tmp); 33 | } else { 34 | printf("user id %d not found\n", i); 35 | } 36 | } 37 | 38 | /* show the hash */ 39 | for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { 40 | printf("user %d, cookie %d\n", user->id, user->cookie); 41 | } 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /tests/test30.ans: -------------------------------------------------------------------------------- 1 | ADRIAN 2 | ARNOLDO 3 | CARROLL 4 | CARY 5 | CHONG 6 | CLIFTON 7 | CODY 8 | COLTON 9 | CORNELL 10 | DAMON 11 | DANNIE 12 | DARIO 13 | DONN 14 | DOUG 15 | DOUGLAS 16 | FREDERICK 17 | FRITZ 18 | GERALD 19 | GUS 20 | HARVEY 21 | IRVING 22 | ISAIAH 23 | JARVIS 24 | JOHN 25 | KENTON 26 | LAURENCE 27 | LESTER 28 | LINCOLN 29 | LOWELL 30 | NELSON 31 | NEVILLE 32 | NIGEL 33 | NORMAND 34 | ODIS 35 | OMAR 36 | ORLANDO 37 | RAYMUNDO 38 | REX 39 | ROLANDO 40 | RON 41 | SHANE 42 | TONEY 43 | TRINIDAD 44 | WALTER 45 | WARNER 46 | WARREN 47 | WES 48 | WILLARD 49 | WILLIAM 50 | WINFRED 51 | XAVIER 52 | -------------------------------------------------------------------------------- /tests/test30.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "utlist.h" 5 | 6 | #define BUFLEN 20 7 | 8 | typedef struct el { 9 | char bname[BUFLEN]; 10 | struct el *next, *prev; 11 | } el; 12 | 13 | static int namecmp(void *_a, void *_b) 14 | { 15 | el *a = (el*)_a; 16 | el *b = (el*)_b; 17 | return strcmp(a->bname,b->bname); 18 | } 19 | 20 | int main() 21 | { 22 | el *name, *tmp; 23 | el *head = NULL; 24 | 25 | char linebuf[BUFLEN]; 26 | FILE *file; 27 | 28 | file = fopen( "test11.dat", "r" ); 29 | if (file == NULL) { 30 | perror("can't open: "); 31 | exit(-1); 32 | } 33 | 34 | while (fgets(linebuf,BUFLEN,file) != NULL) { 35 | name = (el*)malloc(sizeof(el)); 36 | if (name == NULL) { 37 | exit(-1); 38 | } 39 | strcpy(name->bname, linebuf); 40 | CDL_PREPEND(head, name); 41 | } 42 | CDL_SORT(head, namecmp); 43 | CDL_FOREACH(head,tmp) { 44 | printf("%s", tmp->bname); 45 | } 46 | 47 | fclose(file); 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /tests/test31.ans: -------------------------------------------------------------------------------- 1 | ADRIAN 2 | ARNOLDO 3 | CARROLL 4 | CARY 5 | CHONG 6 | CLIFTON 7 | CODY 8 | COLTON 9 | CORNELL 10 | DAMON 11 | DANNIE 12 | DARIO 13 | DONN 14 | DOUG 15 | DOUGLAS 16 | FREDERICK 17 | FRITZ 18 | GERALD 19 | GUS 20 | HARVEY 21 | IRVING 22 | ISAIAH 23 | JARVIS 24 | JOHN 25 | KENTON 26 | LAURENCE 27 | LESTER 28 | LINCOLN 29 | LOWELL 30 | NELSON 31 | NEVILLE 32 | NIGEL 33 | NORMAND 34 | ODIS 35 | OMAR 36 | ORLANDO 37 | RAYMUNDO 38 | REX 39 | ROLANDO 40 | RON 41 | SHANE 42 | TONEY 43 | TRINIDAD 44 | WALTER 45 | WARNER 46 | WARREN 47 | WES 48 | WILLARD 49 | WILLIAM 50 | WINFRED 51 | XAVIER 52 | -------------------------------------------------------------------------------- /tests/test31.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "utlist.h" 5 | 6 | #define BUFLEN 20 7 | 8 | typedef struct el { 9 | char bname[BUFLEN]; 10 | struct el *next, *prev; 11 | } el; 12 | 13 | static int namecmp(void *_a, void *_b) 14 | { 15 | el *a = (el*)_a; 16 | el *b = (el*)_b; 17 | return strcmp(a->bname,b->bname); 18 | } 19 | 20 | int main() 21 | { 22 | el *name, *tmp; 23 | el *head = NULL; 24 | 25 | char linebuf[BUFLEN]; 26 | FILE *file; 27 | 28 | file = fopen( "test11.dat", "r" ); 29 | if (file == NULL) { 30 | perror("can't open: "); 31 | exit(-1); 32 | } 33 | 34 | while (fgets(linebuf,BUFLEN,file) != NULL) { 35 | name = (el*)malloc(sizeof(el)); 36 | if (name == NULL) { 37 | exit(-1); 38 | } 39 | strcpy(name->bname, linebuf); 40 | CDL_PREPEND(head, name); 41 | } 42 | CDL_SORT(head, namecmp); 43 | CDL_FOREACH(head,tmp) { 44 | printf("%s", tmp->bname); 45 | } 46 | 47 | fclose(file); 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /tests/test32.ans: -------------------------------------------------------------------------------- 1 | ARNOLDO 2 | COLTON 3 | WES 4 | WARNER 5 | TONEY 6 | NEVILLE 7 | CHONG 8 | KENTON 9 | DARIO 10 | DANNIE 11 | ODIS 12 | TRINIDAD 13 | DONN 14 | FRITZ 15 | NORMAND 16 | NIGEL 17 | CORNELL 18 | LINCOLN 19 | RAYMUNDO 20 | WINFRED 21 | JARVIS 22 | GUS 23 | ISAIAH 24 | XAVIER 25 | CARY 26 | ROLANDO 27 | LAURENCE 28 | CARROLL 29 | IRVING 30 | LOWELL 31 | DAMON 32 | OMAR 33 | REX 34 | ORLANDO 35 | DOUG 36 | WILLARD 37 | CLIFTON 38 | NELSON 39 | CODY 40 | ADRIAN 41 | HARVEY 42 | RON 43 | LESTER 44 | SHANE 45 | WARREN 46 | FREDERICK 47 | GERALD 48 | DOUGLAS 49 | WALTER 50 | WILLIAM 51 | JOHN 52 | -------------------------------------------------------------------------------- /tests/test32.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "utlist.h" 5 | 6 | #define BUFLEN 20 7 | 8 | typedef struct el { 9 | char bname[BUFLEN]; 10 | struct el *next, *prev; 11 | } el; 12 | 13 | int main() 14 | { 15 | el *name, *tmp; 16 | el *head = NULL; 17 | 18 | char linebuf[BUFLEN]; 19 | FILE *file; 20 | 21 | file = fopen( "test11.dat", "r" ); 22 | if (file == NULL) { 23 | perror("can't open: "); 24 | exit(-1); 25 | } 26 | 27 | while (fgets(linebuf,BUFLEN,file) != NULL) { 28 | name = (el*)malloc(sizeof(el)); 29 | if (name == NULL) { 30 | exit(-1); 31 | } 32 | strcpy(name->bname, linebuf); 33 | DL_PREPEND(head, name); 34 | } 35 | /* DL_SORT(head, namecmp); */ 36 | DL_FOREACH(head,tmp) { 37 | printf("%s", tmp->bname); 38 | } 39 | 40 | fclose(file); 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /tests/test33.ans: -------------------------------------------------------------------------------- 1 | ADRIAN 2 | ARNOLDO 3 | CARROLL 4 | CARY 5 | CHONG 6 | CLIFTON 7 | CODY 8 | COLTON 9 | CORNELL 10 | DAMON 11 | DANNIE 12 | DARIO 13 | DONN 14 | DOUG 15 | DOUGLAS 16 | FREDERICK 17 | FRITZ 18 | GERALD 19 | GUS 20 | HARVEY 21 | IRVING 22 | ISAIAH 23 | JARVIS 24 | JOHN 25 | KENTON 26 | LAURENCE 27 | LESTER 28 | LINCOLN 29 | LOWELL 30 | NELSON 31 | NEVILLE 32 | NIGEL 33 | NORMAND 34 | ODIS 35 | OMAR 36 | ORLANDO 37 | RAYMUNDO 38 | REX 39 | ROLANDO 40 | RON 41 | SHANE 42 | TONEY 43 | TRINIDAD 44 | WALTER 45 | WARNER 46 | WARREN 47 | WES 48 | WILLARD 49 | WILLIAM 50 | WINFRED 51 | XAVIER 52 | -------------------------------------------------------------------------------- /tests/test33.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "utlist.h" 5 | 6 | #define BUFLEN 20 7 | 8 | typedef struct el { 9 | char bname[BUFLEN]; 10 | struct el *next, *prev; 11 | } el; 12 | 13 | static int namecmp(void *_a, void *_b) 14 | { 15 | el *a = (el*)_a; 16 | el *b = (el*)_b; 17 | return strcmp(a->bname,b->bname); 18 | } 19 | 20 | int main() 21 | { 22 | el *name, *tmp; 23 | el *head = NULL; 24 | 25 | char linebuf[BUFLEN]; 26 | FILE *file; 27 | 28 | file = fopen( "test11.dat", "r" ); 29 | if (file == NULL) { 30 | perror("can't open: "); 31 | exit(-1); 32 | } 33 | 34 | while (fgets(linebuf,BUFLEN,file) != NULL) { 35 | name = (el*)malloc(sizeof(el)); 36 | if (name == NULL) { 37 | exit(-1); 38 | } 39 | strcpy(name->bname, linebuf); 40 | LL_PREPEND(head, name); 41 | } 42 | LL_SORT(head, namecmp); 43 | LL_FOREACH(head,tmp) { 44 | printf("%s", tmp->bname); 45 | } 46 | 47 | fclose(file); 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /tests/test34.ans: -------------------------------------------------------------------------------- 1 | ARNOLDO 2 | COLTON 3 | WES 4 | WARNER 5 | TONEY 6 | NEVILLE 7 | CHONG 8 | KENTON 9 | DARIO 10 | DANNIE 11 | ODIS 12 | TRINIDAD 13 | DONN 14 | FRITZ 15 | NORMAND 16 | NIGEL 17 | CORNELL 18 | LINCOLN 19 | RAYMUNDO 20 | WINFRED 21 | JARVIS 22 | GUS 23 | ISAIAH 24 | XAVIER 25 | CARY 26 | ROLANDO 27 | LAURENCE 28 | CARROLL 29 | IRVING 30 | LOWELL 31 | DAMON 32 | OMAR 33 | REX 34 | ORLANDO 35 | DOUG 36 | WILLARD 37 | CLIFTON 38 | NELSON 39 | CODY 40 | ADRIAN 41 | HARVEY 42 | RON 43 | LESTER 44 | SHANE 45 | WARREN 46 | FREDERICK 47 | GERALD 48 | DOUGLAS 49 | WALTER 50 | WILLIAM 51 | JOHN 52 | -------------------------------------------------------------------------------- /tests/test34.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "utlist.h" 5 | 6 | #define BUFLEN 20 7 | 8 | typedef struct el { 9 | char bname[BUFLEN]; 10 | struct el *next, *prev; 11 | } el; 12 | 13 | int main() 14 | { 15 | el *name, *tmp; 16 | el *head = NULL; 17 | 18 | char linebuf[BUFLEN]; 19 | FILE *file; 20 | 21 | file = fopen( "test11.dat", "r" ); 22 | if (file == NULL) { 23 | perror("can't open: "); 24 | exit(-1); 25 | } 26 | 27 | while (fgets(linebuf,BUFLEN,file) != NULL) { 28 | name = (el*)malloc(sizeof(el)); 29 | if (name == NULL) { 30 | exit(-1); 31 | } 32 | strcpy(name->bname, linebuf); 33 | CDL_PREPEND(head, name); 34 | } 35 | /* CDL_SORT(head, namecmp); */ 36 | CDL_FOREACH(head,tmp) { 37 | printf("%s", tmp->bname); 38 | } 39 | 40 | fclose(file); 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /tests/test35.ans: -------------------------------------------------------------------------------- 1 | 0: aello 2 | 1: bello 3 | 2: cello 4 | 3: dello 5 | 4: eello 6 | 5: fello 7 | 6: gello 8 | 7: hello 9 | 8: iello 10 | 9: jello 11 | found aello 12 | right address? yes 13 | found bello 14 | right address? yes 15 | found cello 16 | right address? yes 17 | found dello 18 | right address? yes 19 | found eello 20 | right address? yes 21 | found fello 22 | right address? yes 23 | found gello 24 | right address? yes 25 | found hello 26 | right address? yes 27 | found iello 28 | right address? yes 29 | found jello 30 | right address? yes 31 | -------------------------------------------------------------------------------- /tests/test35.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* strcpy */ 3 | #include /* malloc */ 4 | #include /* printf */ 5 | 6 | typedef struct elt { 7 | char *s; 8 | UT_hash_handle hh; 9 | } elt; 10 | 11 | int main() 12 | { 13 | int i; 14 | elt *head = NULL; 15 | elt elts[10]; 16 | char label[6] = "hello"; 17 | for(i=0; i<10; i++) { 18 | elts[i].s = (char*)malloc(6UL); 19 | strcpy(elts[i].s, "hello"); 20 | elts[i].s[0] = 'a' + i; 21 | printf("%d: %s\n", i, elts[i].s); 22 | HASH_ADD_KEYPTR(hh, head, elts[i].s, 6UL, &elts[i]); 23 | } 24 | 25 | /* look up each element and verify the result pointer */ 26 | for(i=0; i<10; i++) { 27 | elt *e; 28 | label[0] = 'a' + i; 29 | HASH_FIND(hh,head,label,6UL,e); 30 | if (e != NULL) { 31 | printf( "found %s\n", e->s); 32 | printf( "right address? %s\n", (e == &elts[i]) ? "yes" : "no"); 33 | } 34 | } 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /tests/test36.ans: -------------------------------------------------------------------------------- 1 | user 0 2 | user 1 3 | user 2 4 | user 3 5 | user 4 6 | user 5 7 | user 6 8 | user 7 9 | user 8 10 | user 9 11 | user 0, should_find=1, found=1 12 | user 1, should_find=0, found=0 13 | user 2, should_find=1, found=1 14 | user 3, should_find=0, found=0 15 | user 4, should_find=1, found=1 16 | user 5, should_find=0, found=0 17 | user 6, should_find=1, found=1 18 | user 7, should_find=0, found=0 19 | user 8, should_find=1, found=1 20 | user 9, should_find=0, found=0 21 | auser 0 22 | auser 2 23 | auser 4 24 | auser 6 25 | auser 8 26 | -------------------------------------------------------------------------------- /tests/test36.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct { 6 | int id; 7 | UT_hash_handle hh; 8 | UT_hash_handle ah; 9 | } example_user_t; 10 | 11 | #define EVENS(x) (((x)->id % 2) == 0) 12 | static int evens(void *userv) 13 | { 14 | example_user_t *user = (example_user_t*)userv; 15 | return ((user->id % 2) ? 0 : 1); 16 | } 17 | 18 | static int idcmp(void *_a, void *_b) 19 | { 20 | example_user_t *a = (example_user_t*)_a; 21 | example_user_t *b = (example_user_t*)_b; 22 | return (a->id - b->id); 23 | } 24 | 25 | int main() 26 | { 27 | int i; 28 | example_user_t *user, *users=NULL, *ausers=NULL; 29 | 30 | /* create elements */ 31 | for(i=0; i<10; i++) { 32 | user = (example_user_t*)malloc(sizeof(example_user_t)); 33 | if (user == NULL) { 34 | exit(-1); 35 | } 36 | user->id = i; 37 | HASH_ADD_INT(users,id,user); 38 | } 39 | 40 | for(user=users; user!=NULL; user=(example_user_t*)(user->hh.next)) { 41 | printf("user %d\n", user->id); 42 | } 43 | 44 | /* now select some users into ausers */ 45 | HASH_SELECT(ah,ausers,hh,users,evens); 46 | HASH_SRT(ah,ausers,idcmp); 47 | 48 | for(user=users; user!=NULL; user=(example_user_t*)(user->hh.next)) { 49 | example_user_t *found = NULL; 50 | int should_find = !!evens(user); 51 | HASH_FIND(ah, ausers, &user->id, sizeof(user->id), found); 52 | printf("user %d, should_find=%d, found=%d\n", user->id, should_find, (int)(!!found)); 53 | } 54 | 55 | for(user=ausers; user!=NULL; user=(example_user_t*)(user->ah.next)) { 56 | printf("auser %d\n", user->id); 57 | } 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /tests/test37.ans: -------------------------------------------------------------------------------- 1 | user 0 2 | user 1 3 | user 2 4 | user 3 5 | user 4 6 | user 5 7 | user 6 8 | user 7 9 | user 8 10 | user 9 11 | users count: 10 12 | auser 0 13 | auser 2 14 | auser 4 15 | auser 6 16 | auser 8 17 | ausers count: 5 18 | cleared ausers. 19 | ausers count: 0 20 | users count: 10 21 | -------------------------------------------------------------------------------- /tests/test37.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct { 6 | int id; 7 | UT_hash_handle hh; 8 | UT_hash_handle ah; 9 | } example_user_t; 10 | 11 | #define EVENS(x) ((((example_user_t*)(x))->id % 2) == 0) 12 | 13 | static int idcmp(void *_a, void *_b) 14 | { 15 | example_user_t *a = (example_user_t*)_a; 16 | example_user_t *b = (example_user_t*)_b; 17 | return (a->id - b->id); 18 | } 19 | 20 | int main() 21 | { 22 | int i; 23 | example_user_t *user, *users=NULL, *ausers=NULL; 24 | 25 | /* create elements */ 26 | for(i=0; i<10; i++) { 27 | user = (example_user_t*)malloc(sizeof(example_user_t)); 28 | if (user == NULL) { 29 | exit(-1); 30 | } 31 | user->id = i; 32 | HASH_ADD_INT(users,id,user); 33 | } 34 | 35 | for(user=users; user!=NULL; user=(example_user_t*)(user->hh.next)) { 36 | printf("user %d\n", user->id); 37 | } 38 | printf("users count: %u\n", HASH_CNT(hh,users)); 39 | 40 | /* now select some users into ausers */ 41 | HASH_SELECT(ah,ausers,hh,users,EVENS); 42 | HASH_SRT(ah,ausers,idcmp); 43 | 44 | for(user=ausers; user!=NULL; user=(example_user_t*)(user->ah.next)) { 45 | printf("auser %d\n", user->id); 46 | } 47 | printf("ausers count: %u\n", HASH_CNT(ah,ausers)); 48 | HASH_CLEAR(ah,ausers); 49 | printf("cleared ausers.\n"); 50 | printf("ausers count: %u\n", HASH_CNT(ah,ausers)); 51 | for(user=ausers; user!=NULL; user=(example_user_t*)(user->ah.next)) { 52 | printf("auser %d\n", user->id); 53 | } 54 | printf("users count: %u\n", HASH_CNT(hh,users)); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /tests/test38.ans: -------------------------------------------------------------------------------- 1 | hash count 10 2 | -------------------------------------------------------------------------------- /tests/test38.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include 3 | #include 4 | 5 | struct test_t { 6 | int a; 7 | UT_hash_handle hh; 8 | }; 9 | 10 | int main() 11 | { 12 | struct test_t *tests=NULL, *test; 13 | int a, b; 14 | for (b=0; b < 3; b++) { 15 | for (a=0; a < 10; a++) { 16 | test = NULL; 17 | HASH_FIND(hh, tests, &a, sizeof(a), test); 18 | if (test == NULL) { 19 | test = (struct test_t*)malloc(sizeof(struct test_t)); 20 | if (test == NULL) { 21 | exit(-1); 22 | } 23 | memset(test, 0, sizeof(struct test_t)); 24 | test->a = a; 25 | HASH_ADD(hh, tests, a, sizeof(a), test); 26 | } 27 | } 28 | } 29 | printf("hash count %u\n", HASH_COUNT(tests)); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /tests/test39.ans: -------------------------------------------------------------------------------- 1 | adding key eins 2 | adding key zwei 3 | adding key drei 4 | hash count is 3 5 | looking for key eins... found. 6 | looking for key zwei... found. 7 | looking for key drei... found. 8 | -------------------------------------------------------------------------------- /tests/test39.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "uthash.h" 4 | 5 | typedef struct { 6 | const char *name; 7 | UT_hash_handle hh; 8 | } ns_t; 9 | 10 | int main() 11 | { 12 | const char *keys[] = {"eins", "zwei", "drei"}; 13 | unsigned i; 14 | ns_t *nsp; 15 | ns_t *head = NULL; 16 | 17 | for(i=0; i < (sizeof(keys)/sizeof(keys[0])); i++) { 18 | printf("adding key %s\n", keys[i]); 19 | nsp = (ns_t*)malloc(sizeof(ns_t)); 20 | if (nsp == NULL) { 21 | exit(-1); 22 | } 23 | nsp->name = keys[i]; 24 | HASH_ADD_KEYPTR(hh,head,nsp->name,strlen(nsp->name),nsp); 25 | } 26 | printf("hash count is %u\n", HASH_COUNT(head)); 27 | 28 | for(i=0; i < (sizeof(keys)/sizeof(keys[0])); i++) { 29 | printf("looking for key %s... ", keys[i]); 30 | HASH_FIND(hh,head,keys[i],strlen(keys[i]),nsp); 31 | printf("%s.\n", (nsp!=NULL)?"found":"not found"); 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /tests/test4.ans: -------------------------------------------------------------------------------- 1 | cookie 0, user 0 2 | cookie 1, user 1 3 | cookie 4, user 2 4 | cookie 9, user 3 5 | cookie 16, user 4 6 | cookie 25, user 5 7 | cookie 36, user 6 8 | cookie 49, user 7 9 | cookie 64, user 8 10 | cookie 81, user 9 11 | -------------------------------------------------------------------------------- /tests/test4.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct example_user_t { 6 | int id; 7 | int cookie; 8 | UT_hash_handle hh; 9 | UT_hash_handle alth; 10 | } example_user_t; 11 | 12 | int main() 13 | { 14 | int i; 15 | example_user_t *user, *users=NULL, *altusers=NULL; 16 | 17 | /* create elements */ 18 | for(i=0; i<10; i++) { 19 | user = (example_user_t*)malloc(sizeof(example_user_t)); 20 | if (user == NULL) { 21 | exit(-1); 22 | } 23 | user->id = i; 24 | user->cookie = i*i; 25 | HASH_ADD_INT(users,id,user); 26 | HASH_ADD(alth,altusers,cookie,sizeof(int),user); 27 | } 28 | 29 | for(user=altusers; user != NULL; user=(example_user_t*)(user->alth.next)) { 30 | printf("cookie %d, user %d\n", user->cookie, user->id); 31 | } 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /tests/test40.ans: -------------------------------------------------------------------------------- 1 | betty's id is 2 2 | -------------------------------------------------------------------------------- /tests/test40.c: -------------------------------------------------------------------------------- 1 | #include /* strcpy */ 2 | #include /* malloc */ 3 | #include /* printf */ 4 | #include "uthash.h" 5 | 6 | struct my_struct { 7 | const char *name; /* key */ 8 | int id; 9 | UT_hash_handle hh; /* makes this structure hashable */ 10 | }; 11 | 12 | 13 | int main() 14 | { 15 | const char **n, *names[] = { "joe", "bob", "betty", NULL }; 16 | struct my_struct *s, *tmp, *users = NULL; 17 | int i=0; 18 | 19 | for (n = names; *n != NULL; n++) { 20 | s = (struct my_struct*)malloc(sizeof(struct my_struct)); 21 | if (s == NULL) { 22 | exit(-1); 23 | } 24 | s->name = *n; 25 | s->id = i++; 26 | HASH_ADD_KEYPTR( hh, users, s->name, strlen(s->name), s ); 27 | } 28 | 29 | HASH_FIND_STR( users, "betty", s); 30 | if (s != NULL) { 31 | printf("betty's id is %d\n", s->id); 32 | } 33 | 34 | /* free the hash table contents */ 35 | HASH_ITER(hh, users, s, tmp) { 36 | HASH_DEL(users, s); 37 | free(s); 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /tests/test41.ans: -------------------------------------------------------------------------------- 1 | CDL macros 2 | c b a deleting c deleting b deleting a 3 | DL macros 4 | a b c deleting a deleting b deleting c 5 | LL macros 6 | a b c deleting a deleting b deleting c 7 | -------------------------------------------------------------------------------- /tests/test41.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utlist.h" 3 | 4 | typedef struct el { 5 | int id; 6 | struct el *next, *prev; 7 | } el; 8 | 9 | int main() 10 | { 11 | int i; 12 | el *head = NULL; 13 | el els[10], *e, *tmp, *tmp2; 14 | for(i=0; i<10; i++) { 15 | els[i].id=(int)'a'+i; 16 | } 17 | 18 | /* test CDL macros */ 19 | printf("CDL macros\n"); 20 | CDL_PREPEND(head,&els[0]); 21 | CDL_PREPEND(head,&els[1]); 22 | CDL_PREPEND(head,&els[2]); 23 | CDL_FOREACH(head,e) { 24 | printf("%c ", e->id); 25 | } 26 | 27 | /* point head to head->next */ 28 | CDL_FOREACH_SAFE(head,e,tmp,tmp2) { 29 | printf("deleting %c ", e->id); 30 | CDL_DELETE(head,e); 31 | } 32 | printf("\n"); 33 | if (head != NULL) { 34 | printf("non-null head\n"); 35 | } 36 | 37 | /* test DL macros */ 38 | printf("DL macros\n"); 39 | DL_APPEND(head,&els[0]); 40 | DL_APPEND(head,&els[1]); 41 | DL_APPEND(head,&els[2]); 42 | DL_FOREACH(head,e) { 43 | printf("%c ", e->id); 44 | } 45 | DL_FOREACH_SAFE(head,e,tmp) { 46 | printf("deleting %c ", e->id); 47 | DL_DELETE(head,e); 48 | } 49 | printf("\n"); 50 | if (head != NULL) { 51 | printf("non-null head\n"); 52 | } 53 | 54 | /* test LL macros */ 55 | printf("LL macros\n"); 56 | LL_APPEND(head,&els[0]); 57 | LL_APPEND(head,&els[1]); 58 | LL_APPEND(head,&els[2]); 59 | LL_FOREACH(head,e) { 60 | printf("%c ", e->id); 61 | } 62 | LL_FOREACH_SAFE(head,e,tmp) { 63 | printf("deleting %c ", e->id); 64 | LL_DELETE(head,e); 65 | } 66 | printf("\n"); 67 | if (head != NULL) { 68 | printf("non-null head\n"); 69 | } 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /tests/test42.ans: -------------------------------------------------------------------------------- 1 | LL macros 2 | a b c 3 | search scalar found b 4 | search found a 5 | 6 | DL macros 7 | a b c 8 | search scalar found b 9 | search found a 10 | 11 | CDL macros 12 | c b a 13 | search scalar found b 14 | search found a 15 | -------------------------------------------------------------------------------- /tests/test42.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utlist.h" 3 | 4 | typedef struct el { 5 | int id; 6 | struct el *next, *prev; 7 | } el; 8 | 9 | static int eltcmp(el *a, el *b) 10 | { 11 | return a->id - b->id; 12 | } 13 | 14 | int main() 15 | { 16 | int i; 17 | el *head = NULL; 18 | el els[10], *e, *tmp, *tmp2; 19 | for(i=0; i<10; i++) { 20 | els[i].id=(int)'a'+i; 21 | } 22 | 23 | /* test LL macros */ 24 | printf("LL macros\n"); 25 | LL_APPEND(head,&els[0]); 26 | LL_APPEND(head,&els[1]); 27 | LL_APPEND(head,&els[2]); 28 | LL_FOREACH(head,e) { 29 | printf("%c ", e->id); 30 | } 31 | printf("\n"); 32 | LL_SEARCH_SCALAR(head, e, id, 'b'); 33 | if (e != NULL) { 34 | printf("search scalar found b\n"); 35 | } 36 | LL_SEARCH(head, e, &els[0], eltcmp); 37 | if (e != NULL) { 38 | printf("search found %c\n",e->id); 39 | } 40 | LL_FOREACH_SAFE(head,e,tmp) { 41 | LL_DELETE(head,e); 42 | } 43 | 44 | printf("\n"); 45 | 46 | /* test DL macros */ 47 | printf("DL macros\n"); 48 | DL_APPEND(head,&els[0]); 49 | DL_APPEND(head,&els[1]); 50 | DL_APPEND(head,&els[2]); 51 | DL_FOREACH(head,e) { 52 | printf("%c ", e->id); 53 | } 54 | printf("\n"); 55 | DL_SEARCH_SCALAR(head, e, id, 'b'); 56 | if (e != NULL) { 57 | printf("search scalar found b\n"); 58 | } 59 | DL_SEARCH(head, e, &els[0], eltcmp); 60 | if (e != NULL) { 61 | printf("search found %c\n",e->id); 62 | } 63 | DL_FOREACH_SAFE(head,e,tmp) { 64 | DL_DELETE(head,e); 65 | } 66 | printf("\n"); 67 | 68 | /* test CDL macros */ 69 | printf("CDL macros\n"); 70 | CDL_PREPEND(head,&els[0]); 71 | CDL_PREPEND(head,&els[1]); 72 | CDL_PREPEND(head,&els[2]); 73 | CDL_FOREACH(head,e) { 74 | printf("%c ", e->id); 75 | } 76 | printf("\n"); 77 | CDL_SEARCH_SCALAR(head, e, id, 'b'); 78 | if (e != NULL) { 79 | printf("search scalar found b\n"); 80 | } 81 | CDL_SEARCH(head, e, &els[0], eltcmp); 82 | if (e != NULL) { 83 | printf("search found %c\n",e->id); 84 | } 85 | CDL_FOREACH_SAFE(head,e,tmp,tmp2) { 86 | CDL_DELETE(head,e); 87 | } 88 | 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /tests/test43.ans: -------------------------------------------------------------------------------- 1 | length is 0 2 | push 3 | length is 1 4 | back is 1 2 5 | pop 6 | length is 0 7 | push 8 | push 9 | length is 2 10 | 1 2 11 | 3 4 12 | erase [0] 13 | length is 1 14 | 3 4 15 | push 16 | 3 4 17 | 1 2 18 | clear 19 | length is 0 20 | extend 21 | length is 1 22 | ip points to [0] ? yes 23 | push 24 | 0 0 25 | 1 2 26 | erase [1] 27 | length is 1 28 | 0 0 29 | push 30 | 0 0 31 | 3 4 32 | back is 3 4 33 | copy 34 | cpy length is 2 35 | cpy 0 0 36 | cpy 3 4 37 | insert cpy[0] 38 | cpy length is 3 39 | cpy 5 6 40 | cpy 0 0 41 | cpy 3 4 42 | erase cpy [0] [1] 43 | cpy length is 1 44 | cpy 3 4 45 | inserta at cpy[1] 46 | cpy length is 3 47 | cpy 3 4 48 | cpy 0 0 49 | cpy 3 4 50 | free cpy 51 | length is 2 52 | resize to 30 53 | length is 30 54 | 0 0 55 | 3 4 56 | 0 0 57 | 0 0 58 | 0 0 59 | 0 0 60 | 0 0 61 | 0 0 62 | 0 0 63 | 0 0 64 | 0 0 65 | 0 0 66 | 0 0 67 | 0 0 68 | 0 0 69 | 0 0 70 | 0 0 71 | 0 0 72 | 0 0 73 | 0 0 74 | 0 0 75 | 0 0 76 | 0 0 77 | 0 0 78 | 0 0 79 | 0 0 80 | 0 0 81 | 0 0 82 | 0 0 83 | 0 0 84 | resize to 1 85 | length is 1 86 | resize to 0 87 | length is 0 88 | free 89 | -------------------------------------------------------------------------------- /tests/test44.ans: -------------------------------------------------------------------------------- 1 | 0 1 2 3 4 5 6 7 8 9 2 | 9 8 7 6 5 4 3 2 1 0 3 | 9 8 7 3 2 1 0 4 | 9 3 2 1 0 5 | 3 2 1 0 6 | 3 2 1 7 | 3 2 1 0 0 8 | 3 2 1 9 | 10 | -------------------------------------------------------------------------------- /tests/test44.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utarray.h" 3 | 4 | static int reverse(const void *a, const void *b) 5 | { 6 | int _a = *(const int*)a; 7 | int _b = *(const int*)b; 8 | return _b - _a; 9 | } 10 | 11 | int main() 12 | { 13 | UT_array *a; 14 | int i, *p; 15 | utarray_new(a, &ut_int_icd); 16 | for(i=0; i<10; i++) { 17 | utarray_push_back(a,&i); 18 | } 19 | for(p=(int*)utarray_front(a); p!=NULL; p=(int*)utarray_next(a,p)) { 20 | printf("%d ",*p); 21 | } 22 | printf("\n"); 23 | utarray_sort(a,reverse); 24 | while ( (p=(int*)utarray_next(a,p)) != NULL ) { 25 | printf("%d ", *p); 26 | } 27 | printf("\n"); 28 | utarray_erase(a,3,3); 29 | while ( (p=(int*)utarray_next(a,p)) != NULL ) { 30 | printf("%d ", *p); 31 | } 32 | printf("\n"); 33 | utarray_erase(a,1,2); 34 | while ( (p=(int*)utarray_next(a,p)) != NULL ) { 35 | printf("%d ", *p); 36 | } 37 | printf("\n"); 38 | utarray_erase(a,0,1); 39 | while ( (p=(int*)utarray_next(a,p)) != NULL ) { 40 | printf("%d ", *p); 41 | } 42 | printf("\n"); 43 | utarray_erase(a,3,1); 44 | while ( (p=(int*)utarray_next(a,p)) != NULL ) { 45 | printf("%d ", *p); 46 | } 47 | printf("\n"); 48 | utarray_resize(a,5); 49 | while ( (p=(int*)utarray_next(a,p)) != NULL ) { 50 | printf("%d ", *p); 51 | } 52 | printf("\n"); 53 | utarray_resize(a,3); 54 | while ( (p=(int*)utarray_next(a,p)) != NULL ) { 55 | printf("%d ", *p); 56 | } 57 | printf("\n"); 58 | utarray_erase(a,0,3); 59 | while ( (p=(int*)utarray_next(a,p)) != NULL ) { 60 | printf("%d ", *p); 61 | } 62 | printf("\n"); 63 | utarray_free(a); 64 | return 0; 65 | } 66 | 67 | -------------------------------------------------------------------------------- /tests/test45.ans: -------------------------------------------------------------------------------- 1 | 1 2 3 4 5 6 7 8 2 | 1 2 3 100 4 5 6 7 8 3 | 1 2 3 100 4 5 6 7 8 1000 4 | -------------------------------------------------------------------------------- /tests/test45.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utarray.h" 3 | 4 | int main() 5 | { 6 | UT_array *a; 7 | int i, *p=NULL; 8 | utarray_new(a, &ut_int_icd); 9 | for(i=0; i<10; i++) { 10 | utarray_push_back(a,&i); 11 | } 12 | utarray_pop_back(a); 13 | utarray_erase(a,0,1); 14 | while ( (p=(int*)utarray_next(a,p)) != NULL ) { 15 | printf("%d ",*p); 16 | } 17 | printf("\n"); 18 | i = 100; 19 | utarray_insert(a,&i,3); 20 | while ( (p=(int*)utarray_next(a,p)) != NULL ) { 21 | printf("%d ",*p); 22 | } 23 | printf("\n"); 24 | utarray_extend_back(a); 25 | p = (int*)utarray_back(a); 26 | *p = 1000; 27 | p = NULL; 28 | while ( (p=(int*)utarray_next(a,p)) != NULL ) { 29 | printf("%d ",*p); 30 | } 31 | printf("\n"); 32 | utarray_clear(a); 33 | utarray_free(a); 34 | return 0; 35 | } 36 | 37 | -------------------------------------------------------------------------------- /tests/test46.ans: -------------------------------------------------------------------------------- 1 | hello world 2 | begin hello world 3 | alt begin hello world oth 4 | hello world oth 5 | hello world 6 | hello world begin hello world 7 | begin hello world 8 | sorting strs2 9 | begin hello world 10 | reverse sorting strs2 11 | world hello begin 12 | -------------------------------------------------------------------------------- /tests/test46.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utarray.h" 3 | 4 | static int strsort(const void *_a, const void *_b) 5 | { 6 | const char *a = *(const char* const *)_a; 7 | const char *b = *(const char* const *)_b; 8 | return strcmp(a,b); 9 | } 10 | 11 | static int revsort(const void *_a, const void *_b) 12 | { 13 | const char *a = *(const char* const *)_a; 14 | const char *b = *(const char* const *)_b; 15 | return strcmp(b,a); 16 | } 17 | 18 | int main() 19 | { 20 | UT_array *strs,*strs2; 21 | char *s, **p=NULL; 22 | utarray_new(strs, &ut_str_icd); 23 | s=(char*)"hello"; 24 | utarray_push_back(strs, &s); 25 | s=(char*)"world"; 26 | utarray_push_back(strs, &s); 27 | while ( (p=(char**)utarray_next(strs,p)) != NULL ) { 28 | printf("%s ",*p); 29 | } 30 | printf("\n"); 31 | s=(char*)"begin"; 32 | utarray_insert(strs,&s,0); 33 | while ( (p=(char**)utarray_next(strs,p)) != NULL ) { 34 | printf("%s ",*p); 35 | } 36 | printf("\n"); 37 | utarray_new(strs2, &ut_str_icd); 38 | s=(char*)"alt"; 39 | utarray_push_back(strs2, &s); 40 | s=(char*)"oth"; 41 | utarray_push_back(strs2, &s); 42 | utarray_inserta(strs2, strs, 1); 43 | while ( (p=(char**)utarray_next(strs2,p)) != NULL ) { 44 | printf("%s ",*p); 45 | } 46 | printf("\n"); 47 | utarray_erase(strs2,0,2); 48 | while ( (p=(char**)utarray_next(strs2,p)) != NULL ) { 49 | printf("%s ",*p); 50 | } 51 | printf("\n"); 52 | utarray_pop_back(strs2); 53 | while ( (p=(char**)utarray_next(strs2,p)) != NULL ) { 54 | printf("%s ",*p); 55 | } 56 | printf("\n"); 57 | utarray_concat(strs2, strs); 58 | while ( (p=(char**)utarray_next(strs2,p)) != NULL ) { 59 | printf("%s ",*p); 60 | } 61 | printf("\n"); 62 | utarray_clear(strs2); 63 | utarray_concat(strs2, strs); 64 | while ( (p=(char**)utarray_next(strs2,p)) != NULL ) { 65 | printf("%s ",*p); 66 | } 67 | printf("\n"); 68 | printf("sorting strs2\n"); 69 | utarray_sort(strs2,strsort); 70 | while ( (p=(char**)utarray_next(strs2,p)) != NULL ) { 71 | printf("%s ",*p); 72 | } 73 | printf("\n"); 74 | printf("reverse sorting strs2\n"); 75 | utarray_sort(strs2,revsort); 76 | while ( (p=(char**)utarray_next(strs2,p)) != NULL ) { 77 | printf("%s ",*p); 78 | } 79 | printf("\n"); 80 | utarray_clear(strs2); 81 | utarray_free(strs2); 82 | utarray_free(strs); 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /tests/test47.ans: -------------------------------------------------------------------------------- 1 | hello world 2 | hello world text 3 | second 4 | hello world text second 5 | cleared, length t now: 0 6 | length s now: 23 7 | one 1 two 2 three (3) 8 | length t now: 21 9 | -------------------------------------------------------------------------------- /tests/test47.c: -------------------------------------------------------------------------------- 1 | #include /* printf */ 2 | #include "utstring.h" 3 | 4 | int main() 5 | { 6 | UT_string *s,*t; 7 | char a[] = " text"; 8 | utstring_new(s); 9 | utstring_new(t); 10 | 11 | utstring_printf(s,"hello %s", "world"); 12 | printf("%s\n", utstring_body(s)); 13 | utstring_bincpy(s,a,sizeof(a)-1); 14 | printf("%s\n", utstring_body(s)); 15 | utstring_printf(t," second"); 16 | printf("%s\n", utstring_body(t)); 17 | utstring_concat(s,t); 18 | printf("%s\n", utstring_body(s)); 19 | utstring_clear(t); 20 | printf("cleared, length t now: %u\n", (unsigned)utstring_len(t)); 21 | printf("length s now: %u\n", (unsigned)utstring_len(s)); 22 | utstring_printf(t,"one %d two %u three %s", 1, 2, "(3)"); 23 | printf("%s\n", utstring_body(t)); 24 | printf("length t now: %u\n", (unsigned)utstring_len(t)); 25 | 26 | utstring_free(t); 27 | utstring_free(s); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /tests/test48.ans: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 2 4 | 3 5 | 4 6 | 5 7 | 6 8 | 7 9 | 8 10 | 9 11 | -------------------------------------------------------------------------------- /tests/test48.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utarray.h" 3 | 4 | int main() 5 | { 6 | UT_array *nums; 7 | int i, *p; 8 | 9 | utarray_new(nums,&ut_int_icd); 10 | for(i=0; i < 10; i++) { 11 | utarray_push_back(nums,&i); 12 | } 13 | 14 | for(p=(int*)utarray_front(nums); 15 | p!=NULL; 16 | p=(int*)utarray_next(nums,p)) { 17 | printf("%d\n",*p); 18 | } 19 | 20 | utarray_free(nums); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /tests/test49.ans: -------------------------------------------------------------------------------- 1 | hello 2 | world 3 | -------------------------------------------------------------------------------- /tests/test49.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utarray.h" 3 | 4 | int main() 5 | { 6 | UT_array *strs; 7 | const char *s, **p; 8 | 9 | utarray_new(strs,&ut_str_icd); 10 | 11 | s = "hello"; 12 | utarray_push_back(strs, &s); 13 | s = "world"; 14 | utarray_push_back(strs, &s); 15 | p = NULL; 16 | while ( (p=(const char**)utarray_next(strs,p)) != NULL ) { 17 | printf("%s\n",*p); 18 | } 19 | 20 | utarray_free(strs); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /tests/test5.ans: -------------------------------------------------------------------------------- 1 | cookie 0 found, user id 0 2 | cookie 4 found, user id 2 3 | cookie 16 found, user id 4 4 | cookie 36 found, user id 6 5 | cookie 64 found, user id 8 6 | -------------------------------------------------------------------------------- /tests/test5.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct example_user_t { 6 | int id; 7 | int cookie; 8 | UT_hash_handle hh; 9 | UT_hash_handle alth; 10 | } example_user_t; 11 | 12 | int main() 13 | { 14 | int i,j; 15 | example_user_t *user, *tmp, *users=NULL, *altusers=NULL; 16 | 17 | /* create elements */ 18 | for(i=0; i<10; i++) { 19 | user = (example_user_t*)malloc(sizeof(example_user_t)); 20 | if (user == NULL) { 21 | exit(-1); 22 | } 23 | user->id = i; 24 | user->cookie = i*i; 25 | HASH_ADD_INT(users,id,user); 26 | HASH_ADD(alth,altusers,cookie,sizeof(int),user); 27 | } 28 | 29 | /* find cookie corresponding to each even ID */ 30 | for(i=0; i<10; i+=2) { 31 | j=i*i; 32 | HASH_FIND(alth,altusers,&j,sizeof(int),tmp); 33 | if (tmp != NULL) { 34 | printf("cookie %d found, user id %d\n", tmp->cookie, tmp->id); 35 | } else { 36 | printf("cookie %d not found\n", j); 37 | } 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /tests/test50.ans: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | -------------------------------------------------------------------------------- /tests/test50.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utarray.h" 3 | 4 | int main() 5 | { 6 | UT_array *nums; 7 | long l, *p; 8 | UT_icd long_icd = {sizeof(long), NULL, NULL, NULL }; 9 | utarray_new(nums, &long_icd); 10 | 11 | l=1; 12 | utarray_push_back(nums, &l); 13 | l=2; 14 | utarray_push_back(nums, &l); 15 | 16 | p=NULL; 17 | while( (p=(long*)utarray_next(nums,p)) != NULL ) { 18 | printf("%ld\n", *p); 19 | } 20 | 21 | utarray_free(nums); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /tests/test51.ans: -------------------------------------------------------------------------------- 1 | 1 2 2 | 10 20 3 | -------------------------------------------------------------------------------- /tests/test51.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utarray.h" 3 | 4 | typedef struct { 5 | int a; 6 | int b; 7 | } intpair_t; 8 | 9 | int main() 10 | { 11 | 12 | UT_array *pairs; 13 | intpair_t ip, *p; 14 | UT_icd intpair_icd = {sizeof(intpair_t), NULL, NULL, NULL}; 15 | utarray_new(pairs,&intpair_icd); 16 | 17 | ip.a=1; 18 | ip.b=2; 19 | utarray_push_back(pairs, &ip); 20 | ip.a=10; 21 | ip.b=20; 22 | utarray_push_back(pairs, &ip); 23 | 24 | for(p=(intpair_t*)utarray_front(pairs); 25 | p!=NULL; 26 | p=(intpair_t*)utarray_next(pairs,p)) { 27 | printf("%d %d\n", p->a, p->b); 28 | } 29 | 30 | utarray_free(pairs); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /tests/test52.ans: -------------------------------------------------------------------------------- 1 | 1 hello 2 | 2 world 3 | -------------------------------------------------------------------------------- /tests/test52.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "utarray.h" 4 | 5 | typedef struct { 6 | int a; 7 | char *s; 8 | } intchar_t; 9 | 10 | static void intchar_copy(void *_dst, const void *_src) 11 | { 12 | intchar_t *dst = (intchar_t*)_dst; 13 | const intchar_t *src = (const intchar_t*)_src; 14 | dst->a = src->a; 15 | dst->s = (src->s != NULL) ? strdup(src->s) : NULL; 16 | } 17 | 18 | static void intchar_dtor(void *_elt) 19 | { 20 | intchar_t *elt = (intchar_t*)_elt; 21 | if (elt->s != NULL) { 22 | free(elt->s); 23 | } 24 | } 25 | 26 | int main() 27 | { 28 | UT_array *intchars; 29 | intchar_t ic, *p; 30 | UT_icd intchar_icd = {sizeof(intchar_t), NULL, intchar_copy, intchar_dtor}; 31 | utarray_new(intchars, &intchar_icd); 32 | 33 | ic.a=1; 34 | ic.s=(char*)"hello"; 35 | utarray_push_back(intchars, &ic); 36 | ic.a=2; 37 | ic.s=(char*)"world"; 38 | utarray_push_back(intchars, &ic); 39 | 40 | p=NULL; 41 | while( (p=(intchar_t*)utarray_next(intchars,p)) != NULL ) { 42 | printf("%d %s\n", p->a, (p->s != NULL) ? p->s : "null"); 43 | } 44 | 45 | utarray_free(intchars); 46 | return 0; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /tests/test53.ans: -------------------------------------------------------------------------------- 1 | hello world! 2 | -------------------------------------------------------------------------------- /tests/test53.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utstring.h" 3 | 4 | int main() 5 | { 6 | UT_string *s; 7 | 8 | utstring_new(s); 9 | utstring_printf(s, "hello world!" ); 10 | printf("%s\n", utstring_body(s)); 11 | 12 | utstring_free(s); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /tests/test54.ans: -------------------------------------------------------------------------------- 1 | length: 21 2 | hello world hi there 3 | -------------------------------------------------------------------------------- /tests/test54.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utstring.h" 3 | 4 | int main() 5 | { 6 | UT_string *s, *t; 7 | 8 | utstring_new(s); 9 | utstring_new(t); 10 | 11 | utstring_printf(s, "hello " ); 12 | utstring_printf(s, "world " ); 13 | 14 | utstring_printf(t, "hi " ); 15 | utstring_printf(t, "there " ); 16 | 17 | utstring_concat(s, t); 18 | printf("length: %u\n", (unsigned)utstring_len(s)); 19 | printf("%s\n", utstring_body(s)); 20 | 21 | utstring_free(s); 22 | utstring_free(t); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /tests/test55.ans: -------------------------------------------------------------------------------- 1 | length is 3 2 | number 10 3 | -------------------------------------------------------------------------------- /tests/test55.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utstring.h" 3 | 4 | int main() 5 | { 6 | UT_string *s; 7 | char binary[] = "\xff\xff"; 8 | 9 | utstring_new(s); 10 | utstring_bincpy(s, binary, sizeof(binary)); 11 | printf("length is %u\n", (unsigned)utstring_len(s)); 12 | 13 | utstring_clear(s); 14 | utstring_printf(s,"number %d", 10); 15 | printf("%s\n", utstring_body(s)); 16 | 17 | utstring_free(s); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /tests/test56.ans: -------------------------------------------------------------------------------- 1 | ADRIAN 2 | ARNOLDO 3 | CARROLL 4 | CARY 5 | CHONG 6 | CLIFTON 7 | CODY 8 | COLTON 9 | CORNELL 10 | DAMON 11 | DANNIE 12 | DARIO 13 | DONN 14 | DOUG 15 | DOUGLAS 16 | FREDERICK 17 | FRITZ 18 | GERALD 19 | GUS 20 | HARVEY 21 | IRVING 22 | ISAIAH 23 | JARVIS 24 | JOHN 25 | KENTON 26 | LAURENCE 27 | LESTER 28 | LINCOLN 29 | LOWELL 30 | NELSON 31 | NEVILLE 32 | NIGEL 33 | NORMAND 34 | ODIS 35 | OMAR 36 | ORLANDO 37 | RAYMUNDO 38 | REX 39 | ROLANDO 40 | RON 41 | SHANE 42 | TONEY 43 | TRINIDAD 44 | WALTER 45 | WARNER 46 | WARREN 47 | WES 48 | WILLARD 49 | WILLIAM 50 | WINFRED 51 | XAVIER 52 | found WES 53 | 54 | user 0, cookie 0 55 | user 1, cookie 1 56 | user 2, cookie 4 57 | user 3, cookie 9 58 | user 4, cookie 16 59 | user 5, cookie 25 60 | user 6, cookie 36 61 | user 7, cookie 49 62 | user 8, cookie 64 63 | user 9, cookie 81 64 | length is 3 65 | number 10 66 | -------------------------------------------------------------------------------- /tests/test56.c: -------------------------------------------------------------------------------- 1 | #include /* malloc */ 2 | #include /* printf */ 3 | #include 4 | #include "uthash.h" 5 | #include "utlist.h" 6 | #include "utstring.h" 7 | 8 | typedef struct example_user_t { 9 | int id; 10 | int cookie; 11 | UT_hash_handle hh; 12 | } example_user_t; 13 | 14 | #define BUFLEN 20 15 | 16 | typedef struct el { 17 | char bname[BUFLEN]; 18 | struct el *next, *prev; 19 | } el; 20 | 21 | static int namecmp(void *_a, void *_b) 22 | { 23 | el *a = (el*)_a; 24 | el *b = (el*)_b; 25 | return strcmp(a->bname,b->bname); 26 | } 27 | 28 | int main() 29 | { 30 | el *name, *elt, *tmp, etmp; 31 | int i; 32 | example_user_t *user, *users=NULL; 33 | el *head = NULL; /* important- initialize to NULL! */ 34 | 35 | char linebuf[BUFLEN]; 36 | FILE *file; 37 | 38 | UT_string *s; 39 | char binary[] = "\xff\xff"; 40 | 41 | file = fopen( "test11.dat", "r" ); 42 | if (file == NULL) { 43 | perror("can't open: "); 44 | exit(-1); 45 | } 46 | 47 | while (fgets(linebuf,BUFLEN,file) != NULL) { 48 | name = (el*)malloc(sizeof(el)); 49 | if (name == NULL) { 50 | exit(-1); 51 | } 52 | strcpy(name->bname, linebuf); 53 | DL_APPEND(head, name); 54 | } 55 | DL_SORT(head, namecmp); 56 | DL_FOREACH(head,elt) { 57 | printf("%s", elt->bname); 58 | } 59 | 60 | memcpy(etmp.bname, "WES\n", 5UL); 61 | DL_SEARCH(head,elt,&etmp,namecmp); 62 | if (elt != NULL) { 63 | printf("found %s\n", elt->bname); 64 | } 65 | 66 | /* now delete each element, use the safe iterator */ 67 | DL_FOREACH_SAFE(head,elt,tmp) { 68 | DL_DELETE(head,elt); 69 | } 70 | 71 | fclose(file); 72 | 73 | /* create elements */ 74 | for(i=0; i<10; i++) { 75 | user = (example_user_t*)malloc(sizeof(example_user_t)); 76 | if (user == NULL) { 77 | exit(-1); 78 | } 79 | user->id = i; 80 | user->cookie = i*i; 81 | HASH_ADD_INT(users,id,user); 82 | } 83 | 84 | for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { 85 | printf("user %d, cookie %d\n", user->id, user->cookie); 86 | } 87 | 88 | utstring_new(s); 89 | utstring_bincpy(s, binary, sizeof(binary)); 90 | printf("length is %u\n", (unsigned)utstring_len(s)); 91 | 92 | utstring_clear(s); 93 | utstring_printf(s,"number %d", 10); 94 | printf("%s\n", utstring_body(s)); 95 | 96 | utstring_free(s); 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /tests/test57.ans: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/troydhanson/uthash/af6e637f19c102167fb914b9ebcc171389270b48/tests/test57.ans -------------------------------------------------------------------------------- /tests/test57.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "uthash.h" 4 | 5 | typedef struct { 6 | void *key; 7 | int i; 8 | UT_hash_handle hh; 9 | } el_t; 10 | 11 | el_t *findit(el_t *hash, void *keytofind) 12 | { 13 | el_t *found; 14 | HASH_FIND_PTR(hash, &keytofind, found); 15 | return found; 16 | } 17 | 18 | int main() 19 | { 20 | el_t *hash = NULL; 21 | el_t e1; 22 | el_t e2; 23 | 24 | e1.key = NULL; 25 | e1.i = 1; 26 | 27 | e2.key = &e2; 28 | e2.i = 2; 29 | 30 | assert(findit(hash, NULL) == NULL); 31 | assert(findit(hash, &e1) == NULL); 32 | assert(findit(hash, &e2) == NULL); 33 | 34 | HASH_ADD_PTR(hash, key, &e1); 35 | assert(findit(hash, NULL) == &e1); 36 | assert(findit(hash, &e1) == NULL); 37 | assert(findit(hash, &e2) == NULL); 38 | 39 | HASH_ADD_PTR(hash, key, &e2); 40 | assert(findit(hash, NULL) == &e1); 41 | assert(findit(hash, &e1) == NULL); 42 | assert(findit(hash, &e2) == &e2); 43 | 44 | HASH_DEL(hash, &e1); 45 | assert(findit(hash, NULL) == NULL); 46 | assert(findit(hash, &e1) == NULL); 47 | assert(findit(hash, &e2) == &e2); 48 | 49 | HASH_CLEAR(hh, hash); 50 | assert(hash == NULL); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /tests/test58.ans: -------------------------------------------------------------------------------- 1 | user 0, cookie 0 2 | user 1, cookie 1 3 | user 2, cookie 4 4 | user 3, cookie 9 5 | user 4, cookie 16 6 | user 5, cookie 25 7 | user 6, cookie 36 8 | user 7, cookie 49 9 | user 8, cookie 64 10 | user 9, cookie 81 11 | 10 users. Deleting odd id's... 12 | user 0, cookie 0 13 | user 2, cookie 4 14 | user 4, cookie 16 15 | user 6, cookie 36 16 | user 8, cookie 64 17 | 5 users. Deleting remaining id's... 18 | 0 users. 19 | -------------------------------------------------------------------------------- /tests/test58.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct example_user_t { 6 | int id; 7 | int cookie; 8 | UT_hash_handle hh; 9 | } example_user_t; 10 | 11 | int main() 12 | { 13 | int i; 14 | unsigned c; 15 | example_user_t *user, *tmp, *users=NULL; 16 | 17 | /* create elements */ 18 | for(i=0; i<10; i++) { 19 | if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) { 20 | exit(-1); 21 | } 22 | user->id = i; 23 | user->cookie = i*i; 24 | HASH_ADD_INT(users,id,user); 25 | } 26 | /* show the hash */ 27 | for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { 28 | printf("user %d, cookie %d\n", user->id, user->cookie); 29 | } 30 | 31 | 32 | c = HASH_COUNT(users); 33 | printf("%u users. Deleting odd id's...\n", c); 34 | /* delete the odd id's */ 35 | HASH_ITER(hh, users, user, tmp) { 36 | if ((user->id & 1) != 0) { 37 | HASH_DEL(users,user); 38 | } 39 | } 40 | 41 | /* show the hash */ 42 | for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { 43 | printf("user %d, cookie %d\n", user->id, user->cookie); 44 | } 45 | 46 | c = HASH_COUNT(users); 47 | printf("%u users. Deleting remaining id's...\n", c); 48 | /* delete all that are left */ 49 | HASH_ITER(hh, users, user, tmp) { 50 | HASH_DEL(users,user); 51 | } 52 | 53 | c = HASH_COUNT(users); 54 | printf("%u users.\n", c); 55 | /* show the hash */ 56 | for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { 57 | printf("user %d, cookie %d\n", user->id, user->cookie); 58 | } 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /tests/test59.ans: -------------------------------------------------------------------------------- 1 | $items{bob}{age} = 37 2 | -------------------------------------------------------------------------------- /tests/test59.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "uthash.h" 5 | 6 | /* hash of hashes */ 7 | typedef struct item { 8 | char name[10]; 9 | struct item *sub; 10 | int val; 11 | UT_hash_handle hh; 12 | } item_t; 13 | 14 | int main() 15 | { 16 | item_t *item1, *item2, *tmp1, *tmp2; 17 | item_t *items=NULL; 18 | 19 | /* make initial element */ 20 | item_t *i = (item_t *)malloc(sizeof(*i)); 21 | if (i == NULL) { 22 | exit(-1); 23 | } 24 | strcpy(i->name, "bob"); 25 | i->sub = NULL; 26 | i->val = 0; 27 | HASH_ADD_STR(items, name, i); 28 | 29 | /* add a sub hash table off this element */ 30 | item_t *s = (item_t *)malloc(sizeof(*s)); 31 | if (s == NULL) { 32 | exit(-1); 33 | } 34 | strcpy(s->name, "age"); 35 | s->sub = NULL; 36 | s->val = 37; 37 | HASH_ADD_STR(i->sub, name, s); 38 | 39 | /* iterate over hash elements */ 40 | HASH_ITER(hh, items, item1, tmp1) { 41 | HASH_ITER(hh, item1->sub, item2, tmp2) { 42 | printf("$items{%s}{%s} = %d\n", item1->name, item2->name, item2->val); 43 | } 44 | } 45 | 46 | /* clean up both hash tables */ 47 | HASH_ITER(hh, items, item1, tmp1) { 48 | HASH_ITER(hh, item1->sub, item2, tmp2) { 49 | HASH_DEL(item1->sub, item2); 50 | free(item2); 51 | } 52 | HASH_DEL(items, item1); 53 | free(item1); 54 | } 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /tests/test6.ans: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/troydhanson/uthash/af6e637f19c102167fb914b9ebcc171389270b48/tests/test6.ans -------------------------------------------------------------------------------- /tests/test6.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* Set up macros for alternative malloc/free functions */ 8 | #undef uthash_malloc 9 | #undef uthash_free 10 | #undef uthash_strlen 11 | #undef uthash_bzero 12 | #define uthash_malloc(sz) alt_malloc(sz) 13 | #define uthash_free(ptr,sz) alt_free(ptr,sz) 14 | #define uthash_strlen(s) ..fail_to_compile.. 15 | #define uthash_bzero(a,n) alt_bzero(a,n) 16 | 17 | #undef HASH_KEYCMP 18 | #define HASH_KEYCMP(a,b,n) alt_keycmp(a,b,n) 19 | 20 | typedef struct example_user_t { 21 | int id; 22 | int cookie; 23 | UT_hash_handle hh; 24 | } example_user_t; 25 | 26 | static size_t alt_malloc_sizes[10]; 27 | static int alt_malloc_balance = 0; 28 | static void *alt_malloc(size_t sz) 29 | { 30 | alt_malloc_sizes[alt_malloc_balance++] = sz; 31 | if (alt_malloc_balance == 1) { 32 | assert(sz == sizeof(UT_hash_table)); 33 | } 34 | return malloc(sz); 35 | } 36 | static void alt_free(void *ptr, size_t sz) 37 | { 38 | size_t expected = alt_malloc_sizes[--alt_malloc_balance]; 39 | if (sz != expected) { 40 | printf("expected free of size %d, got %d\n", (int)expected, (int)sz); 41 | } 42 | free(ptr); 43 | } 44 | 45 | static int alt_keycmp_count = 0; 46 | static int alt_keycmp(const void *a, const void *b, size_t n) 47 | { 48 | ++alt_keycmp_count; 49 | return memcmp(a,b,n); 50 | } 51 | 52 | static int alt_bzero_count = 0; 53 | static void alt_bzero(void *a, size_t n) 54 | { 55 | ++alt_bzero_count; 56 | memset(a,0,n); 57 | } 58 | 59 | static void *real_malloc(size_t n) 60 | { 61 | return malloc(n); 62 | } 63 | 64 | static void real_free(void *p) 65 | { 66 | free(p); 67 | } 68 | 69 | #undef malloc 70 | #undef realloc 71 | #undef free 72 | #undef memset 73 | #undef memcmp 74 | #undef strlen 75 | #define malloc ..fail_to_compile.. 76 | #define realloc ..fail_to_compile.. 77 | #define free ..fail_to_compile.. 78 | #define memset ..fail_to_compile.. 79 | #define memcmp ..fail_to_compile.. 80 | #define strlen ..fail_to_compile.. 81 | 82 | int main() 83 | { 84 | int i; 85 | example_user_t *user, *tmp, *users=NULL; 86 | 87 | /* create elements */ 88 | for(i=0; i<10; i++) { 89 | user = (example_user_t*)real_malloc(sizeof(example_user_t)); 90 | if (user == NULL) { 91 | exit(-1); 92 | } 93 | user->id = i; 94 | user->cookie = i*i; 95 | HASH_ADD_INT(users,id,user); 96 | } 97 | 98 | /* delete each ID */ 99 | for(i=0; i<10; i++) { 100 | HASH_FIND_INT(users,&i,tmp); 101 | if (tmp != NULL) { 102 | HASH_DEL(users,tmp); 103 | real_free(tmp); 104 | } else { 105 | printf("user id %d not found\n", i); 106 | } 107 | } 108 | 109 | /* show the hash */ 110 | for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { 111 | printf("user %d, cookie %d\n", user->id, user->cookie); 112 | } 113 | 114 | #ifdef HASH_BLOOM 115 | assert(alt_bzero_count == 3); 116 | #else 117 | assert(alt_bzero_count == 2); 118 | #endif 119 | assert(alt_keycmp_count == 10); 120 | assert(alt_malloc_balance == 0); 121 | return 0; 122 | } 123 | -------------------------------------------------------------------------------- /tests/test60.ans: -------------------------------------------------------------------------------- 1 | $items{bob}{age} = 37 2 | -------------------------------------------------------------------------------- /tests/test60.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "uthash.h" 5 | 6 | /* hash of hashes */ 7 | typedef struct item { 8 | char name[10]; 9 | struct item *sub; 10 | int val; 11 | UT_hash_handle hh; 12 | } item_t; 13 | 14 | int main() 15 | { 16 | item_t *item1, *item2, *tmp1, *tmp2; 17 | item_t *items=NULL; 18 | 19 | /* make initial element */ 20 | item_t *i = (item_t *)malloc(sizeof(*i)); 21 | if (i == NULL) { 22 | exit(-1); 23 | } 24 | strcpy(i->name, "bob"); 25 | i->sub = NULL; 26 | i->val = 0; 27 | HASH_ADD_STR(items, name, i); 28 | 29 | /* add a sub hash table off this element */ 30 | item_t *s = (item_t *)malloc(sizeof(*s)); 31 | if (s == NULL) { 32 | exit(-1); 33 | } 34 | strcpy(s->name, "age"); 35 | s->sub = NULL; 36 | s->val = 37; 37 | HASH_ADD_STR(i->sub, name, s); 38 | 39 | /* iterate over hash elements, printing and freeing them */ 40 | HASH_ITER(hh, items, item1, tmp1) { 41 | HASH_ITER(hh, item1->sub, item2, tmp2) { 42 | printf("$items{%s}{%s} = %d\n", item1->name, item2->name, item2->val); 43 | HASH_DEL(item1->sub, item2); 44 | free(item2); 45 | } 46 | HASH_DEL(items, item1); 47 | free(item1); 48 | } 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /tests/test61.ans: -------------------------------------------------------------------------------- 1 | hello 2 | world 3 | one 4 | two 5 | three 6 | sorting 7 | finding hello 8 | hello 9 | finding one 10 | one 11 | finding three 12 | three 13 | finding two 14 | two 15 | finding world 16 | world 17 | -------------------------------------------------------------------------------- /tests/test61.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utarray.h" 3 | 4 | static int strsort(const void *_a, const void *_b) 5 | { 6 | const char *a = *(const char* const *)_a; 7 | const char *b = *(const char* const *)_b; 8 | return strcmp(a,b); 9 | } 10 | 11 | int main() 12 | { 13 | UT_array *strs; 14 | const char *s, **p; 15 | 16 | utarray_new(strs,&ut_str_icd); 17 | 18 | s = "hello"; 19 | utarray_push_back(strs, &s); 20 | s = "world"; 21 | utarray_push_back(strs, &s); 22 | s = "one"; 23 | utarray_push_back(strs, &s); 24 | s = "two"; 25 | utarray_push_back(strs, &s); 26 | s = "three"; 27 | utarray_push_back(strs, &s); 28 | 29 | p = NULL; 30 | while ( (p=(const char**)utarray_next(strs,p)) != NULL ) { 31 | s = *p; 32 | printf("%s\n",s); 33 | } 34 | 35 | printf("sorting\n"); 36 | utarray_sort(strs,strsort); 37 | 38 | p = NULL; 39 | while ( (p=(const char**)utarray_next(strs,p)) != NULL ) { 40 | s = *p; 41 | printf("finding %s\n",s); 42 | #ifdef __cplusplus 43 | p = (const char**)utarray_find(strs,&s,strsort); 44 | #else 45 | p = utarray_find(strs,&s,strsort); 46 | #endif 47 | printf(" %s\n", (p != NULL) ? (*p) : "failed"); 48 | } 49 | 50 | utarray_free(strs); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /tests/test62.ans: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/troydhanson/uthash/af6e637f19c102167fb914b9ebcc171389270b48/tests/test62.ans -------------------------------------------------------------------------------- /tests/test62.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #define HASH_FUNCTION(s, len, hashv) (hashv) = TrivialHash((const char *)s, len) 6 | #include "uthash.h" 7 | 8 | unsigned int TrivialHash(const char *s, size_t len) 9 | { 10 | unsigned int h = 0; 11 | size_t i; 12 | for (i=0; i < len; ++i) { 13 | h += (unsigned char)s[i]; 14 | } 15 | return h; 16 | } 17 | 18 | struct test_t { 19 | int a; 20 | int b; 21 | UT_hash_handle hh; 22 | }; 23 | 24 | struct test_t *make_test(int value) 25 | { 26 | struct test_t *test = (struct test_t *)malloc(sizeof *test); 27 | assert(test != NULL); 28 | test->a = value; 29 | return test; 30 | } 31 | 32 | int main() 33 | { 34 | struct test_t *tests = NULL; 35 | struct test_t *test = NULL; 36 | int x; 37 | unsigned int h; 38 | 39 | x = 0x0042; 40 | HASH_VALUE(&x, sizeof x, h); 41 | assert(h == 0x42); 42 | 43 | x = 0x4002; 44 | HASH_VALUE(&x, sizeof x, h); 45 | assert(h == 0x42); 46 | 47 | test = make_test(0x0042); 48 | HASH_ADD_INT(tests, a, test); 49 | test = make_test(0x4002); 50 | HASH_ADD_INT(tests, a, test); 51 | 52 | x = 0x4002; 53 | test = NULL; 54 | HASH_FIND_BYHASHVALUE(hh, tests, &x, sizeof x, 0x42, test); 55 | assert(test != NULL); 56 | assert(test->a == 0x4002); 57 | 58 | x = 0x0042; 59 | test = NULL; 60 | HASH_FIND_BYHASHVALUE(hh, tests, &x, sizeof x, 0x42, test); 61 | assert(test != NULL); 62 | assert(test->a == 0x0042); 63 | 64 | x = 0x4002; 65 | test = NULL; 66 | HASH_FIND_BYHASHVALUE(hh, tests, &x, sizeof x, 0x43, test); 67 | assert(test == NULL); 68 | 69 | x = 0x0042; 70 | test = NULL; 71 | HASH_FIND_BYHASHVALUE(hh, tests, &x, sizeof x, 0x43, test); 72 | assert(test == NULL); 73 | 74 | x = 0x4003; 75 | test = NULL; 76 | HASH_FIND_BYHASHVALUE(hh, tests, &x, sizeof x, 0x42, test); 77 | assert(test == NULL); 78 | 79 | HASH_CLEAR(hh, tests); 80 | } 81 | -------------------------------------------------------------------------------- /tests/test63.ans: -------------------------------------------------------------------------------- 1 | LL macros 2 | a b c 3 | d e f 4 | a b c d e f 5 | d e f 6 | d e f 7 | a b 8 | -------------------------------------------------------------------------------- /tests/test63.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utlist.h" 3 | 4 | typedef struct el { 5 | int id; 6 | struct el *next, *prev; 7 | } el; 8 | 9 | int main() 10 | { 11 | int i; 12 | el els[10], *e; 13 | el *headA = NULL; 14 | el *headB = NULL; 15 | for(i=0; i<10; i++) { 16 | els[i].id=(int)'a'+i; 17 | } 18 | 19 | /* test LL macros */ 20 | printf("LL macros\n"); 21 | LL_APPEND(headA,&els[0]); 22 | LL_APPEND(headA,&els[1]); 23 | LL_APPEND(headA,&els[2]); 24 | LL_FOREACH(headA,e) { 25 | printf("%c ", e->id); 26 | } 27 | printf("\n"); 28 | 29 | LL_APPEND(headB,&els[3]); 30 | LL_APPEND(headB,&els[4]); 31 | LL_APPEND(headB,&els[5]); 32 | LL_FOREACH(headB,e) { 33 | printf("%c ", e->id); 34 | } 35 | printf("\n"); 36 | 37 | LL_CONCAT(headA,headB); 38 | LL_FOREACH(headA,e) { 39 | printf("%c ", e->id); 40 | } 41 | printf("\n"); 42 | 43 | /* other variations */ 44 | headA = NULL; 45 | LL_CONCAT(headA,headB); 46 | LL_FOREACH(headA,e) { 47 | printf("%c ", e->id); 48 | } 49 | printf("\n"); 50 | headB = NULL; 51 | LL_CONCAT(headA,headB); 52 | LL_FOREACH(headA,e) { 53 | printf("%c ", e->id); 54 | } 55 | printf("\n"); 56 | headA=NULL; 57 | headB=NULL; 58 | LL_APPEND(headA,&els[0]); 59 | LL_APPEND(headB,&els[1]); 60 | LL_CONCAT(headA,headB); 61 | LL_FOREACH(headA,e) { 62 | printf("%c ", e->id); 63 | } 64 | printf("\n"); 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /tests/test64.ans: -------------------------------------------------------------------------------- 1 | DL macros 2 | a b c 3 | d e f 4 | a b c d e f 5 | d e f 6 | d e f 7 | a b 8 | -------------------------------------------------------------------------------- /tests/test64.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utlist.h" 3 | 4 | typedef struct el { 5 | int id; 6 | struct el *next, *prev; 7 | } el; 8 | 9 | int main() 10 | { 11 | int i; 12 | el els[10], *e; 13 | el *headA = NULL; 14 | el *headB = NULL; 15 | for(i=0; i<10; i++) { 16 | els[i].id=(int)'a'+i; 17 | } 18 | 19 | /* test DL macros */ 20 | printf("DL macros\n"); 21 | DL_APPEND(headA,&els[0]); 22 | DL_APPEND(headA,&els[1]); 23 | DL_APPEND(headA,&els[2]); 24 | DL_FOREACH(headA,e) { 25 | printf("%c ", e->id); 26 | } 27 | printf("\n"); 28 | 29 | DL_APPEND(headB,&els[3]); 30 | DL_APPEND(headB,&els[4]); 31 | DL_APPEND(headB,&els[5]); 32 | DL_FOREACH(headB,e) { 33 | printf("%c ", e->id); 34 | } 35 | printf("\n"); 36 | 37 | DL_CONCAT(headA,headB); 38 | DL_FOREACH(headA,e) { 39 | printf("%c ", e->id); 40 | } 41 | printf("\n"); 42 | 43 | /* other variations */ 44 | headA = NULL; 45 | DL_CONCAT(headA,headB); 46 | DL_FOREACH(headA,e) { 47 | printf("%c ", e->id); 48 | } 49 | printf("\n"); 50 | headB = NULL; 51 | DL_CONCAT(headA,headB); 52 | DL_FOREACH(headA,e) { 53 | printf("%c ", e->id); 54 | } 55 | printf("\n"); 56 | headA=NULL; 57 | headB=NULL; 58 | DL_APPEND(headA,&els[0]); 59 | DL_APPEND(headB,&els[1]); 60 | DL_CONCAT(headA,headB); 61 | DL_FOREACH(headA,e) { 62 | printf("%c ", e->id); 63 | } 64 | printf("\n"); 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /tests/test65.ans: -------------------------------------------------------------------------------- 1 | LRU deleting JOHN 2 | 0 3 | LRU deleting WILLIAM 4 | 1 5 | -------------------------------------------------------------------------------- /tests/test65.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "uthash.h" 4 | 5 | // this is an example of how to do a LRU cache in C using uthash 6 | // https://troydhanson.github.io/uthash/ 7 | // by Jehiah Czebotar 2011 - jehiah@gmail.com 8 | // this code is in the public domain http://unlicense.org/ 9 | 10 | #define MAX_CACHE_SIZE 50U /* a real value would be much larger */ 11 | 12 | struct CacheEntry { 13 | char *key; 14 | char *value; 15 | UT_hash_handle hh; 16 | }; 17 | struct CacheEntry *cache = NULL; 18 | 19 | static void add_to_cache(const char *key, const char *value) 20 | { 21 | struct CacheEntry *entry, *tmp_entry; 22 | entry = (struct CacheEntry *)malloc(sizeof(struct CacheEntry)); 23 | if (entry == NULL) { 24 | exit(-1); 25 | } 26 | entry->key = strdup(key); 27 | entry->value = strdup(value); 28 | HASH_ADD_KEYPTR(hh, cache, entry->key, strlen(entry->key), entry); 29 | 30 | // prune the cache to MAX_CACHE_SIZE 31 | if (HASH_COUNT(cache) >= MAX_CACHE_SIZE) { 32 | HASH_ITER(hh, cache, entry, tmp_entry) { 33 | // prune the first entry (loop is based on insertion order so this deletes the oldest item) 34 | printf("LRU deleting %s %s\n", entry->key, entry->value); 35 | HASH_DELETE(hh, cache, entry); 36 | free(entry->key); 37 | free(entry->value); 38 | free(entry); 39 | break; 40 | } 41 | } 42 | } 43 | 44 | /* main added by Troy D. Hanson */ 45 | int main() 46 | { 47 | char linebuf[100]; 48 | char nbuf[11]; 49 | FILE *file; 50 | unsigned int i=0; 51 | 52 | file = fopen( "test65.dat", "r" ); 53 | if (file == NULL) { 54 | perror("can't open: "); 55 | exit(-1); 56 | } 57 | 58 | while (fgets(linebuf,sizeof(linebuf),file) != NULL) { 59 | snprintf(nbuf,sizeof(nbuf),"%u",i++); 60 | add_to_cache(linebuf, nbuf); 61 | } 62 | 63 | fclose(file); 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /tests/test65.dat: -------------------------------------------------------------------------------- 1 | JOHN 2 | WILLIAM 3 | WALTER 4 | DOUGLAS 5 | GERALD 6 | FREDERICK 7 | WARREN 8 | SHANE 9 | LESTER 10 | RON 11 | HARVEY 12 | ADRIAN 13 | CODY 14 | NELSON 15 | CLIFTON 16 | WILLARD 17 | DOUG 18 | ORLANDO 19 | REX 20 | OMAR 21 | DAMON 22 | LOWELL 23 | IRVING 24 | CARROLL 25 | LAURENCE 26 | ROLANDO 27 | CARY 28 | XAVIER 29 | ISAIAH 30 | GUS 31 | JARVIS 32 | WINFRED 33 | RAYMUNDO 34 | LINCOLN 35 | CORNELL 36 | NIGEL 37 | NORMAND 38 | FRITZ 39 | DONN 40 | TRINIDAD 41 | ODIS 42 | DANNIE 43 | DARIO 44 | KENTON 45 | CHONG 46 | NEVILLE 47 | TONEY 48 | WARNER 49 | WES 50 | COLTON 51 | ARNOLDO 52 | -------------------------------------------------------------------------------- /tests/test66.ans: -------------------------------------------------------------------------------- 1 | added bob (id 0) 2 | added jack (id 1) 3 | added gary (id 2) 4 | added ty (id 3) 5 | added bo (id 4) 6 | added phil (id 5) 7 | added art (id 6) 8 | added gil (id 7) 9 | added buck (id 8) 10 | added ted (id 9) 11 | found bob (id 0) 12 | found jack (id 1) 13 | found gary (id 2) 14 | found ty (id 3) 15 | found bo (id 4) 16 | found phil (id 5) 17 | found art (id 6) 18 | found gil (id 7) 19 | found buck (id 8) 20 | found ted (id 9) 21 | -------------------------------------------------------------------------------- /tests/test66.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include 3 | #include /* malloc */ 4 | 5 | typedef struct person_t { 6 | char first_name[10]; 7 | int id; 8 | UT_hash_handle hh; 9 | } person_t; 10 | 11 | int main() 12 | { 13 | person_t *people=NULL, *person; 14 | const char **name; 15 | const char * names[] = { "bob", "jack", "gary", "ty", "bo", "phil", "art", 16 | "gil", "buck", "ted", NULL 17 | }; 18 | int id=0; 19 | 20 | for(name=names; *name!=NULL; name++) { 21 | person = (person_t*)malloc(sizeof(person_t)); 22 | if (person == NULL) { 23 | exit(-1); 24 | } 25 | strcpy(person->first_name, *name); 26 | person->id = id++; 27 | HASH_ADD_STR(people,first_name,person); 28 | printf("added %s (id %d)\n", person->first_name, person->id); 29 | } 30 | 31 | person=NULL; 32 | person_t **p=&person; 33 | 34 | for(name=names; *name!=NULL; name++) { 35 | HASH_FIND_STR(people,*name,*p); 36 | if (person != NULL) { 37 | printf("found %s (id %d)\n", person->first_name, person->id); 38 | } else { 39 | printf("failed to find %s\n", *name); 40 | } 41 | } 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /tests/test67.ans: -------------------------------------------------------------------------------- 1 | 9 2 | 8 3 | 7 4 | 6 5 | 5 6 | 4 7 | 3 8 | 2 9 | 1 10 | 0 11 | 9 12 | 8 13 | 7 14 | 6 15 | 5 16 | 4 17 | 3 18 | 2 19 | 1 20 | 0 21 | -------------------------------------------------------------------------------- /tests/test67.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utarray.h" 3 | 4 | int main() 5 | { 6 | UT_array *nums; 7 | int i, *p; 8 | 9 | utarray_new(nums,&ut_int_icd); 10 | for(i=0; i < 10; i++) { 11 | utarray_push_back(nums,&i); 12 | } 13 | 14 | for(p=(int*)utarray_back(nums); 15 | p!=NULL; 16 | p=(int*)utarray_prev(nums,p)) { 17 | printf("%d\n",*p); 18 | } 19 | 20 | /* the other form of iteration starting from NULL (back) */ 21 | p=NULL; 22 | while ( (p=(int*)utarray_prev(nums,p)) != NULL ) { 23 | printf("%d\n",*p); 24 | } 25 | 26 | 27 | utarray_free(nums); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /tests/test68.ans: -------------------------------------------------------------------------------- 1 | DL replace elem 2 | a b c d 3 | e b c d 4 | f b c d 5 | f b c g 6 | f b c h 7 | f i j h 8 | k l m n 9 | s 10 | t 11 | -------------------------------------------------------------------------------- /tests/test68.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "utlist.h" 4 | 5 | typedef struct el { 6 | int id; 7 | struct el *next, *prev; 8 | } el; 9 | 10 | int main() 11 | { 12 | int i; 13 | el els[20], *e, *tmp; 14 | el *headA = NULL; 15 | el *headB = NULL; 16 | for(i=0; i<20; i++) { 17 | els[i].id=(int)'a'+i; 18 | } 19 | 20 | /* test DL macros */ 21 | printf("DL replace elem\n"); 22 | DL_APPEND(headA,&els[0]); 23 | DL_APPEND(headA,&els[1]); 24 | DL_APPEND(headA,&els[2]); 25 | DL_APPEND(headA,&els[3]); 26 | DL_FOREACH(headA,e) { 27 | printf("%c ", e->id); 28 | } 29 | printf("\n"); 30 | 31 | /* replace head elem */ 32 | DL_REPLACE_ELEM(headA, &els[0], &els[4]); 33 | DL_FOREACH(headA,e) { 34 | printf("%c ", e->id); 35 | } 36 | printf("\n"); 37 | DL_REPLACE_ELEM(headA, &els[4], &els[5]); 38 | DL_FOREACH(headA,e) { 39 | printf("%c ", e->id); 40 | } 41 | printf("\n"); 42 | 43 | /* replace last elem */ 44 | DL_REPLACE_ELEM(headA, &els[3], &els[6]); 45 | DL_FOREACH(headA,e) { 46 | printf("%c ", e->id); 47 | } 48 | printf("\n"); 49 | DL_REPLACE_ELEM(headA, &els[6], &els[7]); 50 | DL_FOREACH(headA,e) { 51 | printf("%c ", e->id); 52 | } 53 | printf("\n"); 54 | 55 | /* replace middle elem */ 56 | DL_REPLACE_ELEM(headA, &els[1], &els[8]); 57 | DL_REPLACE_ELEM(headA, &els[2], &els[9]); 58 | DL_FOREACH(headA,e) { 59 | printf("%c ", e->id); 60 | } 61 | printf("\n"); 62 | 63 | /* replace all just to be sure the list is intact... */ 64 | i = 10; 65 | DL_FOREACH_SAFE(headA, e, tmp) { 66 | DL_REPLACE_ELEM(headA, e, &els[i]); 67 | i++; 68 | } 69 | DL_FOREACH(headA,e) { 70 | printf("%c ", e->id); 71 | } 72 | printf("\n"); 73 | 74 | /* single elem */ 75 | DL_APPEND(headB, &els[18]); 76 | DL_FOREACH(headB,e) { 77 | printf("%c ", e->id); 78 | } 79 | printf("\n"); 80 | DL_REPLACE_ELEM(headB, &els[18], &els[19]); 81 | DL_FOREACH(headB,e) { 82 | printf("%c ", e->id); 83 | } 84 | printf("\n"); 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /tests/test69.ans: -------------------------------------------------------------------------------- 1 | DL prepend elem 2 | a b c d 3 | e a b c d 4 | f e a b c d 5 | f e a b c g d 6 | f e a b c h g d 7 | f e a b i j c h g d 8 | k f l e m a n b o i p j q c r h s g t d 9 | u 10 | v u 11 | w v u 12 | -------------------------------------------------------------------------------- /tests/test69.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "utlist.h" 4 | 5 | typedef struct el { 6 | int id; 7 | struct el *next, *prev; 8 | } el; 9 | 10 | int main() 11 | { 12 | int i; 13 | el els[26], *e, *tmp; 14 | el *headA = NULL; 15 | el *headB = NULL; 16 | for(i=0; i<25; i++) { 17 | els[i].id=(int)'a'+i; 18 | } 19 | 20 | /* test DL macros */ 21 | printf("DL prepend elem\n"); 22 | DL_APPEND(headA,&els[0]); 23 | DL_APPEND(headA,&els[1]); 24 | DL_APPEND(headA,&els[2]); 25 | DL_APPEND(headA,&els[3]); 26 | DL_FOREACH(headA,e) { 27 | printf("%c ", e->id); 28 | } 29 | printf("\n"); 30 | 31 | /* prepend head elem */ 32 | DL_PREPEND_ELEM(headA, &els[0], &els[4]); 33 | DL_FOREACH(headA,e) { 34 | printf("%c ", e->id); 35 | } 36 | printf("\n"); 37 | DL_PREPEND_ELEM(headA, &els[4], &els[5]); 38 | DL_FOREACH(headA,e) { 39 | printf("%c ", e->id); 40 | } 41 | printf("\n"); 42 | 43 | /* prepend last elem */ 44 | DL_PREPEND_ELEM(headA, &els[3], &els[6]); 45 | DL_FOREACH(headA,e) { 46 | printf("%c ", e->id); 47 | } 48 | printf("\n"); 49 | DL_PREPEND_ELEM(headA, &els[6], &els[7]); 50 | DL_FOREACH(headA,e) { 51 | printf("%c ", e->id); 52 | } 53 | printf("\n"); 54 | 55 | /* prepend middle elem */ 56 | DL_PREPEND_ELEM(headA, &els[2], &els[8]); 57 | DL_PREPEND_ELEM(headA, &els[2], &els[9]); 58 | DL_FOREACH(headA,e) { 59 | printf("%c ", e->id); 60 | } 61 | printf("\n"); 62 | 63 | /* prepend all just to be sure the list is intact... */ 64 | i = 10; 65 | DL_FOREACH_SAFE(headA, e, tmp) { 66 | DL_PREPEND_ELEM(headA, e, &els[i]); 67 | i++; 68 | } 69 | DL_FOREACH(headA,e) { 70 | printf("%c ", e->id); 71 | } 72 | printf("\n"); 73 | 74 | /* single elem */ 75 | DL_APPEND(headB, &els[20]); 76 | DL_FOREACH(headB,e) { 77 | printf("%c ", e->id); 78 | } 79 | printf("\n"); 80 | DL_PREPEND_ELEM(headB, &els[20], &els[21]); 81 | DL_FOREACH(headB,e) { 82 | printf("%c ", e->id); 83 | } 84 | printf("\n"); 85 | DL_PREPEND_ELEM(headB, &els[21], &els[22]); 86 | DL_FOREACH(headB,e) { 87 | printf("%c ", e->id); 88 | } 89 | printf("\n"); 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /tests/test7.ans: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/troydhanson/uthash/af6e637f19c102167fb914b9ebcc171389270b48/tests/test7.ans -------------------------------------------------------------------------------- /tests/test7.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | 6 | typedef struct example_user_t { 7 | int id; 8 | int cookie; 9 | UT_hash_handle hh; 10 | } example_user_t; 11 | 12 | int main() 13 | { 14 | int i; 15 | example_user_t *user, *tmp, *users=NULL; 16 | 17 | /* create elements */ 18 | for(i=0; i<1000; i++) { 19 | user = (example_user_t*)malloc(sizeof(example_user_t)); 20 | if (user == NULL) { 21 | exit(-1); 22 | } 23 | user->id = i; 24 | user->cookie = i*i; 25 | HASH_ADD_INT(users,id,user); 26 | } 27 | 28 | /* delete each ID */ 29 | for(i=0; i<1000; i++) { 30 | HASH_FIND_INT(users,&i,tmp); 31 | if (tmp != NULL) { 32 | HASH_DEL(users,tmp); 33 | free(tmp); 34 | } else { 35 | printf("user id %d not found\n", i); 36 | } 37 | } 38 | 39 | /* show the hash */ 40 | for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { 41 | printf("user %d, cookie %d\n", user->id, user->cookie); 42 | } 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /tests/test70.ans: -------------------------------------------------------------------------------- 1 | LL replace elem 2 | a b c d 3 | e b c d 4 | f b c d 5 | f b c g 6 | f b c h 7 | f i j h 8 | k l m n 9 | s 10 | t 11 | -------------------------------------------------------------------------------- /tests/test70.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "utlist.h" 4 | 5 | typedef struct el { 6 | int id; 7 | struct el *next, *prev; 8 | } el; 9 | 10 | int main() 11 | { 12 | int i; 13 | el els[20], *e, *tmp; 14 | el *headA = NULL; 15 | el *headB = NULL; 16 | for(i=0; i<20; i++) { 17 | els[i].id=(int)'a'+i; 18 | } 19 | 20 | /* test LL macros */ 21 | printf("LL replace elem\n"); 22 | LL_APPEND(headA,&els[0]); 23 | LL_APPEND(headA,&els[1]); 24 | LL_APPEND(headA,&els[2]); 25 | LL_APPEND(headA,&els[3]); 26 | LL_FOREACH(headA,e) { 27 | printf("%c ", e->id); 28 | } 29 | printf("\n"); 30 | 31 | /* replace head elem */ 32 | LL_REPLACE_ELEM(headA, &els[0], &els[4]); 33 | LL_FOREACH(headA,e) { 34 | printf("%c ", e->id); 35 | } 36 | printf("\n"); 37 | LL_REPLACE_ELEM(headA, &els[4], &els[5]); 38 | LL_FOREACH(headA,e) { 39 | printf("%c ", e->id); 40 | } 41 | printf("\n"); 42 | 43 | /* replace last elem */ 44 | LL_REPLACE_ELEM(headA, &els[3], &els[6]); 45 | LL_FOREACH(headA,e) { 46 | printf("%c ", e->id); 47 | } 48 | printf("\n"); 49 | LL_REPLACE_ELEM(headA, &els[6], &els[7]); 50 | LL_FOREACH(headA,e) { 51 | printf("%c ", e->id); 52 | } 53 | printf("\n"); 54 | 55 | /* replace middle elem */ 56 | LL_REPLACE_ELEM(headA, &els[1], &els[8]); 57 | LL_REPLACE_ELEM(headA, &els[2], &els[9]); 58 | LL_FOREACH(headA,e) { 59 | printf("%c ", e->id); 60 | } 61 | printf("\n"); 62 | 63 | /* replace all just to be sure the list is intact... */ 64 | i = 10; 65 | LL_FOREACH_SAFE(headA, e, tmp) { 66 | LL_REPLACE_ELEM(headA, e, &els[i]); 67 | i++; 68 | } 69 | LL_FOREACH(headA,e) { 70 | printf("%c ", e->id); 71 | } 72 | printf("\n"); 73 | 74 | /* single elem */ 75 | LL_APPEND(headB, &els[18]); 76 | LL_FOREACH(headB,e) { 77 | printf("%c ", e->id); 78 | } 79 | printf("\n"); 80 | LL_REPLACE_ELEM(headB, &els[18], &els[19]); 81 | LL_FOREACH(headB,e) { 82 | printf("%c ", e->id); 83 | } 84 | printf("\n"); 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /tests/test71.ans: -------------------------------------------------------------------------------- 1 | LL prepend elem 2 | a b c d 3 | e a b c d 4 | f e a b c d 5 | f e a b c g d 6 | f e a b c h g d 7 | f e a b i j c h g d 8 | k f l e m a n b o i p j q c r h s g t d 9 | u 10 | v u 11 | w v u 12 | -------------------------------------------------------------------------------- /tests/test71.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "utlist.h" 4 | 5 | typedef struct el { 6 | int id; 7 | struct el *next, *prev; 8 | } el; 9 | 10 | int main() 11 | { 12 | int i; 13 | el els[26], *e, *tmp; 14 | el *headA = NULL; 15 | el *headB = NULL; 16 | for(i=0; i<25; i++) { 17 | els[i].id=(int)'a'+i; 18 | } 19 | 20 | /* test LL macros */ 21 | printf("LL prepend elem\n"); 22 | LL_APPEND(headA,&els[0]); 23 | LL_APPEND(headA,&els[1]); 24 | LL_APPEND(headA,&els[2]); 25 | LL_APPEND(headA,&els[3]); 26 | LL_FOREACH(headA,e) { 27 | printf("%c ", e->id); 28 | } 29 | printf("\n"); 30 | 31 | /* prepend head elem */ 32 | LL_PREPEND_ELEM(headA, &els[0], &els[4]); 33 | LL_FOREACH(headA,e) { 34 | printf("%c ", e->id); 35 | } 36 | printf("\n"); 37 | LL_PREPEND_ELEM(headA, &els[4], &els[5]); 38 | LL_FOREACH(headA,e) { 39 | printf("%c ", e->id); 40 | } 41 | printf("\n"); 42 | 43 | /* prepend last elem */ 44 | LL_PREPEND_ELEM(headA, &els[3], &els[6]); 45 | LL_FOREACH(headA,e) { 46 | printf("%c ", e->id); 47 | } 48 | printf("\n"); 49 | LL_PREPEND_ELEM(headA, &els[6], &els[7]); 50 | LL_FOREACH(headA,e) { 51 | printf("%c ", e->id); 52 | } 53 | printf("\n"); 54 | 55 | /* prepend middle elem */ 56 | LL_PREPEND_ELEM(headA, &els[2], &els[8]); 57 | LL_PREPEND_ELEM(headA, &els[2], &els[9]); 58 | LL_FOREACH(headA,e) { 59 | printf("%c ", e->id); 60 | } 61 | printf("\n"); 62 | 63 | /* prepend all just to be sure the list is intact... */ 64 | i = 10; 65 | LL_FOREACH_SAFE(headA, e, tmp) { 66 | LL_PREPEND_ELEM(headA, e, &els[i]); 67 | i++; 68 | } 69 | LL_FOREACH(headA,e) { 70 | printf("%c ", e->id); 71 | } 72 | printf("\n"); 73 | 74 | /* single elem */ 75 | LL_APPEND(headB, &els[20]); 76 | LL_FOREACH(headB,e) { 77 | printf("%c ", e->id); 78 | } 79 | printf("\n"); 80 | LL_PREPEND_ELEM(headB, &els[20], &els[21]); 81 | LL_FOREACH(headB,e) { 82 | printf("%c ", e->id); 83 | } 84 | printf("\n"); 85 | LL_PREPEND_ELEM(headB, &els[21], &els[22]); 86 | LL_FOREACH(headB,e) { 87 | printf("%c ", e->id); 88 | } 89 | printf("\n"); 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /tests/test72.ans: -------------------------------------------------------------------------------- 1 | CDL replace elem 2 | a b c d 3 | e b c d 4 | f b c d 5 | f b c g 6 | f b c h 7 | f i j h 8 | k l m n 9 | s 10 | t 11 | -------------------------------------------------------------------------------- /tests/test72.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "utlist.h" 4 | 5 | typedef struct el { 6 | int id; 7 | struct el *next, *prev; 8 | } el; 9 | 10 | int main() 11 | { 12 | int i; 13 | el els[20], *e, *tmp, *tmp2; 14 | el *headA = NULL; 15 | el *headB = NULL; 16 | for(i=0; i<20; i++) { 17 | els[i].id=(int)'a'+i; 18 | } 19 | 20 | /* test CDL macros */ 21 | printf("CDL replace elem\n"); 22 | CDL_PREPEND(headA,&els[3]); 23 | CDL_PREPEND(headA,&els[2]); 24 | CDL_PREPEND(headA,&els[1]); 25 | CDL_PREPEND(headA,&els[0]); 26 | CDL_FOREACH(headA,e) { 27 | printf("%c ", e->id); 28 | } 29 | printf("\n"); 30 | 31 | /* replace head elem */ 32 | CDL_REPLACE_ELEM(headA, &els[0], &els[4]); 33 | CDL_FOREACH(headA,e) { 34 | printf("%c ", e->id); 35 | } 36 | printf("\n"); 37 | CDL_REPLACE_ELEM(headA, &els[4], &els[5]); 38 | CDL_FOREACH(headA,e) { 39 | printf("%c ", e->id); 40 | } 41 | printf("\n"); 42 | 43 | /* replace last elem */ 44 | CDL_REPLACE_ELEM(headA, &els[3], &els[6]); 45 | CDL_FOREACH(headA,e) { 46 | printf("%c ", e->id); 47 | } 48 | printf("\n"); 49 | CDL_REPLACE_ELEM(headA, &els[6], &els[7]); 50 | CDL_FOREACH(headA,e) { 51 | printf("%c ", e->id); 52 | } 53 | printf("\n"); 54 | 55 | /* replace middle elem */ 56 | CDL_REPLACE_ELEM(headA, &els[1], &els[8]); 57 | CDL_REPLACE_ELEM(headA, &els[2], &els[9]); 58 | CDL_FOREACH(headA,e) { 59 | printf("%c ", e->id); 60 | } 61 | printf("\n"); 62 | 63 | /* replace all just to be sure the list is intact... */ 64 | i = 10; 65 | CDL_FOREACH_SAFE(headA, e, tmp, tmp2) { 66 | CDL_REPLACE_ELEM(headA, e, &els[i]); 67 | i++; 68 | } 69 | CDL_FOREACH(headA,e) { 70 | printf("%c ", e->id); 71 | } 72 | printf("\n"); 73 | 74 | /* single elem */ 75 | CDL_PREPEND(headB, &els[18]); 76 | CDL_FOREACH(headB,e) { 77 | printf("%c ", e->id); 78 | } 79 | printf("\n"); 80 | CDL_REPLACE_ELEM(headB, &els[18], &els[19]); 81 | CDL_FOREACH(headB,e) { 82 | printf("%c ", e->id); 83 | } 84 | printf("\n"); 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /tests/test73.ans: -------------------------------------------------------------------------------- 1 | CDL prepend elem 2 | a b c d 3 | e a b c d 4 | f e a b c d 5 | f e a b c g d 6 | f e a b c h g d 7 | f e a b i j c h g d 8 | k f l e m a n b o i p j q c r h s g t d 9 | u 10 | v u 11 | w v u 12 | -------------------------------------------------------------------------------- /tests/test73.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "utlist.h" 4 | 5 | typedef struct el { 6 | int id; 7 | struct el *next, *prev; 8 | } el; 9 | 10 | int main() 11 | { 12 | int i; 13 | el els[26], *e, *tmp, *tmp2; 14 | el *headA = NULL; 15 | el *headB = NULL; 16 | for(i=0; i<25; i++) { 17 | els[i].id=(int)'a'+i; 18 | } 19 | 20 | /* test CDL macros */ 21 | printf("CDL prepend elem\n"); 22 | CDL_PREPEND(headA,&els[3]); 23 | CDL_PREPEND(headA,&els[2]); 24 | CDL_PREPEND(headA,&els[1]); 25 | CDL_PREPEND(headA,&els[0]); 26 | CDL_FOREACH(headA,e) { 27 | printf("%c ", e->id); 28 | } 29 | printf("\n"); 30 | 31 | /* prepend head elem */ 32 | CDL_PREPEND_ELEM(headA, &els[0], &els[4]); 33 | CDL_FOREACH(headA,e) { 34 | printf("%c ", e->id); 35 | } 36 | printf("\n"); 37 | CDL_PREPEND_ELEM(headA, &els[4], &els[5]); 38 | CDL_FOREACH(headA,e) { 39 | printf("%c ", e->id); 40 | } 41 | printf("\n"); 42 | 43 | /* prepend last elem */ 44 | CDL_PREPEND_ELEM(headA, &els[3], &els[6]); 45 | CDL_FOREACH(headA,e) { 46 | printf("%c ", e->id); 47 | } 48 | printf("\n"); 49 | CDL_PREPEND_ELEM(headA, &els[6], &els[7]); 50 | CDL_FOREACH(headA,e) { 51 | printf("%c ", e->id); 52 | } 53 | printf("\n"); 54 | 55 | /* prepend middle elem */ 56 | CDL_PREPEND_ELEM(headA, &els[2], &els[8]); 57 | CDL_PREPEND_ELEM(headA, &els[2], &els[9]); 58 | CDL_FOREACH(headA,e) { 59 | printf("%c ", e->id); 60 | } 61 | printf("\n"); 62 | 63 | /* prepend all just to be sure the list is intact... */ 64 | i = 10; 65 | CDL_FOREACH_SAFE(headA, e, tmp, tmp2) { 66 | CDL_PREPEND_ELEM(headA, e, &els[i]); 67 | i++; 68 | } 69 | CDL_FOREACH(headA,e) { 70 | printf("%c ", e->id); 71 | } 72 | printf("\n"); 73 | 74 | /* single elem */ 75 | CDL_PREPEND(headB, &els[20]); 76 | CDL_FOREACH(headB,e) { 77 | printf("%c ", e->id); 78 | } 79 | printf("\n"); 80 | CDL_PREPEND_ELEM(headB, &els[20], &els[21]); 81 | CDL_FOREACH(headB,e) { 82 | printf("%c ", e->id); 83 | } 84 | printf("\n"); 85 | CDL_PREPEND_ELEM(headB, &els[21], &els[22]); 86 | CDL_FOREACH(headB,e) { 87 | printf("%c ", e->id); 88 | } 89 | printf("\n"); 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /tests/test74.ans: -------------------------------------------------------------------------------- 1 | "There are two needle" len=55 2 | "needle" len=8 3 | utstring_find()=14 4 | utstring_find()=46 5 | utstring_find()=-1 6 | FindCnt=2 7 | -------------------------------------------------------------------------------- /tests/test74.c: -------------------------------------------------------------------------------- 1 | #include /* printf */ 2 | #include "utstring.h" 3 | 4 | int main() 5 | { 6 | UT_string *s,*t; 7 | char V_TestStr[] = "There are two needle\0s in this \0haystack with needle\0s."; 8 | char V_NeedleStr[] = "needle\0s"; 9 | long V_FindPos; 10 | size_t V_FindCnt; 11 | 12 | 13 | utstring_new(s); 14 | utstring_new(t); 15 | 16 | utstring_bincpy(s, V_TestStr, sizeof(V_TestStr)-1); 17 | printf("\"%s\" len=%u\n", utstring_body(s), (unsigned)utstring_len(s)); 18 | utstring_bincpy(t, V_NeedleStr, sizeof(V_NeedleStr)-1); 19 | printf("\"%s\" len=%u\n", utstring_body(t), (unsigned)utstring_len(t)); 20 | 21 | V_FindCnt = 0; 22 | V_FindPos = 0; 23 | do { 24 | V_FindPos = utstring_find(s, 25 | V_FindPos, 26 | utstring_body(t), 27 | utstring_len(t)); 28 | printf("utstring_find()=%ld\n", V_FindPos); 29 | if (V_FindPos >= 0) { 30 | V_FindPos++; 31 | V_FindCnt++; 32 | } 33 | } while (V_FindPos >= 0); 34 | printf("FindCnt=%u\n", (unsigned)V_FindCnt); 35 | 36 | utstring_free(s); 37 | utstring_free(t); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /tests/test75.ans: -------------------------------------------------------------------------------- 1 | "There are two needle" len=55 2 | "needle" len=8 3 | utstring_findR()=46 4 | utstring_findR()=14 5 | utstring_findR()=-1 6 | FindCnt=2 7 | -------------------------------------------------------------------------------- /tests/test75.c: -------------------------------------------------------------------------------- 1 | #include /* printf */ 2 | #include "utstring.h" 3 | 4 | int main() 5 | { 6 | UT_string *s,*t; 7 | char V_TestStr[] = "There are two needle\0s in this \0haystack with needle\0s."; 8 | char V_NeedleStr[] = "needle\0s"; 9 | long V_FindPos; 10 | size_t V_FindCnt; 11 | 12 | 13 | utstring_new(s); 14 | utstring_new(t); 15 | 16 | utstring_bincpy(s, V_TestStr, sizeof(V_TestStr)-1); 17 | printf("\"%s\" len=%u\n", utstring_body(s), (unsigned)utstring_len(s)); 18 | utstring_bincpy(t, V_NeedleStr, sizeof(V_NeedleStr)-1); 19 | printf("\"%s\" len=%u\n", utstring_body(t), (unsigned)utstring_len(t)); 20 | 21 | V_FindCnt = 0; 22 | V_FindPos = -1; 23 | do { 24 | V_FindPos = utstring_findR(s, 25 | V_FindPos, 26 | utstring_body(t), 27 | utstring_len(t)); 28 | printf("utstring_findR()=%ld\n", V_FindPos); 29 | if (V_FindPos >= 0) { 30 | V_FindPos--; 31 | V_FindCnt++; 32 | } 33 | } while (V_FindPos >= 0); 34 | printf("FindCnt=%u\n", (unsigned)V_FindCnt); 35 | 36 | utstring_free(s); 37 | utstring_free(t); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /tests/test76.ans: -------------------------------------------------------------------------------- 1 | "There are two needle" len=55 2 | "needle" len=8 3 | utstring_find()=14 4 | utstring_find()=46 5 | utstring_find()=-1 6 | FindCnt=2 7 | -------------------------------------------------------------------------------- /tests/test76.c: -------------------------------------------------------------------------------- 1 | #include /* printf */ 2 | #include "utstring.h" 3 | 4 | int main() 5 | { 6 | UT_string *s,*t; 7 | char V_TestStr[] = "There are two needle\0s in this \0haystack with needle\0s."; 8 | char V_NeedleStr[] = "needle\0s"; 9 | long *V_KMP_Table; 10 | long V_FindPos; 11 | size_t V_StartPos = 0; 12 | size_t V_FindCnt = 0; 13 | 14 | 15 | utstring_new(s); 16 | utstring_new(t); 17 | 18 | utstring_bincpy(s, V_TestStr, sizeof(V_TestStr)-1); 19 | printf("\"%s\" len=%u\n", utstring_body(s), (unsigned)utstring_len(s)); 20 | utstring_bincpy(t, V_NeedleStr, sizeof(V_NeedleStr)-1); 21 | printf("\"%s\" len=%u\n", utstring_body(t), (unsigned)utstring_len(t)); 22 | 23 | V_KMP_Table = (long *)malloc(sizeof(long) * (utstring_len(t) + 1)); 24 | if (V_KMP_Table != NULL) { 25 | _utstring_BuildTable(utstring_body(t), utstring_len(t), V_KMP_Table); 26 | 27 | do { 28 | V_FindPos = _utstring_find(utstring_body(s) + V_StartPos, 29 | utstring_len(s) - V_StartPos, 30 | utstring_body(t), 31 | utstring_len(t), 32 | V_KMP_Table); 33 | if (V_FindPos >= 0) { 34 | V_FindPos += V_StartPos; 35 | V_FindCnt++; 36 | V_StartPos = V_FindPos + 1; 37 | } 38 | printf("utstring_find()=%ld\n", V_FindPos); 39 | } while (V_FindPos >= 0); 40 | printf("FindCnt=%u\n", (unsigned)V_FindCnt); 41 | 42 | free(V_KMP_Table); 43 | } else { 44 | printf("malloc() failed...\n"); 45 | } 46 | 47 | utstring_free(s); 48 | utstring_free(t); 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /tests/test77.ans: -------------------------------------------------------------------------------- 1 | "There are two needle" len=55 2 | "needle" len=8 3 | utstring_find()=46 4 | utstring_find()=14 5 | utstring_find()=-1 6 | FindCnt=2 7 | expect 15 15 8 | expect 4 4 9 | expect -1 -1 10 | expect 11 11 11 | expect 4 4 12 | expect 11 11 13 | expect 0 0 14 | -------------------------------------------------------------------------------- /tests/test77.c: -------------------------------------------------------------------------------- 1 | #include /* printf */ 2 | #include "utstring.h" 3 | 4 | int main() 5 | { 6 | UT_string *s,*t; 7 | char V_TestStr[] = "There are two needle\0s in this \0haystack with needle\0s."; 8 | char V_NeedleStr[] = "needle\0s"; 9 | long *V_KMP_Table; 10 | long V_FindPos; 11 | size_t V_StartPos; 12 | size_t V_FindCnt = 0; 13 | 14 | 15 | utstring_new(s); 16 | utstring_new(t); 17 | 18 | utstring_bincpy(s, V_TestStr, sizeof(V_TestStr)-1); 19 | printf("\"%s\" len=%u\n", utstring_body(s), (unsigned)utstring_len(s)); 20 | utstring_bincpy(t, V_NeedleStr, sizeof(V_NeedleStr)-1); 21 | printf("\"%s\" len=%u\n", utstring_body(t), (unsigned)utstring_len(t)); 22 | 23 | V_KMP_Table = (long *)malloc(sizeof(long) * (utstring_len(t) + 1)); 24 | if (V_KMP_Table != NULL) { 25 | _utstring_BuildTableR(utstring_body(t), utstring_len(t), V_KMP_Table); 26 | 27 | V_StartPos = utstring_len(s) - 1; 28 | do { 29 | V_FindPos = _utstring_findR(utstring_body(s), 30 | V_StartPos + 1, 31 | utstring_body(t), 32 | utstring_len(t), 33 | V_KMP_Table); 34 | if (V_FindPos >= 0) { 35 | V_FindCnt++; 36 | V_StartPos = V_FindPos - 1; 37 | } 38 | printf("utstring_find()=%ld\n", V_FindPos); 39 | } while (V_FindPos >= 0); 40 | printf("FindCnt=%u\n", (unsigned)V_FindCnt); 41 | 42 | free(V_KMP_Table); 43 | } else { 44 | printf("malloc() failed...\n"); 45 | } 46 | 47 | utstring_free(t); 48 | utstring_clear(s); 49 | utstring_printf(s,"ABC ABCDAB ABCDABCDABDE"); 50 | int o; 51 | 52 | o=utstring_find( s, -9, "ABC", 3 ) ; 53 | printf("expect 15 %d\n",o); 54 | o=utstring_find( s, 3, "ABC", 3 ) ; 55 | printf("expect 4 %d\n",o); 56 | o=utstring_find( s, 16, "ABC", 3 ) ; 57 | printf("expect -1 %d\n",o); 58 | o=utstring_findR( s, -9, "ABC", 3 ) ; 59 | printf("expect 11 %d\n",o); 60 | o=utstring_findR( s, 12, "ABC", 3 ) ; 61 | printf("expect 4 %d\n",o); 62 | o=utstring_findR( s, 13, "ABC", 3 ) ; 63 | printf("expect 11 %d\n",o); 64 | o=utstring_findR( s, 2, "ABC", 3 ) ; 65 | printf("expect 0 %d\n",o); 66 | 67 | utstring_free(s); 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /tests/test78.ans: -------------------------------------------------------------------------------- 1 | CDL macros 2 | c b a 3 | advancing head pointer 4 | b a c 5 | b a c b a c b a c b 6 | b c a b c a b c a b 7 | deleting b 8 | a c 9 | deleting (a) 10 | c 11 | deleting (c) 12 | 13 | DL macros 14 | a b c 15 | deleting tail c 16 | a b 17 | deleting head a 18 | b 19 | deleting head b 20 | 21 | LL macros 22 | a b c 23 | deleting tail c 24 | a b 25 | deleting head a 26 | b 27 | deleting head b 28 | 29 | -------------------------------------------------------------------------------- /tests/test78.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utlist.h" 3 | 4 | typedef struct el { 5 | int id; 6 | struct el *Next, *Prev; 7 | } el; 8 | 9 | int main() 10 | { 11 | int i; 12 | el els[10], *e; 13 | el *head = NULL; 14 | for(i=0; i<10; i++) { 15 | els[i].id=(int)'a'+i; 16 | } 17 | 18 | /* test CDL macros */ 19 | printf("CDL macros\n"); 20 | CDL_PREPEND2(head,&els[0],Prev,Next); 21 | CDL_PREPEND2(head,&els[1],Prev,Next); 22 | CDL_PREPEND2(head,&els[2],Prev,Next); 23 | CDL_FOREACH2(head,e,Next) { 24 | printf("%c ", e->id); 25 | } 26 | printf("\n"); 27 | 28 | /* point head to head->next */ 29 | printf("advancing head pointer\n"); 30 | head = head->Next; 31 | CDL_FOREACH2(head,e,Next) { 32 | printf("%c ", e->id); 33 | } 34 | printf("\n"); 35 | 36 | /* follow circular loop a few times */ 37 | for(i=0,e=head; e && i<10; i++,e=e->Next) { 38 | printf("%c ", e->id); 39 | } 40 | printf("\n"); 41 | 42 | /* follow circular loop backwards a few times */ 43 | for(i=0,e=head; e && i<10; i++,e=e->Prev) { 44 | printf("%c ", e->id); 45 | } 46 | printf("\n"); 47 | 48 | printf("deleting b\n"); 49 | CDL_DELETE2(head,&els[1],Prev,Next); 50 | CDL_FOREACH2(head,e,Next) { 51 | printf("%c ", e->id); 52 | } 53 | printf("\n"); 54 | printf("deleting (a)\n"); 55 | CDL_DELETE2(head,&els[0],Prev,Next); 56 | CDL_FOREACH2(head,e,Next) { 57 | printf("%c ", e->id); 58 | } 59 | printf("\n"); 60 | printf("deleting (c)\n"); 61 | CDL_DELETE2(head,&els[2],Prev,Next); 62 | CDL_FOREACH2(head,e,Next) { 63 | printf("%c ", e->id); 64 | } 65 | printf("\n"); 66 | 67 | /* test DL macros */ 68 | printf("DL macros\n"); 69 | DL_APPEND2(head,&els[0],Prev,Next); 70 | DL_APPEND2(head,&els[1],Prev,Next); 71 | DL_APPEND2(head,&els[2],Prev,Next); 72 | DL_FOREACH2(head,e,Next) { 73 | printf("%c ", e->id); 74 | } 75 | printf("\n"); 76 | 77 | printf("deleting tail c\n"); 78 | DL_DELETE2(head,&els[2],Prev,Next); 79 | DL_FOREACH2(head,e,Next) { 80 | printf("%c ", e->id); 81 | } 82 | printf("\n"); 83 | 84 | printf("deleting head a\n"); 85 | DL_DELETE2(head,&els[0],Prev,Next); 86 | DL_FOREACH2(head,e,Next) { 87 | printf("%c ", e->id); 88 | } 89 | printf("\n"); 90 | 91 | printf("deleting head b\n"); 92 | DL_DELETE2(head,&els[1],Prev,Next); 93 | DL_FOREACH2(head,e,Next) { 94 | printf("%c ", e->id); 95 | } 96 | printf("\n"); 97 | 98 | /* test LL macros */ 99 | printf("LL macros\n"); 100 | LL_APPEND2(head,&els[0],Next); 101 | LL_APPEND2(head,&els[1],Next); 102 | LL_APPEND2(head,&els[2],Next); 103 | LL_FOREACH2(head,e,Next) { 104 | printf("%c ", e->id); 105 | } 106 | printf("\n"); 107 | 108 | printf("deleting tail c\n"); 109 | LL_DELETE2(head,&els[2],Next); 110 | LL_FOREACH2(head,e,Next) { 111 | printf("%c ", e->id); 112 | } 113 | printf("\n"); 114 | 115 | printf("deleting head a\n"); 116 | LL_DELETE2(head,&els[0],Next); 117 | LL_FOREACH2(head,e,Next) { 118 | printf("%c ", e->id); 119 | } 120 | printf("\n"); 121 | 122 | printf("deleting head b\n"); 123 | LL_DELETE2(head,&els[1],Next); 124 | LL_FOREACH2(head,e,Next) { 125 | printf("%c ", e->id); 126 | } 127 | printf("\n"); 128 | 129 | return 0; 130 | } 131 | -------------------------------------------------------------------------------- /tests/test79.ans: -------------------------------------------------------------------------------- 1 | added 10 100 2 | id 10, tag 100 3 | added 11 101 4 | id 10, tag 100 5 | id 11, tag 101 6 | replaced 11 that had tag 101 with tag 102 7 | id 10, tag 100 8 | id 11, tag 102 9 | -------------------------------------------------------------------------------- /tests/test79.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "uthash.h" 4 | 5 | typedef struct hs_t { 6 | int id; 7 | int tag; 8 | UT_hash_handle hh; 9 | } hs_t; 10 | 11 | 12 | static void pr(hs_t **hdpp) 13 | { 14 | hs_t *el, *tmp, *hdp = *hdpp; 15 | HASH_ITER(hh, hdp, el, tmp) { 16 | printf("id %d, tag %d\n",el->id,el->tag); 17 | } 18 | } 19 | 20 | int main() 21 | { 22 | 23 | hs_t *hs_head=NULL, *tmp, *replaced=NULL; 24 | 25 | tmp = (hs_t*)malloc(sizeof(hs_t)); 26 | if (tmp == NULL) { 27 | exit(-1); 28 | } 29 | tmp->id = 10; 30 | tmp->tag = 100; 31 | HASH_REPLACE_INT(hs_head,id,tmp,replaced); 32 | if(replaced == NULL) { 33 | printf("added %d %d\n",tmp->id,tmp->tag); 34 | } else { 35 | printf("ERROR, ended up replacing a value, replaced: %p\n",(void*)replaced); 36 | } 37 | 38 | pr(&hs_head); 39 | 40 | tmp = (hs_t*)malloc(sizeof(hs_t)); 41 | if (tmp == NULL) { 42 | exit(-1); 43 | } 44 | tmp->id=11; 45 | tmp->tag = 101; 46 | HASH_REPLACE_INT(hs_head,id,tmp,replaced); 47 | if(replaced == NULL) { 48 | printf("added %d %d\n",tmp->id,tmp->tag); 49 | } else { 50 | printf("ERROR, ended up replacing a value, replaced: %p\n",(void*)replaced); 51 | } 52 | 53 | pr(&hs_head); 54 | 55 | tmp = (hs_t*)malloc(sizeof(hs_t)); 56 | if (tmp == NULL) { 57 | exit(-1); 58 | } 59 | tmp->id=11; 60 | tmp->tag = 102; 61 | HASH_REPLACE_INT(hs_head,id,tmp,replaced); 62 | if(replaced == NULL) { 63 | printf("ERROR, exected to replace a value with key: %d\n",tmp->id); 64 | } else { 65 | printf("replaced %d that had tag %d with tag %d\n",tmp->id,replaced->tag,tmp->tag); 66 | } 67 | 68 | pr(&hs_head); 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /tests/test8.ans: -------------------------------------------------------------------------------- 1 | num_items in hash: 1 2 | num_items in hash: 2 3 | num_items in hash: 3 4 | num_items in hash: 4 5 | num_items in hash: 5 6 | num_items in hash: 6 7 | num_items in hash: 7 8 | num_items in hash: 8 9 | num_items in hash: 9 10 | num_items in hash: 10 11 | deleted; num_items in hash: 9 12 | deleted; num_items in hash: 8 13 | deleted; num_items in hash: 7 14 | deleted; num_items in hash: 6 15 | deleted; num_items in hash: 5 16 | -------------------------------------------------------------------------------- /tests/test8.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct example_user_t { 6 | int id; 7 | int cookie; 8 | UT_hash_handle hh; 9 | } example_user_t; 10 | 11 | int main() 12 | { 13 | int i; 14 | example_user_t *user, *tmp, *users=NULL; 15 | 16 | /* create elements */ 17 | for(i=0; i<10; i++) { 18 | user = (example_user_t*)malloc(sizeof(example_user_t)); 19 | if (user == NULL) { 20 | exit(-1); 21 | } 22 | user->id = i; 23 | user->cookie = i*i; 24 | HASH_ADD_INT(users,id,user); 25 | printf("num_items in hash: %u\n", user->hh.tbl->num_items); 26 | } 27 | 28 | /* delete each even ID */ 29 | for(i=0; i<10; i+=2) { 30 | HASH_FIND_INT(users,&i,tmp); 31 | if (tmp != NULL) { 32 | HASH_DEL(users,tmp); 33 | free(tmp); 34 | printf("deleted; num_items in hash: %u\n", user->hh.tbl->num_items); 35 | } else { 36 | printf("user id %d not found\n", i); 37 | } 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /tests/test80.ans: -------------------------------------------------------------------------------- 1 | 0 1 2 3 4 5 6 7 8 9 2 | len: 10 3 | 4 | 0 1 2 3 4 5 6 7 8 9 0 11 5 | len: 12 6 | 7 | -------------------------------------------------------------------------------- /tests/test80.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utarray.h" 3 | 4 | int main() 5 | { 6 | UT_array *a; 7 | int i, *p; 8 | utarray_new(a, &ut_int_icd); 9 | for(i=0; i<10; i++) { 10 | utarray_push_back(a,&i); 11 | } 12 | for(p=(int*)utarray_front(a); p!=NULL; p=(int*)utarray_next(a,p)) { 13 | printf("%d ",*p); 14 | } 15 | printf("\n"); 16 | printf("len: %u\n\n", utarray_len(a)); 17 | 18 | i=11; 19 | utarray_insert(a, &i, 11); 20 | while ( (p=(int*)utarray_next(a,p)) != NULL ) { 21 | printf("%d ", *p); 22 | } 23 | printf("\n"); 24 | printf("len: %u\n\n", utarray_len(a)); 25 | 26 | utarray_free(a); 27 | return 0; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /tests/test81.ans: -------------------------------------------------------------------------------- 1 | 0 1 2 3 4 5 6 7 8 9 2 | len: 10 3 | 4 | 0 1 2 3 4 5 6 7 8 9 10 5 | len: 11 6 | 7 | -------------------------------------------------------------------------------- /tests/test81.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utarray.h" 3 | 4 | int main() 5 | { 6 | UT_array *a; 7 | int i, *p; 8 | utarray_new(a, &ut_int_icd); 9 | for(i=0; i<10; i++) { 10 | utarray_push_back(a,&i); 11 | } 12 | for(p=(int*)utarray_front(a); p!=NULL; p=(int*)utarray_next(a,p)) { 13 | printf("%d ",*p); 14 | } 15 | printf("\n"); 16 | printf("len: %u\n\n", utarray_len(a)); 17 | 18 | i=10; 19 | utarray_insert(a, &i, 10); 20 | while ( (p=(int*)utarray_next(a,p)) != NULL ) { 21 | printf("%d ", *p); 22 | } 23 | printf("\n"); 24 | printf("len: %u\n\n", utarray_len(a)); 25 | 26 | utarray_free(a); 27 | return 0; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /tests/test82.ans: -------------------------------------------------------------------------------- 1 | 0 1 2 3 4 5 6 7 8 9 2 | len: 10 3 | 4 | 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 len: 20 5 | 6 | 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 7 | 8 | 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 9 | 10 | -------------------------------------------------------------------------------- /tests/test82.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utarray.h" 3 | 4 | int main() 5 | { 6 | UT_array *a,*b; 7 | int i, *p; 8 | utarray_new(a, &ut_int_icd); 9 | utarray_new(b, &ut_int_icd); 10 | 11 | for(i=0; i<10; i++) { 12 | utarray_push_back(a,&i); 13 | } 14 | for(p=(int*)utarray_front(a); p!=NULL; p=(int*)utarray_next(a,p)) { 15 | printf("%d ",*p); 16 | } 17 | printf("\n"); 18 | printf("len: %u\n\n", utarray_len(a)); 19 | 20 | utarray_inserta(b,a,10); 21 | for(p=(int*)utarray_front(b); p!=NULL; p=(int*)utarray_next(b,p)) { 22 | printf("%d ",*p); 23 | } 24 | printf("len: %u\n\n", utarray_len(b)); 25 | 26 | utarray_inserta(b,a,0); 27 | for(p=(int*)utarray_front(b); p!=NULL; p=(int*)utarray_next(b,p)) { 28 | printf("%d ",*p); 29 | } 30 | printf("len: %u\n\n", utarray_len(b)); 31 | 32 | utarray_inserta(b,a,25); 33 | for(p=(int*)utarray_front(b); p!=NULL; p=(int*)utarray_next(b,p)) { 34 | printf("%d ",*p); 35 | } 36 | printf("len: %u\n\n", utarray_len(b)); 37 | 38 | utarray_free(a); 39 | utarray_free(b); 40 | return 0; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /tests/test83.ans: -------------------------------------------------------------------------------- 1 | added bob (id 0) 2 | added jack (id 1) 3 | added gary (id 2) 4 | added ty (id 3) 5 | added bo (id 4) 6 | added phil (id 5) 7 | added art (id 6) 8 | added gil (id 7) 9 | added buck (id 8) 10 | added ted (id 9) 11 | found bob (id 0) 12 | replaced (y) with bob (id 0) 13 | found jack (id 1) 14 | replaced (y) with jack (id 10) 15 | found gary (id 2) 16 | replaced (y) with gary (id 20) 17 | found ty (id 3) 18 | replaced (y) with ty (id 30) 19 | found bo (id 4) 20 | replaced (y) with bo (id 40) 21 | found phil (id 5) 22 | replaced (y) with phil (id 50) 23 | found art (id 6) 24 | replaced (y) with art (id 60) 25 | found gil (id 7) 26 | replaced (y) with gil (id 70) 27 | found buck (id 8) 28 | replaced (y) with buck (id 80) 29 | found ted (id 9) 30 | replaced (y) with ted (id 90) 31 | traversing... 32 | bob (id 0) 33 | jack (id 10) 34 | gary (id 20) 35 | ty (id 30) 36 | bo (id 40) 37 | phil (id 50) 38 | art (id 60) 39 | gil (id 70) 40 | buck (id 80) 41 | ted (id 90) 42 | -------------------------------------------------------------------------------- /tests/test83.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include 3 | #include /* malloc */ 4 | 5 | typedef struct person_t { 6 | char first_name[10]; 7 | int id; 8 | UT_hash_handle hh; 9 | } person_t; 10 | 11 | int main() 12 | { 13 | person_t *people=NULL, *person, *new_person, *tmp; 14 | const char **name; 15 | const char * names[] = { "bob", "jack", "gary", "ty", "bo", "phil", "art", 16 | "gil", "buck", "ted", NULL 17 | }; 18 | int id=0; 19 | 20 | for(name=names; *name!=NULL; name++) { 21 | person = (person_t*)malloc(sizeof(person_t)); 22 | if (person == NULL) { 23 | exit(-1); 24 | } 25 | strcpy(person->first_name, *name); 26 | person->id = id++; 27 | HASH_ADD_STR(people,first_name,person); 28 | printf("added %s (id %d)\n", person->first_name, person->id); 29 | } 30 | 31 | person=NULL; 32 | person_t **p=&person; 33 | 34 | for(name=names; *name!=NULL; name++) { 35 | HASH_FIND_STR(people,*name,*p); 36 | if (person != NULL) { 37 | printf("found %s (id %d)\n", person->first_name, person->id); 38 | new_person = (person_t *)malloc(sizeof(person_t)); 39 | if (new_person == NULL) { 40 | exit(-1); 41 | } 42 | memcpy(new_person, person, sizeof(person_t)); 43 | new_person->id = person->id*10; 44 | HASH_REPLACE_STR(people,first_name,new_person,tmp); 45 | printf("replaced (%c) with %s (id %d)\n", (tmp!=NULL)?'y':'n', new_person->first_name, new_person->id); 46 | if (tmp != NULL) { 47 | free(tmp); 48 | } 49 | } else { 50 | printf("failed to find %s\n", *name); 51 | } 52 | } 53 | 54 | printf("traversing... \n"); 55 | HASH_ITER(hh, people, person, tmp) { 56 | printf("%s (id %d)\n", person->first_name, person->id); 57 | HASH_DEL(people,person); 58 | free(person); 59 | } 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /tests/test84.ans: -------------------------------------------------------------------------------- 1 | added bob (id 0) 2 | added jack (id 1) 3 | added gary (id 2) 4 | added ty (id 3) 5 | added bo (id 4) 6 | added phil (id 5) 7 | added art (id 6) 8 | added gil (id 7) 9 | added buck (id 8) 10 | added ted (id 9) 11 | found bob (id 0) 12 | replaced (y) with bob (id 0) 13 | found jack (id 1) 14 | replaced (y) with jack (id 10) 15 | found gary (id 2) 16 | replaced (y) with gary (id 20) 17 | found ty (id 3) 18 | replaced (y) with ty (id 30) 19 | found bo (id 4) 20 | replaced (y) with bo (id 40) 21 | found phil (id 5) 22 | replaced (y) with phil (id 50) 23 | found art (id 6) 24 | replaced (y) with art (id 60) 25 | found gil (id 7) 26 | replaced (y) with gil (id 70) 27 | found buck (id 8) 28 | replaced (y) with buck (id 80) 29 | found ted (id 9) 30 | replaced (y) with ted (id 90) 31 | traversing... 32 | bob (id 0) 33 | jack (id 10) 34 | gary (id 20) 35 | ty (id 30) 36 | bo (id 40) 37 | phil (id 50) 38 | art (id 60) 39 | gil (id 70) 40 | buck (id 80) 41 | ted (id 90) 42 | -------------------------------------------------------------------------------- /tests/test84.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include 3 | #include /* malloc */ 4 | 5 | typedef struct person_t { 6 | char *first_name; 7 | int id; 8 | UT_hash_handle hh; 9 | } person_t; 10 | 11 | int main() 12 | { 13 | person_t *people=NULL, *person, *new_person, *tmp; 14 | const char **name; 15 | const char * names[] = { "bob", "jack", "gary", "ty", "bo", "phil", "art", 16 | "gil", "buck", "ted", NULL 17 | }; 18 | int id=0; 19 | 20 | for(name=names; *name!=NULL; name++) { 21 | person = (person_t*)malloc(sizeof(person_t)); 22 | if (person == NULL) { 23 | exit(-1); 24 | } 25 | person->first_name = (char*)malloc(10UL); 26 | if (person->first_name == NULL) { 27 | exit(-1); 28 | } 29 | strcpy(person->first_name, *name); 30 | person->id = id++; 31 | HASH_ADD_STR(people,first_name,person); 32 | printf("added %s (id %d)\n", person->first_name, person->id); 33 | } 34 | 35 | person=NULL; 36 | person_t **p=&person; 37 | 38 | for(name=names; *name!=NULL; name++) { 39 | HASH_FIND_STR(people,*name,*p); 40 | if (person != NULL) { 41 | printf("found %s (id %d)\n", person->first_name, person->id); 42 | new_person = (person_t*)malloc(sizeof(person_t)); 43 | if (new_person == NULL) { 44 | exit(-1); 45 | } 46 | new_person->first_name = (char*)malloc(10UL); 47 | if (new_person->first_name == NULL) { 48 | exit(-1); 49 | } 50 | strcpy(new_person->first_name, person->first_name); 51 | new_person->id = person->id*10; 52 | HASH_REPLACE_STR(people,first_name,new_person,tmp); 53 | printf("replaced (%c) with %s (id %d)\n", (tmp!=NULL)?'y':'n', new_person->first_name, new_person->id); 54 | if (tmp != NULL) { 55 | free(tmp->first_name); 56 | free(tmp); 57 | } 58 | } else { 59 | printf("failed to find %s\n", *name); 60 | } 61 | } 62 | 63 | printf("traversing... \n"); 64 | HASH_ITER(hh, people, person, tmp) { 65 | printf("%s (id %d)\n", person->first_name, person->id); 66 | HASH_DEL(people,person); 67 | free(person->first_name); 68 | free(person); 69 | } 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /tests/test85.ans: -------------------------------------------------------------------------------- 1 | overhead non-zero 2 | overhead zero 3 | -------------------------------------------------------------------------------- /tests/test85.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct example_user_t { 6 | int id; 7 | int cookie; 8 | UT_hash_handle hh; 9 | } example_user_t; 10 | 11 | int main() 12 | { 13 | int i; 14 | example_user_t *user, *users=NULL; 15 | 16 | /* create elements */ 17 | for(i=0; i<10; i++) { 18 | user = (example_user_t*)malloc(sizeof(example_user_t)); 19 | if (user == NULL) { 20 | exit(-1); 21 | } 22 | user->id = i; 23 | user->cookie = i*i; 24 | HASH_ADD_INT(users,id,user); 25 | } 26 | 27 | size_t s = HASH_OVERHEAD(hh,users); 28 | printf("overhead %s\n", (s==0U)?"zero":"non-zero"); 29 | HASH_CLEAR(hh,users); 30 | // should free those elements 31 | // but this test is not concerned with that 32 | s = HASH_OVERHEAD(hh,users); 33 | printf("overhead %s\n", (s==0U)?"zero":"non-zero"); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /tests/test86.ans: -------------------------------------------------------------------------------- 1 | CDL appends 2 | a b c 3 | count = 3 4 | Test CDL_PREPEND_ELEM d with elt NULL 5 | a b c d 6 | Test CDL_PREPEND_ELEM e before item b 7 | a e b c d 8 | Test CDL_APPEND_ELEM f with elt NULL 9 | f a e b c d 10 | Test CDL_APPEND_ELEM g after item b 11 | f a e b g c d 12 | count = 7 13 | advancing head pointer 14 | a e b g c d f 15 | a e b g c d f a e b g c d f a e b g c d 16 | a f d c g b e a f d 17 | deleting (b) 18 | a e g c d f 19 | deleting (a) 20 | e g c d f 21 | deleting (c) 22 | e g d f 23 | deleting (g) 24 | e d f 25 | deleting (e) 26 | d f 27 | deleting (d) 28 | f deleting (f) 29 | 30 | DL appends 31 | a b c 32 | count = 3 33 | Test DL_PREPEND_ELEM d with elt NULL 34 | a b c d 35 | Test DL_PREPEND_ELEM e before item b 36 | a e b c d 37 | Test DL_APPEND_ELEM f with elt NULL 38 | f a e b c d 39 | Test DL_APPEND_ELEM g after item b 40 | f a e b g c d 41 | count = 7 42 | deleting (b) 43 | f a e g c d 44 | deleting (a) 45 | f e g c d 46 | deleting (c) 47 | f e g d 48 | deleting (g) 49 | f e d 50 | deleting (e) 51 | f d 52 | deleting (d) 53 | f deleting (f) 54 | 55 | LL appends 56 | a b c 57 | count = 3 58 | Test LL_PREPEND_ELEM d with elt NULL 59 | a b c d 60 | Test LL_PREPEND_ELEM e before item b 61 | a e b c d 62 | Test LL_APPEND_ELEM f with elt NULL 63 | f a e b c d 64 | Test LL_APPEND_ELEM g after item b 65 | f a e b g c d 66 | count = 7 67 | deleting (b) 68 | f a e g c d 69 | deleting (a) 70 | f e g c d 71 | deleting (c) 72 | f e g d 73 | deleting (g) 74 | f e d 75 | deleting (e) 76 | f d 77 | deleting (d) 78 | f deleting (f) 79 | 80 | -------------------------------------------------------------------------------- /tests/test87.ans: -------------------------------------------------------------------------------- 1 | 1: muh3 2 | 2: muh1 3 | 3: muh5 4 | 5: muh6 5 | 6: muh7 6 | 6: muh9 7 | 8: muh2 8 | 8: muh4 9 | 9: muh10 10 | 10: muh11 11 | 15: muh8 12 | 43: muh12 13 | ### 14 | 1: muh3 15 | 2: muh1 16 | 3: muh5 17 | 5: muh6 18 | 6: muh7 19 | 6: muh9 20 | 7: muh12 21 | 8: muh2 22 | 8: muh4 23 | 9: muh10 24 | 10: muh11 25 | 15: muh8 26 | ### 27 | 2: muh1 28 | 3: muh5 29 | 5: muh6 30 | 6: muh7 31 | 6: muh9 32 | 7: muh12 33 | 8: muh2 34 | 8: muh4 35 | 9: muh10 36 | 9: muh3 37 | 10: muh11 38 | 15: muh8 39 | ### 40 | 2: muh1 41 | 3: muh5 42 | 5: muh6 43 | 6: muh9 44 | 7: muh12 45 | 8: muh2 46 | 8: muh4 47 | 9: muh10 48 | 9: muh3 49 | 10: muh11 50 | 15: muh8 51 | 16: muh7 52 | ### 53 | 2: muh1 54 | 3: muh5 55 | 5: muh6 56 | 6: muh9 57 | 7: muh12 58 | 8: muh4 59 | 9: muh10 60 | 9: muh3 61 | 10: muh11 62 | 15: muh8 63 | 16: muh7 64 | ### 65 | 2: muh1 66 | 3: muh5 67 | 5: muh6 68 | 6: muh9 69 | 7: muh12 70 | 8: muh4 71 | 8: muh2 72 | 9: muh10 73 | 9: muh3 74 | 10: muh11 75 | 15: muh8 76 | 16: muh7 77 | ### 78 | ### 79 | -------------------------------------------------------------------------------- /tests/test88.ans: -------------------------------------------------------------------------------- 1 | alt_strlen 2 | alt_strlen 3 | alt_strlen 4 | alt_strlen 5 | alt_strlen 6 | alt_strlen 7 | alt_strlen 8 | alt_strlen 9 | alt_strlen 10 | alt_strlen 11 | alt_strlen 12 | alt_keycmp 13 | alt_strlen 14 | alt_keycmp 15 | alt_strlen 16 | alt_keycmp 17 | alt_strlen 18 | alt_keycmp 19 | alt_strlen 20 | alt_keycmp 21 | alt_strlen 22 | alt_keycmp 23 | alt_strlen 24 | alt_keycmp 25 | alt_strlen 26 | alt_keycmp 27 | alt_strlen 28 | alt_keycmp 29 | alt_strlen 30 | alt_keycmp 31 | -------------------------------------------------------------------------------- /tests/test88.c: -------------------------------------------------------------------------------- 1 | #ifdef HASH_FUNCTION 2 | #undef HASH_FUNCTION /* this test's output depends on the pattern of hash collisions */ 3 | #endif 4 | 5 | #include "uthash.h" 6 | #include /* malloc */ 7 | #include /* printf */ 8 | 9 | /* This is mostly a copy of test6.c. */ 10 | 11 | #undef HASH_KEYCMP 12 | #undef uthash_strlen 13 | #define HASH_KEYCMP(a,b,n) alt_keycmp(a,b,n) 14 | #define uthash_strlen(s) alt_strlen(s) 15 | 16 | typedef struct example_user_t { 17 | char id[3]; 18 | int cookie; 19 | UT_hash_handle hh; 20 | } example_user_t; 21 | 22 | static int alt_keycmp(const void *a, const void *b, size_t n) 23 | { 24 | puts("alt_keycmp"); 25 | return memcmp(a,b,n); 26 | } 27 | 28 | static size_t alt_strlen(const char *s) 29 | { 30 | puts("alt_strlen"); 31 | return strlen(s); 32 | } 33 | 34 | int main() 35 | { 36 | int i; 37 | example_user_t *user, *tmp, *users=NULL; 38 | 39 | /* create elements */ 40 | for (i=0; i<10; i++) { 41 | user = (example_user_t*)malloc(sizeof(example_user_t)); 42 | if (user == NULL) { 43 | exit(-1); 44 | } 45 | sprintf(user->id, "%d", i); 46 | user->cookie = i*i; 47 | HASH_ADD_STR(users,id,user); 48 | } 49 | 50 | /* delete each ID */ 51 | for (i=0; i<10; i++) { 52 | char buffer[3]; 53 | sprintf(buffer, "%d", i); 54 | HASH_FIND_STR(users,buffer,tmp); 55 | if (tmp != NULL) { 56 | HASH_DEL(users,tmp); 57 | free(tmp); 58 | } else { 59 | printf("user id %d not found\n", i); 60 | } 61 | } 62 | 63 | /* show the hash */ 64 | for (user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { 65 | printf("user %s, cookie %d\n", user->id, user->cookie); 66 | } 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /tests/test89.ans: -------------------------------------------------------------------------------- 1 | node #0, timeout: 100 2 | node #1, timeout: 200 3 | node #2, timeout: 300 4 | node #3, timeout: 400 5 | node #4, timeout: 500 6 | -------------------------------------------------------------------------------- /tests/test89.c: -------------------------------------------------------------------------------- 1 | /* Minified version of code from tinydtls 0.9 */ 2 | /* See https://projects.eclipse.org/projects/iot.tinydtls */ 3 | 4 | #include "utlist.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | typedef int clock_time_t; 11 | 12 | typedef struct netq_t { 13 | struct netq_t *next; 14 | clock_time_t t; 15 | } netq_t; 16 | 17 | void dump_queue(struct netq_t *queue) 18 | { 19 | struct netq_t *p; 20 | int i = 0; 21 | 22 | if (!queue) { 23 | printf("(null)\n"); 24 | } else { 25 | LL_FOREACH(queue, p) { 26 | printf("node #%d, timeout: %d\n", i++, p->t); 27 | } 28 | } 29 | } 30 | 31 | int netq_insert_node(netq_t **queue, netq_t *node) 32 | { 33 | netq_t *p = *queue; 34 | while (p && p->t <= node->t) { 35 | p = p->next; 36 | } 37 | /* *INDENT-OFF* */ 38 | if (p) 39 | LL_PREPEND_ELEM(*queue, p, node); 40 | else 41 | LL_APPEND(*queue, node); 42 | /* *INDENT-ON* */ 43 | return 1; 44 | } 45 | 46 | int main() 47 | { 48 | struct netq_t *nq = NULL; 49 | size_t i; 50 | 51 | clock_time_t timestamps[] = { 300, 100, 200, 400, 500 }; 52 | 53 | for (i = 0; i < sizeof(timestamps)/sizeof(clock_time_t); i++) { 54 | struct netq_t *node = (struct netq_t *)malloc(sizeof *node); 55 | memset(node, '\0', sizeof *node); 56 | node->t = timestamps[i]; 57 | 58 | if (netq_insert_node(&nq, node) != 1) { 59 | puts("ERROR"); 60 | } 61 | } 62 | 63 | dump_queue(nq); 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /tests/test9.c: -------------------------------------------------------------------------------- 1 | #include "uthash.h" 2 | #include /* malloc */ 3 | #include /* printf */ 4 | 5 | typedef struct example_user_t { 6 | int id; 7 | int cookie; 8 | UT_hash_handle hh; 9 | } example_user_t; 10 | 11 | int main() 12 | { 13 | int i; 14 | example_user_t *user, *tmp, *users=NULL; 15 | 16 | /* create elements */ 17 | for(i=0; i<1000; i++) { 18 | user = (example_user_t*)malloc(sizeof(example_user_t)); 19 | if (user == NULL) { 20 | exit(-1); 21 | } 22 | user->id = i; 23 | user->cookie = i*i; 24 | HASH_ADD_INT(users,id,user); 25 | } 26 | 27 | /* delete each ID */ 28 | for(i=0; i<1000; i+=2) { 29 | HASH_FIND_INT(users,&i,tmp); 30 | if (tmp != NULL) { 31 | printf("user %d, cookie %d\n", tmp->id, tmp->cookie); 32 | } else { 33 | printf("user id %d not found\n", i); 34 | } 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /tests/test90.ans: -------------------------------------------------------------------------------- 1 | filling in is ok 2 | cleanup is ok 3 | -------------------------------------------------------------------------------- /tests/test90.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "uthash.h" 5 | 6 | struct item { 7 | unsigned char *sort_field; 8 | size_t sort_field_len; /** Sort field length, in bytes */ 9 | int some_user_data; 10 | UT_hash_handle hh; 11 | }; 12 | 13 | int sort_func(const struct item *a, const struct item *b) 14 | { 15 | int va = *(int*)(void*)a->sort_field; 16 | int vb = *(int*)(void*)b->sort_field; 17 | return (va < vb) ? -1 : (va > vb); 18 | } 19 | 20 | int main() 21 | { 22 | size_t i; 23 | struct item *p, *tmp; 24 | int total = 0; 25 | 26 | /** The sorted list */ 27 | struct item *list = NULL; 28 | int counter = 0; 29 | 30 | /* fill in the sorted list */ 31 | for(i=0; i<100; i++) { 32 | p = (struct item *)malloc(sizeof *p); 33 | 34 | p->sort_field_len = sizeof(int); 35 | p->sort_field = (unsigned char *)malloc(p->sort_field_len); 36 | *(int*)(void*)p->sort_field = counter++; 37 | 38 | HASH_ADD_KEYPTR_INORDER(hh, list, p->sort_field, p->sort_field_len, p, sort_func); 39 | } 40 | 41 | printf("filling in is ok\n"); 42 | 43 | HASH_ITER(hh, list, p, tmp) { 44 | total += *(int*)(void*)p->sort_field; 45 | HASH_DEL(list, p); 46 | free(p->sort_field); 47 | free(p); 48 | } 49 | assert(total == 4950); // sum of 0 through 99 50 | 51 | printf("cleanup is ok\n"); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /tests/test91.ans: -------------------------------------------------------------------------------- 1 | n g m f l e k d j c i b o h a 2 | DL_INSERT_INORDER 3 | n g m f l e k d j c i b o h a 4 | CDL_INSERT_INORDER 5 | n g m f l e k d j c i b o h a 6 | n a h o b i c j d k e l f m g 7 | -------------------------------------------------------------------------------- /tests/test91.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utlist.h" 3 | 4 | typedef struct el { 5 | int id, score; 6 | struct el *next, *prev; 7 | } el; 8 | 9 | static int order_desc(el *a, el *b) 10 | { 11 | return (a->score > b->score) ? -1 : (a->score < b->score); 12 | } 13 | 14 | int main() 15 | { 16 | int i; 17 | el *head = NULL; 18 | el els[15], *e; 19 | 20 | for (i=0; i<15; i++) { 21 | els[i].id = (int)'a'+i; 22 | els[i].score = i%7; 23 | LL_INSERT_INORDER(head, &els[i], order_desc); 24 | } 25 | LL_FOREACH(head, e) { 26 | printf("%c ", e->id); 27 | } 28 | printf("\n"); 29 | 30 | printf("DL_INSERT_INORDER\n"); 31 | head = NULL; 32 | for (i=0; i<15; i++) { 33 | DL_INSERT_INORDER(head, &els[i], order_desc); 34 | } 35 | DL_FOREACH(head, e) { 36 | printf("%c ", e->id); 37 | } 38 | printf("\n"); 39 | 40 | printf("CDL_INSERT_INORDER\n"); 41 | head = NULL; 42 | for (i=0; i<15; i++) { 43 | CDL_INSERT_INORDER(head, &els[i], order_desc); 44 | } 45 | CDL_FOREACH(head, e) { 46 | printf("%c ", e->id); 47 | } 48 | printf("\n"); 49 | CDL_FOREACH2(head, e, prev) { 50 | printf("%c ", e->id); 51 | } 52 | printf("\n"); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /tests/test92.ans: -------------------------------------------------------------------------------- 1 | End 2 | -------------------------------------------------------------------------------- /tests/test93.ans: -------------------------------------------------------------------------------- 1 | End 2 | -------------------------------------------------------------------------------- /tests/test93.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define HASH_BLOOM 16 5 | 6 | #include "uthash.h" 7 | 8 | #undef uthash_malloc 9 | #undef uthash_fatal 10 | #define uthash_malloc(sz) alt_malloc(sz) 11 | #define uthash_fatal(s) alt_fatal(s) 12 | 13 | typedef struct example_user_t { 14 | int id; 15 | int cookie; 16 | UT_hash_handle hh; 17 | } example_user_t; 18 | 19 | static int malloc_cnt = 0; 20 | static int malloc_failed; 21 | static int is_fatal; 22 | static jmp_buf j_buf; 23 | static example_user_t * users; 24 | static int user_id = 0; 25 | 26 | static void *alt_malloc(size_t sz) 27 | { 28 | if (--malloc_cnt <= 0) { 29 | malloc_failed = 1; 30 | return 0; 31 | } 32 | malloc_failed = 0; 33 | return malloc(sz); 34 | } 35 | 36 | static void alt_fatal(char const * s) { 37 | (void)s; 38 | is_fatal = 1; 39 | longjmp(j_buf, 1); 40 | } 41 | 42 | static void init_users(int need_malloc_cnt) { 43 | users = NULL; 44 | example_user_t * user = (example_user_t*)malloc(sizeof(example_user_t)); 45 | user->id = user_id; 46 | is_fatal = 0; 47 | malloc_cnt = need_malloc_cnt; 48 | if (!setjmp(j_buf)) { 49 | HASH_ADD_INT(users, id, user); 50 | } else { 51 | free(user); 52 | } 53 | } 54 | 55 | int main() 56 | { 57 | example_user_t *user; 58 | 59 | init_users(3); /* bloom filter must fail */ 60 | if (!is_fatal) { 61 | printf("fatal not called after bloom failure\n"); 62 | } 63 | 64 | init_users(2); /* bucket creation must fail */ 65 | if (!is_fatal) { 66 | printf("fatal not called after bucket creation failure\n"); 67 | } 68 | 69 | init_users(1); /* table creation must fail */ 70 | if (!is_fatal) { 71 | printf("fatal not called after table creation failure\n"); 72 | } 73 | 74 | init_users(4); /* hash must create OK */ 75 | if (is_fatal) { 76 | printf("fatal error when creating hash normally\n"); 77 | /* bad idea to continue running */ 78 | return 1; 79 | } 80 | 81 | /* let's add users until expansion fails */ 82 | users = NULL; 83 | malloc_cnt = 4; 84 | while (1) { 85 | if (user_id++ == 1000) { 86 | printf("there is no way 1000 iterations didn't require realloc\n"); 87 | break; 88 | } 89 | user = (example_user_t*)malloc(sizeof(example_user_t)); 90 | user->id = user_id; 91 | if (!setjmp(j_buf)) { 92 | HASH_ADD_INT(users, id, user); 93 | } else { 94 | free(user); 95 | } 96 | if (malloc_failed) { 97 | 98 | if (!is_fatal) { 99 | printf("fatal not called after bucket not extended\n"); 100 | } 101 | if (user_id < 10) { 102 | printf("there is no way your bucket size is 10\n"); 103 | } 104 | 105 | /* we can't really do anything, the hash is not in consistent 106 | * state, so assume this is a success. */ 107 | break; 108 | } 109 | malloc_cnt = 0; 110 | } 111 | 112 | HASH_CLEAR(hh, users); 113 | 114 | printf("End\n"); 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /tests/test94.ans: -------------------------------------------------------------------------------- 1 | LL_INSERT_INORDER 2 | list1: n g m f l e k d j c i b o h a 3 | list2: o h a i b j c k d l e m f n g 4 | DL_INSERT_INORDER 5 | list1: n g m f l e k d j c i b o h a 6 | list2: o h a i b j c k d l e m f n g 7 | CDL_INSERT_INORDER 8 | list1: 9 | n g m f l e k d j c i b o h a 10 | n a h o b i c j d k e l f m g 11 | list2: 12 | o h a i b j c k d l e m f n g 13 | o g n f m e l d k c j b i a h 14 | -------------------------------------------------------------------------------- /tests/test94.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utlist.h" 3 | 4 | typedef struct el { 5 | int id, score; 6 | struct el *next, *prev; 7 | struct el *next_list2, *prev_list2; 8 | } el; 9 | 10 | static int order_desc(el *a, el *b) 11 | { 12 | return (a->score > b->score) ? -1 : (a->score < b->score); 13 | } 14 | 15 | static int order_asc(el *a, el *b) 16 | { 17 | return -order_desc(a, b); 18 | } 19 | 20 | int main() 21 | { 22 | int i; 23 | el *head = NULL; 24 | el *head2 = NULL; 25 | el els[15], *e; 26 | 27 | for (i=0; i<15; i++) { 28 | els[i].id = (int)'a'+i; 29 | els[i].score = i%7; 30 | LL_INSERT_INORDER(head, &els[i], order_desc); 31 | LL_INSERT_INORDER2(head2, &els[i], order_asc, next_list2); 32 | } 33 | 34 | printf("LL_INSERT_INORDER\n"); 35 | printf("list1: "); 36 | LL_FOREACH(head, e) { 37 | printf("%c ", e->id); 38 | } 39 | printf("\n"); 40 | printf("list2: "); 41 | LL_FOREACH2(head2, e, next_list2) { 42 | printf("%c ", e->id); 43 | } 44 | printf("\n"); 45 | 46 | printf("DL_INSERT_INORDER\n"); 47 | head = NULL; 48 | head2 = NULL; 49 | for (i=0; i<15; i++) { 50 | DL_INSERT_INORDER(head, &els[i], order_desc); 51 | DL_INSERT_INORDER2(head2, &els[i], order_asc, prev_list2, next_list2); 52 | } 53 | 54 | printf("list1: "); 55 | DL_FOREACH(head, e) { 56 | printf("%c ", e->id); 57 | } 58 | printf("\n"); 59 | printf("list2: "); 60 | DL_FOREACH2(head2, e, next_list2) { 61 | printf("%c ", e->id); 62 | } 63 | printf("\n"); 64 | 65 | printf("CDL_INSERT_INORDER\n"); 66 | head = NULL; 67 | head2 = NULL; 68 | for (i=0; i<15; i++) { 69 | CDL_INSERT_INORDER(head, &els[i], order_desc); 70 | CDL_INSERT_INORDER2(head2, &els[i], order_asc, prev_list2, next_list2); 71 | } 72 | printf("list1:\n"); 73 | CDL_FOREACH(head, e) { 74 | printf("%c ", e->id); 75 | } 76 | printf("\n"); 77 | CDL_FOREACH2(head, e, prev) { 78 | printf("%c ", e->id); 79 | } 80 | printf("\n"); 81 | 82 | printf("list2:\n"); 83 | CDL_FOREACH2(head2, e, next_list2) { 84 | printf("%c ", e->id); 85 | } 86 | printf("\n"); 87 | CDL_FOREACH2(head2, e, prev_list2) { 88 | printf("%c ", e->id); 89 | } 90 | printf("\n"); 91 | 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /tests/test95.ans: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/troydhanson/uthash/af6e637f19c102167fb914b9ebcc171389270b48/tests/test95.ans -------------------------------------------------------------------------------- /tests/test95.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include /* size_t, NULL */ 3 | #include "utstack.h" 4 | 5 | typedef struct el { 6 | int id, score; 7 | struct el *next; 8 | struct el *next2; 9 | } el; 10 | 11 | int main() 12 | { 13 | el alpha = {1, 100, NULL, NULL}; 14 | el beta = {2, 100, NULL, NULL}; 15 | el gamma = {3, 100, NULL, NULL}; 16 | el delta = {4, 100, NULL, NULL}; 17 | 18 | el *stack1 = NULL; 19 | el *stack2 = NULL; 20 | el *dummy; 21 | int size1; 22 | size_t size2; 23 | 24 | STACK_COUNT(stack1, dummy, size1); assert(size1 == 0); 25 | STACK_COUNT(stack2, dummy, size2); assert(size2 == 0); 26 | assert(STACK_EMPTY(stack1)); 27 | assert(STACK_EMPTY(stack2)); 28 | 29 | STACK_PUSH(stack1, &alpha); 30 | STACK_COUNT(stack1, dummy, size1); assert(size1 == 1); 31 | STACK_PUSH(stack1, &beta); 32 | STACK_COUNT(stack1, dummy, size1); assert(size1 == 2); 33 | STACK_PUSH(stack1, &gamma); 34 | STACK_PUSH2(stack1, &delta, next); 35 | STACK_COUNT(stack1, dummy, size1); assert(size1 == 4); 36 | assert(stack1 == &delta); 37 | 38 | STACK_PUSH2(stack2, &alpha, next2); 39 | assert(stack2 == &alpha); 40 | assert(alpha.next2 == NULL); 41 | STACK_PUSH2(stack2, &delta, next2); 42 | assert(stack2 == &delta); 43 | assert(delta.next2 == &alpha); 44 | STACK_COUNT2(stack2, dummy, size2, next2); assert(size2 == 2); 45 | assert(!STACK_EMPTY(stack2)); 46 | assert(stack2 == &delta); 47 | 48 | assert(!STACK_EMPTY(stack1)); 49 | assert(!STACK_EMPTY(stack2)); 50 | 51 | STACK_POP(stack1, dummy); assert(stack1 == &gamma); assert(dummy == &delta); 52 | STACK_POP(stack1, dummy); assert(stack1 == &beta); assert(dummy == &gamma); 53 | STACK_POP(stack1, dummy); assert(stack1 == &alpha); assert(dummy == &beta); 54 | STACK_COUNT(stack1, dummy, size1); assert(size1 == 1); 55 | STACK_POP(stack1, dummy); assert(stack1 == NULL); assert(dummy == &alpha); 56 | 57 | assert(STACK_TOP(stack2) == &delta); 58 | while (!STACK_EMPTY(stack2)) { 59 | STACK_POP2(stack2, dummy, next2); 60 | } 61 | 62 | assert(STACK_EMPTY(stack1)); 63 | assert(STACK_EMPTY(stack2)); 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /tests/test96.ans: -------------------------------------------------------------------------------- 1 | time 56 not found, inserting it 2 | time 7 not found, inserting it 3 | time 10 not found, inserting it 4 | time 39 not found, inserting it 5 | time 82 found with value 10 6 | time 15 found with value 39 7 | time 31 found with value 7 8 | time 26 not found, inserting it 9 | time 51 found with value 39 10 | time 83 not found, inserting it 11 | time 46 found with value 10 12 | time 92 found with value 56 13 | time 49 not found, inserting it 14 | time 25 found with value 49 15 | time 80 found with value 56 16 | time 54 not found, inserting it 17 | time 97 found with value 49 18 | time 9 not found, inserting it 19 | time 34 found with value 10 20 | time 86 found with value 26 21 | time 87 found with value 39 22 | time 28 not found, inserting it 23 | time 13 found with value 49 24 | time 91 found with value 7 25 | time 95 found with value 83 26 | time 63 found with value 39 27 | time 71 found with value 83 28 | time 100 found with value 28 29 | time 44 found with value 56 30 | time 42 found with value 54 31 | time 16 found with value 28 32 | time 32 found with value 56 33 | time 6 found with value 54 34 | time 85 found with value 49 35 | time 40 found with value 28 36 | time 20 found with value 56 37 | time 18 found with value 54 38 | time 99 found with value 39 39 | time 22 found with value 10 40 | time 1 found with value 49 41 | -------------------------------------------------------------------------------- /tests/test96.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define HASH_FUNCTION(a,n,hv) (hv = clockface_hash(*(const int*)(a))) 5 | #define HASH_KEYCMP(a,b,n) clockface_neq(*(const int*)(a), *(const int*)(b)) 6 | 7 | #include "uthash.h" 8 | 9 | struct clockface { 10 | int time; 11 | UT_hash_handle hh; 12 | }; 13 | 14 | int clockface_hash(int time) 15 | { 16 | return (time % 4); 17 | } 18 | 19 | int clockface_neq(int t1, int t2) 20 | { 21 | return ((t1 % 12) != (t2 % 12)); 22 | } 23 | 24 | int main() 25 | { 26 | int random_data[] = { 27 | 56, 7, 10, 39, 82, 15, 31, 26, 51, 83, 28 | 46, 92, 49, 25, 80, 54, 97, 9, 34, 86, 29 | 87, 28, 13, 91, 95, 63, 71, 100, 44, 42, 30 | 16, 32, 6, 85, 40, 20, 18, 99, 22, 1 31 | }; 32 | 33 | struct clockface *times = NULL; 34 | for (int i=0; i < 40; ++i) { 35 | struct clockface *elt = (struct clockface *)malloc(sizeof(*elt)); 36 | struct clockface *found = NULL; 37 | elt->time = random_data[i]; 38 | HASH_FIND_INT(times, &elt->time, found); 39 | if (found) { 40 | printf("time %d found with value %d\n", elt->time, found->time); 41 | } else { 42 | printf("time %d not found, inserting it\n", elt->time); 43 | HASH_ADD_INT(times, time, elt); 44 | } 45 | } 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /tests/test97.ans: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/troydhanson/uthash/af6e637f19c102167fb914b9ebcc171389270b48/tests/test97.ans -------------------------------------------------------------------------------- /tests/test97.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "uthash.h" 5 | 6 | struct item { 7 | int payload; 8 | UT_hash_handle hh; 9 | }; 10 | 11 | void delete_without_modifying(struct item *head, const struct item *p) 12 | { 13 | struct item old; 14 | memcpy(&old, p, sizeof(struct item)); // also copy the padding bits 15 | assert(memcmp(&old, p, sizeof(struct item)) == 0); 16 | assert(p->hh.tbl == head->hh.tbl); // class invariant 17 | HASH_DEL(head, p); 18 | assert(memcmp(&old, p, sizeof(struct item)) == 0); // unmodified by HASH_DEL 19 | } 20 | 21 | int main() 22 | { 23 | struct item *items = NULL; 24 | struct item *found = NULL; 25 | int fortytwo = 42; 26 | int i; 27 | 28 | for (i=0; i < 100; i++) { 29 | struct item *p = (struct item *)malloc(sizeof *p); 30 | p->payload = i; 31 | HASH_ADD_INT(items, payload, p); 32 | } 33 | assert(HASH_COUNT(items) == 100); 34 | 35 | // Delete item "42" from the hash, wherever it is. 36 | HASH_FIND_INT(items, &fortytwo, found); 37 | assert(found != NULL); 38 | assert(found->payload == 42); 39 | delete_without_modifying(items, found); 40 | 41 | assert(HASH_COUNT(items) == 99); 42 | HASH_FIND_INT(items, &fortytwo, found); 43 | assert(found == NULL); 44 | 45 | // Delete the very first item in the hash. 46 | assert(items != NULL); 47 | i = items->payload; 48 | delete_without_modifying(items, items); 49 | 50 | assert(HASH_COUNT(items) == 98); 51 | HASH_FIND_INT(items, &i, found); 52 | assert(found == NULL); 53 | 54 | // leak the items, we don't care 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /tests/test98.ans: -------------------------------------------------------------------------------- 1 | F: 2 2 2 3 9 9 9 9 9 9 -1 -1 2 2 2 3 9 9 9 9 9 9 -1 -1 -1 2 | R: -1 -1 2 3 3 3 3 3 3 9 9 9 -1 -1 2 3 3 3 3 3 3 9 9 9 9 3 | -------------------------------------------------------------------------------- /tests/test98.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "utstring.h" 4 | 5 | int findl(const UT_string *haystack, int pos, char needle) { 6 | return utstring_find(haystack, pos, &needle, 1); 7 | } 8 | int findr(const UT_string *haystack, int pos, char needle) { 9 | return utstring_findR(haystack, pos, &needle, 1); 10 | } 11 | 12 | int main() 13 | { 14 | UT_string *s; 15 | 16 | utstring_new(s); 17 | utstring_printf(s, "%s %s!", "hello", "world"); 18 | assert(utstring_len(s) == 12); 19 | 20 | printf("F:"); 21 | for (int i = -12; i <= 12; ++i) { 22 | printf(" %d", findl(s, i, 'l')); 23 | } 24 | printf("\n"); 25 | 26 | printf("R:"); 27 | for (int i = -12; i <= 12; ++i) { 28 | printf(" %d", findr(s, i, 'l')); 29 | } 30 | printf("\n"); 31 | 32 | utstring_free(s); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /tests/test99.ans: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 4 4 | 8 5 | 16 6 | 110 7 | 64 8 | 128 9 | 256 10 | 512 11 | -------------------------------------------------------------------------------- /tests/test99.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utarray.h" 3 | 4 | int main(void) { 5 | UT_array *nums; 6 | int i, *p; 7 | 8 | utarray_new(nums, &ut_int_icd); 9 | 10 | for(i = 1; i < 1024; i <<= 1){ 11 | utarray_push_back(nums, &i); 12 | } 13 | 14 | i = 110; 15 | utarray_replace(nums, &i, 5); 16 | 17 | for(p = (int*)utarray_front(nums); 18 | p != NULL; 19 | p = (int*)utarray_next(nums, p)) { 20 | printf("%d\n",*p); 21 | } 22 | 23 | utarray_free(nums); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /tests/threads/Makefile: -------------------------------------------------------------------------------- 1 | HASHDIR = ../../src 2 | PROGS = test1 test2 3 | 4 | # Thread support requires compiler-specific options 5 | # ---------------------------------------------------------------------------- 6 | # GNU 7 | CFLAGS += -I$(HASHDIR) -g -pthread 8 | # Solaris (Studio 11) 9 | #CFLAGS = -I$(HASHDIR) -g -mt 10 | # ---------------------------------------------------------------------------- 11 | 12 | ifeq ($(HASH_DEBUG),1) 13 | CFLAGS += -DHASH_DEBUG=1 14 | endif 15 | 16 | all: $(PROGS) run_tests 17 | 18 | $(PROGS) : $(HASHDIR)/uthash.h 19 | $(CC) $(CPPLFAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(@).c 20 | 21 | debug: 22 | $(MAKE) all HASH_DEBUG=1 23 | 24 | run_tests: $(PROGS) 25 | perl ../do_tests 26 | 27 | .PHONY: clean 28 | 29 | clean: 30 | rm -f $(PROGS) test*.out 31 | rm -rf test*.dSYM 32 | -------------------------------------------------------------------------------- /tests/threads/README: -------------------------------------------------------------------------------- 1 | test1: exercise a two-reader, one-writer, rwlock-protected hash. 2 | test2: a template for a nthread, nloop kind of program 3 | -------------------------------------------------------------------------------- /tests/threads/do_tests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | my @tests; 7 | for (glob "test*[0-9]") { 8 | push @tests, $_ if -e "$_.ans"; 9 | } 10 | 11 | my $num_failed=0; 12 | 13 | for my $test (@tests) { 14 | `./$test > $test.out 2> $test.err`; 15 | `diff $test.out $test.ans`; 16 | print "$test failed\n" if $?; 17 | $num_failed++ if $?; 18 | unlink "$test.err" if -z "$test.err"; 19 | } 20 | 21 | print scalar @tests . " tests conducted, $num_failed failed.\n"; 22 | exit $num_failed; 23 | -------------------------------------------------------------------------------- /tests/threads/test2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "uthash.h" 12 | 13 | #undef uthash_noexpand_fyi 14 | #define uthash_noexpand_fyi(tbl) fprintf(stderr,"warning: bucket expansion inhibited\n"); 15 | 16 | #define LOOPS 100000 17 | #define NTHREADS 2 18 | 19 | typedef struct { 20 | int i; 21 | int v; 22 | UT_hash_handle hh; 23 | } elt; 24 | 25 | elt *elts=NULL; /* this is our hash table which two threads will use */ 26 | pthread_rwlock_t lock; 27 | 28 | void *thread_routine( void *arg ) { 29 | int keepgoing=0; 30 | /* TODO write me */ 31 | return NULL; 32 | } 33 | 34 | int main() { 35 | unsigned i; 36 | long num_added=0; 37 | int status; 38 | pthread_t thread[NTHREADS]; 39 | void *thread_result; 40 | elt tmp, *e; 41 | 42 | if (pthread_rwlock_init(&lock,NULL) != 0) { 43 | fprintf(stderr,"lock init failed\n"); 44 | exit(-1); 45 | } 46 | 47 | /* populate it to start */ 48 | for(i=0; ii = i; 52 | e->v = 0; 53 | HASH_ADD_INT(elts, i, e); 54 | } 55 | 56 | for(i=0; i