| LIRC libraries LinuxInfraredRemoteControl

dictionary.c
Go to the documentation of this file.
1 /* Copyright (c) 2000-2007 by Nicolas Devillard.
2 * Copyright (x) 2009 by Tim Post <tinkertim@gmail.com>
3 * MIT License
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
39 #include "dictionary.h"
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45
47 #define MAXVALSZ 1024
48
50 #define DICTMINSZ 128
51
53 #define DICT_INVALID_KEY ((char*)-1)
54
60 static void* mem_double(void* ptr, int size)
61 {
62 void* newptr;
63
64 newptr = calloc(2 * size, 1);
65 if (newptr == NULL)
66 return NULL;
67 memcpy(newptr, ptr, size);
68 free(ptr);
69 return newptr;
70 }
71
72 /* The remaining exposed functions are documented in dictionary.h */
73
74 unsigned dictionary_hash(const char* key)
75 {
76 int len;
77 unsigned hash;
78 int i;
79
80 len = strlen(key);
81 for (hash = 0, i = 0; i < len; i++) {
82 hash += (unsigned)key[i];
83 hash += (hash << 10);
84 hash ^= (hash >> 6);
85 }
86 hash += (hash << 3);
87 hash ^= (hash >> 11);
88 hash += (hash << 15);
89 return hash;
90 }
91
92 dictionary* dictionary_new(int size)
93 {
94 dictionary* d;
95
96 /* If no size was specified, allocate space for DICTMINSZ */
97 if (size < DICTMINSZ)
98 size = DICTMINSZ;
99
100 if (!(d = (dictionary*)calloc(1, sizeof(dictionary))))
101 return NULL;
102 d->size = size;
103 d->val = (char**)calloc(size, sizeof(char*));
104 d->key = (char**)calloc(size, sizeof(char*));
105 d->hash = (unsigned int*)calloc(size, sizeof(unsigned));
106 return d;
107 }
108
109 void dictionary_del(dictionary* d)
110 {
111 int i;
112
113 if (d == NULL)
114 return;
115 for (i = 0; i < d->size; i++) {
116 if (d->key[i] != NULL)
117 free(d->key[i]);
118 if (d->val[i] != NULL)
119 free(d->val[i]);
120 }
121 free(d->val);
122 free(d->key);
123 free(d->hash);
124 free(d);
125 return;
126 }
127
128 const char* dictionary_get(dictionary* d, const char* key, const char* def)
129 {
130 unsigned hash;
131 int i;
132
133 hash = dictionary_hash(key);
134 for (i = 0; i < d->size; i++) {
135 if (d->key[i] == NULL)
136 continue;
137 /* Compare hash */
138 if (hash == d->hash[i]) {
139 /* Compare string, to avoid hash collisions */
140 if (!strcmp(key, d->key[i]))
141 return d->val[i];
142 }
143 }
144 return def;
145 }
146
147 int dictionary_set(dictionary* d, const char* key, const char* val)
148 {
149 int i;
150 unsigned hash;
151
152 if (d == NULL || key == NULL)
153 return -1;
154
155 /* Compute hash for this key */
156 hash = dictionary_hash(key);
157 /* Find if value is already in dictionary */
158 if (d->n > 0) {
159 for (i = 0; i < d->size; i++) {
160 if (d->key[i] == NULL)
161 continue;
162 /* Same hash value */
163 if (hash == d->hash[i]) {
164 /* Same key */
165 if (!strcmp(key, d->key[i])) {
166 /* Found a value: modify and return */
167 if (d->val[i] != NULL)
168 free(d->val[i]);
169 d->val[i] = val ? strdup(val) : NULL;
170 /* Value has been modified: return */
171 return 0;
172 }
173 }
174 }
175 }
176
177 /* Add a new value
178 * See if dictionary needs to grow */
179 if (d->n == d->size) {
180 /* Reached maximum size: reallocate dictionary */
181 d->val = (char**)mem_double(d->val, d->size * sizeof(char*));
182 d->key = (char**)mem_double(d->key, d->size * sizeof(char*));
183 d->hash = (unsigned int*)
184 mem_double(d->hash, d->size * sizeof(unsigned));
185 if ((d->val == NULL) || (d->key == NULL) || (d->hash == NULL))
186 /* Cannot grow dictionary */
187 return -1;
188 /* Double size */
189 d->size *= 2;
190 }
191
192 /* Insert key in the first empty slot */
193 for (i = 0; i < d->size; i++) {
194 if (d->key[i] == NULL)
195 /* Add key here */
196 break;
197 }
198 /* Copy key */
199 d->key[i] = strdup(key);
200 d->val[i] = val ? strdup(val) : NULL;
201 d->hash[i] = hash;
202 d->n++;
203 return 0;
204 }
205
206 void dictionary_unset(dictionary* d, const char* key)
207 {
208 unsigned hash;
209 int i;
210
211 if (key == NULL)
212 return;
213
214 hash = dictionary_hash(key);
215 for (i = 0; i < d->size; i++) {
216 if (d->key[i] == NULL)
217 continue;
218 /* Compare hash */
219 if (hash == d->hash[i]) {
220 /* Compare string, to avoid hash collisions */
221 if (!strcmp(key, d->key[i]))
222 /* Found key */
223 break;
224 }
225 }
226 if (i >= d->size)
227 /* Key not found */
228 return;
229
230 free(d->key[i]);
231 d->key[i] = NULL;
232 if (d->val[i] != NULL) {
233 free(d->val[i]);
234 d->val[i] = NULL;
235 }
236 d->hash[i] = 0;
237 d->n--;
238 return;
239 }
240
241 void dictionary_dump(dictionary* d, FILE* out)
242 {
243 int i;
244
245 if (d == NULL || out == NULL)
246 return;
247 if (d->n < 1) {
248 fprintf(out, "empty dictionary\n");
249 return;
250 }
251 for (i = 0; i < d->size; i++) {
252 if (d->key[i]) {
253 fprintf(out, "%20s\t[%s]\n",
254 d->key[i],
255 d->val[i] ? d->val[i] : "UNDEF");
256 }
257 }
258 return;
259 }
260
dictionary_set
int dictionary_set(dictionary *d, const char *key, const char *val)
Set a value in a dictionary.
Definition: dictionary.c:147
DICTMINSZ
#define DICTMINSZ
Definition: dictionary.c:50
dictionary_get
const char * dictionary_get(dictionary *d, const char *key, const char *def)
Get a value from a dictionary.
Definition: dictionary.c:128
dictionary_new
dictionary * dictionary_new(int size)
Create a new dictionary object.
Definition: dictionary.c:92
dictionary_del
void dictionary_del(dictionary *d)
Delete a dictionary object.
Definition: dictionary.c:109
dictionary_unset
void dictionary_unset(dictionary *d, const char *key)
Delete a key in a dictionary.
Definition: dictionary.c:206
dictionary_dump
void dictionary_dump(dictionary *d, FILE *out)
Dump a dictionary to an opened file pointer.
Definition: dictionary.c:241
_dictionary_
Dictionary object.
Definition: dictionary.h:67
dictionary_hash
unsigned dictionary_hash(const char *key)
Compute the hash key for a string.
Definition: dictionary.c:74
dictionary.h
Implements a dictionary for string variables.This module implements a simple dictionary object...