12 #include "dictionary.h"
14 // ----------------------------------------------------------------------------
17 static int name_value_iterator(avl *a) { if(a) {}; return 0; }
19 static int name_value_compare(void* a, void* b) {
20 if(((NAME_VALUE *)a)->hash < ((NAME_VALUE *)b)->hash) return -1;
21 else if(((NAME_VALUE *)a)->hash > ((NAME_VALUE *)b)->hash) return 1;
22 else return strcmp(((NAME_VALUE *)a)->name, ((NAME_VALUE *)b)->name);
25 #define name_value_index_add(dict, cv) avl_insert(&((dict)->values_index), (avl *)(cv))
26 #define name_value_index_del(dict, cv) avl_remove(&((dict)->values_index), (avl *)(cv))
28 static NAME_VALUE *dictionary_name_value_index_find(DICTIONARY *dict, const char *name, uint32_t hash) {
29 NAME_VALUE *result = NULL, tmp;
30 tmp.hash = (hash)?hash:simple_hash(name);
31 tmp.name = (char *)name;
33 avl_search(&(dict->values_index), (avl *)&tmp, name_value_iterator, (avl **)&result);
37 // ----------------------------------------------------------------------------
39 static NAME_VALUE *dictionary_name_value_create(DICTIONARY *dict, const char *name, void *value, size_t value_len) {
40 debug(D_DICTIONARY, "Creating name value entry for name '%s', value '%s'.", name, value);
42 NAME_VALUE *nv = calloc(1, sizeof(NAME_VALUE));
43 if(!nv) fatal("Cannot allocate name_value of size %z", sizeof(NAME_VALUE));
45 nv->name = strdup(name);
46 if(!nv->name) fatal("Cannot allocate name_value.name of size %z", strlen(name));
47 nv->hash = simple_hash(nv->name);
49 nv->value = malloc(value_len);
50 if(!nv->value) fatal("Cannot allocate name_value.value of size %z", value_len);
51 memcpy(nv->value, value, value_len);
54 pthread_rwlock_wrlock(&dict->rwlock);
55 nv->next = dict->values;
57 pthread_rwlock_unlock(&dict->rwlock);
60 name_value_index_add(dict, nv);
65 static void dictionary_name_value_destroy(DICTIONARY *dict, NAME_VALUE *nv) {
66 debug(D_DICTIONARY, "Destroying name value entry for name '%s'.", nv->name);
68 pthread_rwlock_wrlock(&dict->rwlock);
69 if(dict->values == nv) dict->values = nv->next;
71 NAME_VALUE *n = dict->values;
72 while(n && n->next && n->next != nv) nv = nv->next;
73 if(!n || n->next != nv) fatal("Cannot find name_value with name '%s' in dictionary.", nv->name);
77 pthread_rwlock_unlock(&dict->rwlock);
83 // ----------------------------------------------------------------------------
85 DICTIONARY *dictionary_create(void) {
86 debug(D_DICTIONARY, "Creating dictionary.");
88 DICTIONARY *dict = calloc(1, sizeof(DICTIONARY));
89 if(!dict) fatal("Cannot allocate DICTIONARY");
91 dict->values_index.compar = name_value_compare;
92 pthread_rwlock_init(&dict->rwlock, NULL);
97 void dictionary_destroy(DICTIONARY *dict) {
98 debug(D_DICTIONARY, "Destroying dictionary.");
100 pthread_rwlock_wrlock(&dict->rwlock);
101 while(dict->values) dictionary_name_value_destroy(dict, dict->values);
102 pthread_rwlock_unlock(&dict->rwlock);
107 // ----------------------------------------------------------------------------
109 void *dictionary_set(DICTIONARY *dict, const char *name, void *value, size_t value_len) {
110 debug(D_DICTIONARY, "SET dictionary entry with name '%s'.", name);
112 pthread_rwlock_rdlock(&dict->rwlock);
113 NAME_VALUE *nv = dictionary_name_value_index_find(dict, name, 0);
114 pthread_rwlock_unlock(&dict->rwlock);
116 debug(D_DICTIONARY, "Dictionary entry with name '%s' not found. Creating a new one.", name);
117 nv = dictionary_name_value_create(dict, name, value, value_len);
118 if(!nv) fatal("Cannot create name_value.");
122 debug(D_DICTIONARY, "Dictionary entry with name '%s' found. Changing its value.", name);
123 pthread_rwlock_wrlock(&dict->rwlock);
124 void *old = nv->value;
125 nv->value = malloc(value_len);
126 if(!nv->value) fatal("Cannot allocate value of size %z", value_len);
127 memcpy(nv->value, value, value_len);
128 pthread_rwlock_unlock(&dict->rwlock);
135 void *dictionary_get(DICTIONARY *dict, const char *name) {
136 debug(D_DICTIONARY, "GET dictionary entry with name '%s'.", name);
138 pthread_rwlock_rdlock(&dict->rwlock);
139 NAME_VALUE *nv = dictionary_name_value_index_find(dict, name, 0);
140 pthread_rwlock_unlock(&dict->rwlock);
142 debug(D_DICTIONARY, "Not found dictionary entry with name '%s'.", name);
146 debug(D_DICTIONARY, "Found dictionary entry with name '%s'.", name);