From 95af8738513940a1c8d7d7463edd2e52997e99a4 Mon Sep 17 00:00:00 2001 From: tmeissner Date: Sat, 16 May 2015 21:54:22 +0200 Subject: [PATCH] add new example of a (simple & not so safe) dictionary implementation from chapter 11 --- 21st_century_c/chapter11/Makefile | 6 ++- 21st_century_c/chapter11/dict.c | 84 +++++++++++++++++++++++++++++ 21st_century_c/chapter11/dict.h | 17 ++++++ 21st_century_c/chapter11/dict_use.c | 23 ++++++++ 21st_century_c/chapter11/keyval.c | 53 ++++++++++++++++++ 21st_century_c/chapter11/keyval.h | 10 ++++ 6 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 21st_century_c/chapter11/dict.c create mode 100644 21st_century_c/chapter11/dict.h create mode 100644 21st_century_c/chapter11/dict_use.c create mode 100644 21st_century_c/chapter11/keyval.c create mode 100644 21st_century_c/chapter11/keyval.h diff --git a/21st_century_c/chapter11/Makefile b/21st_century_c/chapter11/Makefile index 74dfa6c..a0efbee 100644 --- a/21st_century_c/chapter11/Makefile +++ b/21st_century_c/chapter11/Makefile @@ -1,4 +1,4 @@ -CFLAGS = -Wall -O3 --std=c11 +CFLAGS = -Wall -O0 --std=c11 -g simple_cplx : cplx.h complex.c simple_cplx.c @@ -10,6 +10,9 @@ seamlessone : seamlessone.c seamlesstwo : seamlesstwo.c $(CC) $(CFLAGS) -fms-extensions -Wno-microsoft $@.c -o $@ +dict_use : keyval.h keyval.c dict.h dict.c dict_use.c + $(CC) $(CFLAGS) keyval.c dict.c $@.c -o $@ + .PHONY : all all : simple_cplx seamlessone seamlesstwo @@ -23,4 +26,5 @@ clean : rm -f simple_cplx rm -f seamlessone rm -f seamlesstwo + rm -f dict_use rm -rf *.dSYM diff --git a/21st_century_c/chapter11/dict.c b/21st_century_c/chapter11/dict.c new file mode 100644 index 0000000..abed088 --- /dev/null +++ b/21st_century_c/chapter11/dict.c @@ -0,0 +1,84 @@ +#include +#include +#include "dict.h" + + + +void *dictionary_not_found; + + +dictionary *dictionary_new(void) { + + static int dnf; + if (!dictionary_not_found) { + dictionary_not_found = &dnf; + } + dictionary *out = malloc(sizeof(dictionary)); + if(out != NULL) { + *out = (dictionary) {}; + } else { + fprintf(stderr, "Out of memory.\n"); + abort(); + } + return out; + +} + + +static void dictionary_add_keyval(dictionary *in, keyval *kv) { + + in->length++; + in->pairs = realloc(in->pairs, sizeof(keyval*) * in->length); + if(in->pairs != NULL) { + in->pairs[in->length-1] = kv; + } else { + fprintf(stderr, "Out of memory.\n"); + abort(); + } + +} + + +void dictionary_add(dictionary *in, char *key, void *value) { + + if(key == NULL) { + fprintf(stderr, "NULL is not a valid key.\n"); + abort(); + } + dictionary_add_keyval(in, keyval_new(key, value)); + +} + + +void *dictionary_find(const dictionary *in, const char *key) { + + for (size_t i = 0; i < in->length; i++) { + if (keyval_matches(in->pairs[i], key)) { + return in->pairs[i]->value; + } + } + return dictionary_not_found; + +} + + +dictionary *dictionary_copy(dictionary *in) { + + dictionary *out = dictionary_new(); + for (size_t i = 0; i < in->length; i++) { + dictionary_add_keyval(out, keyval_copy(in->pairs[i])); + } + return out; + +} + + +void dictionary_free(dictionary *in) { + + for (size_t i = 0; i < in->length; i++) { + keyval_free(in->pairs[i]); + } + free(in); + +} + diff --git a/21st_century_c/chapter11/dict.h b/21st_century_c/chapter11/dict.h new file mode 100644 index 0000000..c2f700a --- /dev/null +++ b/21st_century_c/chapter11/dict.h @@ -0,0 +1,17 @@ +#include "keyval.h" + + + +extern void *dictionary_not_found; + +typedef struct dictionary { + keyval **pairs; + size_t length; +} dictionary; + + +dictionary *dictionary_new(void); +dictionary *dictionary_copy(dictionary *in); +void dictionary_free(dictionary *in); +void dictionary_add(dictionary *in, char *key, void *value); +void *dictionary_find(const dictionary *in, const char *key); diff --git a/21st_century_c/chapter11/dict_use.c b/21st_century_c/chapter11/dict_use.c new file mode 100644 index 0000000..27e52f5 --- /dev/null +++ b/21st_century_c/chapter11/dict_use.c @@ -0,0 +1,23 @@ +#include +#include "dict.h" + + + +int main() { + + int zero = 0; + float one = 1.0; + char two[] = "two"; + + dictionary *d = dictionary_new(); + + dictionary_add(d, "an int", &zero); + dictionary_add(d, "a float", &one); + dictionary_add(d, "a string", &two); + + printf("The integer I recorded was: %i\n", *(int*) dictionary_find(d, "an int")); + printf("The string I recorded was: %s\n", (char*) dictionary_find(d, "a string")); + + dictionary_free(d); + +} \ No newline at end of file diff --git a/21st_century_c/chapter11/keyval.c b/21st_century_c/chapter11/keyval.c new file mode 100644 index 0000000..e0cb246 --- /dev/null +++ b/21st_century_c/chapter11/keyval.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include "keyval.h" + + + +/* +Create a new key/value pair. +*/ +keyval *keyval_new(char *key, void *value) { + keyval *out = malloc(sizeof(keyval)); + if(out != NULL) { + *out = (keyval){.key = key, .value = value}; + } else { + fprintf(stderr, "Out of memory.\n"); + abort(); + } + return out; +} + +/* +Copy a key/value pair. The new pair has pointers to +the values in the old pair, not copies of their data. +*/ +keyval *keyval_copy(const keyval *in) { + keyval *out = malloc(sizeof(keyval)); + if(out != NULL) { + *out = *in; + } else { + fprintf(stderr, "Out of memory.\n"); + abort(); + } + return out; +} + + +/* +Free a existing key/value pair. +*/ +void keyval_free(keyval *in) { + if(in != NULL) { + free(in); + } +} + + +/* +Check if key of key/value pair matches given key. +*/ +int keyval_matches(const keyval *in, const char *key) { + return !strcasecmp(in->key, key); +} diff --git a/21st_century_c/chapter11/keyval.h b/21st_century_c/chapter11/keyval.h new file mode 100644 index 0000000..4f4e54e --- /dev/null +++ b/21st_century_c/chapter11/keyval.h @@ -0,0 +1,10 @@ +typedef struct keyval { + char *key; + void *value; +} keyval; + + +keyval *keyval_new(char *key, void *value); +keyval *keyval_copy(const keyval *in); +void keyval_free(keyval *in); +int keyval_matches(const keyval *in, const char *key);