1 /**
2 * Hash table to be used by DinkC's 'sp_custom' function
3
4 * Copyright (C) 2008, 2009 Sylvain Beucler
5
6 * This file is part of GNU FreeDink
7
8 * GNU FreeDink is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 3 of the
11 * License, or (at your option) any later version.
12
13 * GNU FreeDink is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "log.h"
32 #include "dinkc_sp_custom.h"
33
34 # include <stdbool.h>
35 struct str_int
36 {
37 char key[200]; // same size as slist[0][]
38 int val;
39 };
40
41 /* Auxiliary functions for hash */
dinkc_sp_custom_hasher(const void * x,size_t tablesize)42 static size_t dinkc_sp_custom_hasher(const void *x, size_t tablesize)
43 {
44 return hash_string(((struct str_int*)x)->key, tablesize);
45 // We could also call 'hash_pjw' from module 'hash-pjw'
46 }
dinkc_sp_custom_comparator(const void * a,const void * b)47 static bool dinkc_sp_custom_comparator(const void* a, const void* b)
48 {
49 return !strcmp(((struct str_int*)a)->key,
50 ((struct str_int*)b)->key);
51 }
52
53 /**
54 * Return a new hash table
55 */
dinkc_sp_custom_new()56 dinkc_sp_custom dinkc_sp_custom_new()
57 {
58 Hash_tuning* default_tuner = NULL;
59 int start_size = 10;
60
61 return hash_initialize(start_size, default_tuner,
62 dinkc_sp_custom_hasher, dinkc_sp_custom_comparator,
63 free);
64 }
65
66 /**
67 * Free all memory
68 */
dinkc_sp_custom_free(dinkc_sp_custom hash)69 void dinkc_sp_custom_free(dinkc_sp_custom hash)
70 {
71 hash_free(hash);
72 }
73
dinkc_sp_custom_clear(dinkc_sp_custom hash)74 void dinkc_sp_custom_clear(dinkc_sp_custom hash)
75 {
76 hash_clear(hash);
77 }
78
79 /**
80 * Create a new int value for key 'key', or replace existing value if
81 * 'key' is already mapped.
82 */
dinkc_sp_custom_set(dinkc_sp_custom hash,char key[200],int val)83 void dinkc_sp_custom_set(dinkc_sp_custom hash, char key[200], int val)
84 {
85 struct str_int search;
86 strcpy(search.key, key);
87 void* slot = hash_lookup(hash, &search);
88 if (slot != NULL)
89 {
90 ((struct str_int*)slot)->val = val;
91 }
92 else
93 {
94 struct str_int* newslot = malloc(sizeof(struct str_int));
95 strcpy(newslot->key, key);
96 ((struct str_int*)newslot)->val = val;
97 if (hash_insert(hash, newslot) == NULL)
98 {
99 log_fatal("sp_custom: Not enough memory to add value '%s'", key);
100 exit(EXIT_FAILURE);
101 }
102 }
103 }
104
105 /**
106 * Get the int value associated with 'key'. Returns -1 if not found
107 * (DinkC limitation: no way to return NULL or similar).
108 */
dinkc_sp_custom_get(dinkc_sp_custom hash,char key[200])109 int dinkc_sp_custom_get(dinkc_sp_custom hash, char key[200])
110 {
111 struct str_int search;
112 strcpy(search.key, key);
113 void* slot = hash_lookup(hash, &search);
114 if (slot != NULL)
115 return ((struct str_int*)slot)->val;
116 else
117 return -1;
118 }
119
120
121 #ifdef TEST
122
main(void)123 int main(void)
124 {
125 dinkc_sp_custom myhash = dinkc_sp_custom_new();
126
127 dinkc_sp_custom_set(myhash, "foo", -1);
128 dinkc_sp_custom_set(myhash, "foo", 3);
129 dinkc_sp_custom_set(myhash, "foo", -1);
130 dinkc_sp_custom_set(myhash, "foo", 4);
131
132 dinkc_sp_custom_set(myhash, "bar", 34);
133
134 printf("foo: %d\n", dinkc_sp_custom_get(myhash, "foo"));
135 printf("bar: %d\n", dinkc_sp_custom_get(myhash, "bar"));
136
137 dinkc_sp_custom_clear(myhash);
138 printf("foo (after clear): %d\n", dinkc_sp_custom_get(myhash, "foo"));
139
140 dinkc_sp_custom_free(myhash);
141 return 0;
142 }
143
144 #endif
145