Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(681)

Side by Side Diff: third_party/mozprocess/tests/iniparser/dictionary.c

Issue 108313011: Adding mozilla libraries required by Firefox interop test. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 /*-------------------------------------------------------------------------*/
2 /**
3 @file dictionary.c
4 @author N. Devillard
5 @date Sep 2007
6 @version $Revision: 1.27 $
7 @brief Implements a dictionary for string variables.
8
9 This module implements a simple dictionary object, i.e. a list
10 of string/string associations. This object is useful to store e.g.
11 informations retrieved from a configuration file (ini files).
12 */
13 /*--------------------------------------------------------------------------*/
14
15 /*
16 $Id: dictionary.c,v 1.27 2007-11-23 21:39:18 ndevilla Exp $
17 $Revision: 1.27 $
18 */
19 /*---------------------------------------------------------------------------
20 Includes
21 ---------------------------------------------------------------------------*/
22 #include "dictionary.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #ifndef _WIN32
28 #include <unistd.h>
29 #endif
30
31 /** Maximum value size for integers and doubles. */
32 #define MAXVALSZ 1024
33
34 /** Minimal allocated number of entries in a dictionary */
35 #define DICTMINSZ 128
36
37 /** Invalid key token */
38 #define DICT_INVALID_KEY ((char*)-1)
39
40 /*---------------------------------------------------------------------------
41 Private functions
42 ---------------------------------------------------------------------------*/
43
44 /* Doubles the allocated size associated to a pointer */
45 /* 'size' is the current allocated size. */
46 static void * mem_double(void * ptr, int size)
47 {
48 void * newptr ;
49
50 newptr = calloc(2*size, 1);
51 if (newptr==NULL) {
52 return NULL ;
53 }
54 memcpy(newptr, ptr, size);
55 free(ptr);
56 return newptr ;
57 }
58
59 /*-------------------------------------------------------------------------*/
60 /**
61 @brief Duplicate a string
62 @param s String to duplicate
63 @return Pointer to a newly allocated string, to be freed with free()
64
65 This is a replacement for strdup(). This implementation is provided
66 for systems that do not have it.
67 */
68 /*--------------------------------------------------------------------------*/
69 static char * xstrdup(char * s)
70 {
71 char * t ;
72 if (!s)
73 return NULL ;
74 t = malloc(strlen(s)+1) ;
75 if (t) {
76 strcpy(t,s);
77 }
78 return t ;
79 }
80
81 /*---------------------------------------------------------------------------
82 Function codes
83 ---------------------------------------------------------------------------*/
84 /*-------------------------------------------------------------------------*/
85 /**
86 @brief Compute the hash key for a string.
87 @param key Character string to use for key.
88 @return 1 unsigned int on at least 32 bits.
89
90 This hash function has been taken from an Article in Dr Dobbs Journal.
91 This is normally a collision-free function, distributing keys evenly.
92 The key is stored anyway in the struct so that collision can be avoided
93 by comparing the key itself in last resort.
94 */
95 /*--------------------------------------------------------------------------*/
96 unsigned dictionary_hash(char * key)
97 {
98 int len ;
99 unsigned hash ;
100 int i ;
101
102 len = strlen(key);
103 for (hash=0, i=0 ; i<len ; i++) {
104 hash += (unsigned)key[i] ;
105 hash += (hash<<10);
106 hash ^= (hash>>6) ;
107 }
108 hash += (hash <<3);
109 hash ^= (hash >>11);
110 hash += (hash <<15);
111 return hash ;
112 }
113
114 /*-------------------------------------------------------------------------*/
115 /**
116 @brief Create a new dictionary object.
117 @param size Optional initial size of the dictionary.
118 @return 1 newly allocated dictionary objet.
119
120 This function allocates a new dictionary object of given size and returns
121 it. If you do not know in advance (roughly) the number of entries in the
122 dictionary, give size=0.
123 */
124 /*--------------------------------------------------------------------------*/
125 dictionary * dictionary_new(int size)
126 {
127 dictionary * d ;
128
129 /* If no size was specified, allocate space for DICTMINSZ */
130 if (size<DICTMINSZ) size=DICTMINSZ ;
131
132 if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) {
133 return NULL;
134 }
135 d->size = size ;
136 d->val = (char **)calloc(size, sizeof(char*));
137 d->key = (char **)calloc(size, sizeof(char*));
138 d->hash = (unsigned int *)calloc(size, sizeof(unsigned));
139 return d ;
140 }
141
142 /*-------------------------------------------------------------------------*/
143 /**
144 @brief Delete a dictionary object
145 @param d dictionary object to deallocate.
146 @return void
147
148 Deallocate a dictionary object and all memory associated to it.
149 */
150 /*--------------------------------------------------------------------------*/
151 void dictionary_del(dictionary * d)
152 {
153 int i ;
154
155 if (d==NULL) return ;
156 for (i=0 ; i<d->size ; i++) {
157 if (d->key[i]!=NULL)
158 free(d->key[i]);
159 if (d->val[i]!=NULL)
160 free(d->val[i]);
161 }
162 free(d->val);
163 free(d->key);
164 free(d->hash);
165 free(d);
166 return ;
167 }
168
169 /*-------------------------------------------------------------------------*/
170 /**
171 @brief Get a value from a dictionary.
172 @param d dictionary object to search.
173 @param key Key to look for in the dictionary.
174 @param def Default value to return if key not found.
175 @return 1 pointer to internally allocated character string.
176
177 This function locates a key in a dictionary and returns a pointer to its
178 value, or the passed 'def' pointer if no such key can be found in
179 dictionary. The returned character pointer points to data internal to the
180 dictionary object, you should not try to free it or modify it.
181 */
182 /*--------------------------------------------------------------------------*/
183 char * dictionary_get(dictionary * d, char * key, char * def)
184 {
185 unsigned hash ;
186 int i ;
187
188 hash = dictionary_hash(key);
189 for (i=0 ; i<d->size ; i++) {
190 if (d->key[i]==NULL)
191 continue ;
192 /* Compare hash */
193 if (hash==d->hash[i]) {
194 /* Compare string, to avoid hash collisions */
195 if (!strcmp(key, d->key[i])) {
196 return d->val[i] ;
197 }
198 }
199 }
200 return def ;
201 }
202
203 /*-------------------------------------------------------------------------*/
204 /**
205 @brief Set a value in a dictionary.
206 @param d dictionary object to modify.
207 @param key Key to modify or add.
208 @param val Value to add.
209 @return int 0 if Ok, anything else otherwise
210
211 If the given key is found in the dictionary, the associated value is
212 replaced by the provided one. If the key cannot be found in the
213 dictionary, it is added to it.
214
215 It is Ok to provide a NULL value for val, but NULL values for the dictionary
216 or the key are considered as errors: the function will return immediately
217 in such a case.
218
219 Notice that if you dictionary_set a variable to NULL, a call to
220 dictionary_get will return a NULL value: the variable will be found, and
221 its value (NULL) is returned. In other words, setting the variable
222 content to NULL is equivalent to deleting the variable from the
223 dictionary. It is not possible (in this implementation) to have a key in
224 the dictionary without value.
225
226 This function returns non-zero in case of failure.
227 */
228 /*--------------------------------------------------------------------------*/
229 int dictionary_set(dictionary * d, char * key, char * val)
230 {
231 int i ;
232 unsigned hash ;
233
234 if (d==NULL || key==NULL) return -1 ;
235
236 /* Compute hash for this key */
237 hash = dictionary_hash(key) ;
238 /* Find if value is already in dictionary */
239 if (d->n>0) {
240 for (i=0 ; i<d->size ; i++) {
241 if (d->key[i]==NULL)
242 continue ;
243 if (hash==d->hash[i]) { /* Same hash value */
244 if (!strcmp(key, d->key[i])) { /* Same key */
245 /* Found a value: modify and return */
246 if (d->val[i]!=NULL)
247 free(d->val[i]);
248 d->val[i] = val ? xstrdup(val) : NULL ;
249 /* Value has been modified: return */
250 return 0 ;
251 }
252 }
253 }
254 }
255 /* Add a new value */
256 /* See if dictionary needs to grow */
257 if (d->n==d->size) {
258
259 /* Reached maximum size: reallocate dictionary */
260 d->val = (char **)mem_double(d->val, d->size * sizeof(char*)) ;
261 d->key = (char **)mem_double(d->key, d->size * sizeof(char*)) ;
262 d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(u nsigned)) ;
263 if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) {
264 /* Cannot grow dictionary */
265 return -1 ;
266 }
267 /* Double size */
268 d->size *= 2 ;
269 }
270
271 /* Insert key in the first empty slot */
272 for (i=0 ; i<d->size ; i++) {
273 if (d->key[i]==NULL) {
274 /* Add key here */
275 break ;
276 }
277 }
278 /* Copy key */
279 d->key[i] = xstrdup(key);
280 d->val[i] = val ? xstrdup(val) : NULL ;
281 d->hash[i] = hash;
282 d->n ++ ;
283 return 0 ;
284 }
285
286 /*-------------------------------------------------------------------------*/
287 /**
288 @brief Delete a key in a dictionary
289 @param d dictionary object to modify.
290 @param key Key to remove.
291 @return void
292
293 This function deletes a key in a dictionary. Nothing is done if the
294 key cannot be found.
295 */
296 /*--------------------------------------------------------------------------*/
297 void dictionary_unset(dictionary * d, char * key)
298 {
299 unsigned hash ;
300 int i ;
301
302 if (key == NULL) {
303 return;
304 }
305
306 hash = dictionary_hash(key);
307 for (i=0 ; i<d->size ; i++) {
308 if (d->key[i]==NULL)
309 continue ;
310 /* Compare hash */
311 if (hash==d->hash[i]) {
312 /* Compare string, to avoid hash collisions */
313 if (!strcmp(key, d->key[i])) {
314 /* Found key */
315 break ;
316 }
317 }
318 }
319 if (i>=d->size)
320 /* Key not found */
321 return ;
322
323 free(d->key[i]);
324 d->key[i] = NULL ;
325 if (d->val[i]!=NULL) {
326 free(d->val[i]);
327 d->val[i] = NULL ;
328 }
329 d->hash[i] = 0 ;
330 d->n -- ;
331 return ;
332 }
333
334 /*-------------------------------------------------------------------------*/
335 /**
336 @brief Dump a dictionary to an opened file pointer.
337 @param d Dictionary to dump
338 @param f Opened file pointer.
339 @return void
340
341 Dumps a dictionary onto an opened file pointer. Key pairs are printed out
342 as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
343 output file pointers.
344 */
345 /*--------------------------------------------------------------------------*/
346 void dictionary_dump(dictionary * d, FILE * out)
347 {
348 int i ;
349
350 if (d==NULL || out==NULL) return ;
351 if (d->n<1) {
352 fprintf(out, "empty dictionary\n");
353 return ;
354 }
355 for (i=0 ; i<d->size ; i++) {
356 if (d->key[i]) {
357 fprintf(out, "%20s\t[%s]\n",
358 d->key[i],
359 d->val[i] ? d->val[i] : "UNDEF");
360 }
361 }
362 return ;
363 }
364
365
366 /* Test code */
367 #ifdef TESTDIC
368 #define NVALS 20000
369 int main(int argc, char *argv[])
370 {
371 dictionary * d ;
372 char * val ;
373 int i ;
374 char cval[90] ;
375
376 /* Allocate dictionary */
377 printf("allocating...\n");
378 d = dictionary_new(0);
379
380 /* Set values in dictionary */
381 printf("setting %d values...\n", NVALS);
382 for (i=0 ; i<NVALS ; i++) {
383 sprintf(cval, "%04d", i);
384 dictionary_set(d, cval, "salut");
385 }
386 printf("getting %d values...\n", NVALS);
387 for (i=0 ; i<NVALS ; i++) {
388 sprintf(cval, "%04d", i);
389 val = dictionary_get(d, cval, DICT_INVALID_KEY);
390 if (val==DICT_INVALID_KEY) {
391 printf("cannot get value for key [%s]\n", cval);
392 }
393 }
394 printf("unsetting %d values...\n", NVALS);
395 for (i=0 ; i<NVALS ; i++) {
396 sprintf(cval, "%04d", i);
397 dictionary_unset(d, cval);
398 }
399 if (d->n != 0) {
400 printf("error deleting values\n");
401 }
402 printf("deallocating...\n");
403 dictionary_del(d);
404 return 0 ;
405 }
406 #endif
407 /* vim: set ts=4 et sw=4 tw=75 */
OLDNEW
« no previous file with comments | « third_party/mozprocess/tests/iniparser/dictionary.h ('k') | third_party/mozprocess/tests/iniparser/iniparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698