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 
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 
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 
int dictionary_set(dictionary *d, const char *key, const char *val)
Set a value in a dictionary.
Definition: dictionary.c:147
#define DICTMINSZ
Minimal allocated number of entries in a dictionary.
Definition: dictionary.c:50
const char * dictionary_get(dictionary *d, const char *key, const char *def)
Get a value from a dictionary.
Definition: dictionary.c:128
dictionary * dictionary_new(int size)
Create a new dictionary object.
Definition: dictionary.c:92
void dictionary_del(dictionary *d)
Delete a dictionary object.
Definition: dictionary.c:109
void dictionary_unset(dictionary *d, const char *key)
Delete a key in a dictionary.
Definition: dictionary.c:206
void dictionary_dump(dictionary *d, FILE *out)
Dump a dictionary to an opened file pointer.
Definition: dictionary.c:241
Dictionary object.
Definition: dictionary.h:67
unsigned dictionary_hash(const char *key)
Compute the hash key for a string.
Definition: dictionary.c:74
Implements a dictionary for string variables.This module implements a simple dictionary object...