Navigation Menu

Skip to content

Commit

Permalink
[6model/c] add hashtable and a few tests (works only on Linux)
Browse files Browse the repository at this point in the history
  • Loading branch information
mberends committed Jul 30, 2011
1 parent 12a4dbf commit 74a549e
Show file tree
Hide file tree
Showing 9 changed files with 896 additions and 63 deletions.
5 changes: 3 additions & 2 deletions c/Configure.bat
@@ -1,6 +1,7 @@
:: Configure.bat

:: This script is written for Microsoft Visual C++ Express 2010 or GCC.
:: This script should work on a Microsoft Windows operating system with
:: either Microsoft Visual C++ or GNU Compiler Collection gcc.

:: TODO
:: - Add a --help option and provide for more options in general
Expand Down Expand Up @@ -65,4 +66,4 @@ tools\build\Configure.exe tools\build\Makefile.in Makefile
:: friendliness grounds, .bat reassures the reader that the script will do
:: only "simple" things.
:: You could argue it the other way - we use cmd.exe, not command.com, so we
:: should use the extension that command.com cannot handle. Dunno...
:: should use the extension that command.com cannot handle. Dunno...
6 changes: 4 additions & 2 deletions c/Configure.sh
@@ -1,5 +1,7 @@
#!/bin/sh
# TODO
# - Add a --help option and provide for more options in general
cc -Wall -o tools/build/Configure tools/build/Configure.c
tools/build/Configure tools/build/Makefile.in Makefile
export COMPILER=GCC
set opts_gcc=-Wall -DCC=$COMPILER
cc $opts_gcc -o tools/build/Configure tools/build/Configure.c
tools/build/Configure tools/build/Makefile.in Makefile
511 changes: 511 additions & 0 deletions c/src/hashtable.c

Large diffs are not rendered by default.

74 changes: 74 additions & 0 deletions c/src/hashtable.h
@@ -0,0 +1,74 @@
/* hashtable.h */

/* Structures */

/* hashtable_entry */
struct hashtable_entry {
/* A hash entry is a key-value pair. The key and the value can */
/* each be an arbitrary array of bytes. */
/* This is a frequently accessed data structure. For address */
/* alignment and efficient memory access all the pointers are */
/* defined at the beginning and the other members ordered by */
/* decreasing size and frquency of use after that. Some C */
/* compilers may do that anyway, but maintaining the order in the */
/* source code is only a small effort. */
void * keypointer;
void * valuepointer;
int keyint;
int valueint;
/* A hash entry can also be empty, for example after a delete. */
/* The empty entries are arranged in a linked list ordered by */
/* position in the hash entry table, so that subsequent re-use */
/* occurs in the entry nearest the start of the table. The empty */
/* entry list is doubly linked so that the average addition needs */
/* to walk only a quarter of the list (single linked would have */
/* needed to walk half the list on average). */
/* In an empty entry, keypointer == NULL, keyint == 0, */
/* (int)valuepointer == forward link subscript (-1 ends), */
/* valueint == backward link subscript (-1 ends). */
};

/* hashtable_bucket */
struct hashtable_bucket {
int * list; /* list of indices into hash entry list */
int size;
};

/* hashtable */
struct hashtable {
/* This is a frequently accessed data structure. For best memory */
/* alignment, all the pointer fields are at the beginning and the */
/* other members ordered by decreasing size and popularity after */
/* that. Some compilers may do that anyway, but manual ordering */
/* is only a slight inconvenience. */
struct hashtable_entry * entrylist;
struct hashtable_bucket * bucketlist1;
struct hashtable_bucket * bucketlist2;
float loadfactorlow; /* threshold to halve the number of buckets */
float loadfactorhigh; /* threshold to double number of buckets */
int salt; /* random seed for hashing function */
int entrylistsize; /* total including deleted entries */
int entrycount; /* number of actual (not deleted) entries */
int deletedentryhead; /* head of linked list of deleted entries */
int deletedentrytail; /* tail of linked list of deleted entries */
int bucketmask1; /* eg 0x3f when there are 64 buckets */
int bucketmask2; /* eg 0x3f when there are 64 buckets */
int emptybuckets; /* to decide when to shorten bucket list */
};

/* hashtable_iterator */
struct hashtable_iterator {
struct hashtable * hashtable;
int nextentryindex; /* >=0 when iterating, -1 when done */
};

/* Function declarations */
struct hashtable * hashtable_new();
int hashtable_store(struct hashtable * hash, void * keypointer, int keylength, void * valuepointer, int valueint);
int hashtable_fetch(struct hashtable * hash, void * keypointer, int keylength, void ** valuepointerpointer, int * valueintpointer);
int hashtable_delete(struct hashtable * hash, void * keypointer, int keylength);
void hashtable_free(struct hashtable * hash);
void hashtable_iterator_init(struct hashtable * hash, struct hashtable_iterator * iter);
int hashtable_iterator_next(struct hashtable_iterator * iter, struct hashtable_entry * entry);

/* end of hashtable.h */
55 changes: 29 additions & 26 deletions c/t/01-toolchain/01a-cc.c
Expand Up @@ -137,13 +137,13 @@ remove_exe()
perror("01a-cc error 6:");
exit(6);
}
printf("ok 6 - unlink testexe.c\n");
printf("ok 6 - remove testexe.c\n");
status = unlink("testexe" EXT_EXE);
if (status) {
perror("01a-cc error 7:");
exit(5);
}
printf("ok 7 - unlink testexe" EXT_EXE "\n");
printf("ok 7 - remove testexe" EXT_EXE "\n");
}


Expand Down Expand Up @@ -173,7 +173,7 @@ create_lib()
);
fclose(testlib_sourcefile);
#ifdef _WIN32
#ifdef MSVC
#ifdef _MSC_VER
status = system("cl -LD -WX -nologo testlib.c >nul"); /* Visual C++ */
#else
status = system("gcc -mdll -o testlib.dll testlib.c"); /* MinGW */
Expand All @@ -183,6 +183,9 @@ create_lib()
if (status==0) {
status = system("cc -shared -s -o testlib.so testlib.o");
}
if (status==0) {
status = system("rm testlib.o");
}
#endif
if (status) {
perror("01a-cc error 8:");
Expand Down Expand Up @@ -215,38 +218,38 @@ load_lib()
exit(9);
}
#endif
printf("ok 9 - loaded testlib" EXT_DYNLIB "\n");
printf("ok 9 - load testlib" EXT_DYNLIB "\n");

#ifdef _WIN32
pfunction = GetProcAddress(testlib, "testfunction");
#else
dlerror(); /* clear any possible error */
pfunction = dlsym(testlib, "testfunction");
if( (error = dlerror()) != NULL ) {
fprintf(stderr, "01a-cc error 11: %s\n", error);
fprintf(stderr, "01a-cc error 10: %s\n", error);
exit(10);
}
#endif
if (pfunction == NULL) {
fprintf(stderr, "01a-cc error 11a: GetProcAddress returned NULL\n");
exit(11);
fprintf(stderr, "01a-cc error 10a: GetProcAddress returned NULL\n");
exit(10);
}
printf("ok 11 - dlsym testfunction\n");
result = (* pfunction)(12, "call testfunction"); /* prints "ok 12" */
if (result == 42+12)
printf("ok 13 - testfunction result\n");
printf("ok 10 - dlsym testfunction\n");
result = (* pfunction)(11, "call testfunction"); /* prints "ok 12" */
if (result == 42+11)
printf("ok 12 - testfunction result\n");
else
printf("not ok 13 - testfunction result\n");
printf("not ok 12 - testfunction result\n");
#ifdef _WIN32
result = ! FreeLibrary(testlib); /* returns 0 for failure! */
#else
result = dlclose(testlib);
#endif
if (result) {
fprintf(stderr, "01a-cc error 14: %s\n", error);
fprintf(stderr, "01a-cc error 13: %s\n", error);
exit(EXIT_FAILURE);
}
printf("ok 14 - dlclose\n");
printf("ok 13 - unload library\n");
}


Expand All @@ -257,34 +260,34 @@ remove_lib()
int status;
status = unlink("testlib.c");
if (status) {
perror("01a-cc error 15:");
exit(15);
perror("01a-cc error 14:");
exit(14);
}
printf("ok 15 - unlink testlib.c\n");
#ifdef MSVC
printf("ok 14 - remove testlib.c\n");
#ifdef _MSC_VER
status = unlink("testlib" EXT_OBJ);
if (status) {
perror("01a-cc error 16:");
exit(16);
perror("01a-cc error 15:");
exit(15);
}
printf("ok 16 - unlink testlib" EXT_OBJ "\n");
printf("ok 15 - remove testlib" EXT_OBJ "\n");
#else
printf("ok 16 - unlink testlib # SKIPPED\n");
printf("ok 15 - remove testlib # SKIPPED\n"); /* MinGW */
#endif
status = unlink("testlib" EXT_DYNLIB);
if (status) {
perror("01a-cc error 17:");
exit(17);
perror("01a-cc error 16:");
exit(16);
}
printf("ok 17 - unlink testlib" EXT_DYNLIB "\n");
printf("ok 16 - remove testlib" EXT_DYNLIB "\n");
}


/* main */
int
main(int argc, char * argv[])
{
printf("1..17\n"); /* tests */
printf("1..16\n"); /* tests */
create_exe(); /* 1-2 make testexe.c and testexe.exe */
run_exe(); /* 2-5 run testexe.exe */
remove_exe(); /* 6-7 remove testexe.c and testexe.exe */
Expand Down

0 comments on commit 74a549e

Please sign in to comment.