9c16def5e2c1adf35a9a65239fc3481156042512
[libradsec.git] / hash.c
1 /* Copyright (c) 2006-2009, Stig Venaas, UNINETT AS.
2  * Copyright (c) 2010, UNINETT AS, NORDUnet A/S.
3  * Copyright (c) 2010-2012, NORDUnet A/S. */
4 /* See LICENSE for licensing information. */
5
6 #include <stdlib.h>
7 #include <string.h>
8 #include <pthread.h>
9 #include "list.h"
10 #include "hash.h"
11
12 /* allocates and initialises hash structure; returns NULL if malloc fails */
13 struct hash *hash_create() {
14     struct hash *h = malloc(sizeof(struct hash));
15     if (!h)
16         return NULL;
17     h->hashlist = list_create();
18     if (!h->hashlist) {
19         free(h);
20         return NULL;
21     }
22     pthread_mutex_init(&h->mutex, NULL);
23     return h;
24 }
25
26 /* frees all memory associated with the hash */
27 void hash_destroy(struct hash *h) {
28     struct list_node *ln;
29
30     if (!h)
31         return;
32     for (ln = list_first(h->hashlist); ln; ln = list_next(ln)) {
33         free(((struct hash_entry *)ln->data)->key);
34         free(((struct hash_entry *)ln->data)->data);
35     }
36     list_destroy(h->hashlist);
37     pthread_mutex_destroy(&h->mutex);
38 }
39
40 /* insert entry in hash; returns 1 if ok, 0 if malloc fails */
41 int hash_insert(struct hash *h, void *key, uint32_t keylen, void *data) {
42     struct hash_entry *e;
43
44     if (!h)
45         return 0;
46     e = malloc(sizeof(struct hash_entry));
47     if (!e)
48         return 0;
49     memset(e, 0, sizeof(struct hash_entry));
50     e->key = malloc(keylen);
51     if (!e->key) {
52         free(e);
53         return 0;
54     }
55     memcpy(e->key, key, keylen);
56     e->keylen = keylen;
57     e->data = data;
58     pthread_mutex_lock(&h->mutex);
59     if (!list_push(h->hashlist, e)) {
60         pthread_mutex_unlock(&h->mutex);
61         free(e->key);
62         free(e);
63         return 0;
64     }
65     pthread_mutex_unlock(&h->mutex);
66     return 1;
67 }
68
69 /* reads entry from hash */
70 void *hash_read(struct hash *h, void *key, uint32_t keylen) {
71     struct list_node *ln;
72     struct hash_entry *e;
73
74     if (!h)
75         return 0;
76     pthread_mutex_lock(&h->mutex);
77     for (ln = list_first(h->hashlist); ln; ln = list_next(ln)) {
78         e = (struct hash_entry *)ln->data;
79         if (e->keylen == keylen && !memcmp(e->key, key, keylen)) {
80             pthread_mutex_unlock(&h->mutex);
81             return e->data;
82         }
83     }
84     pthread_mutex_unlock(&h->mutex);
85     return NULL;
86 }
87
88 /* extracts entry from hash */
89 void *hash_extract(struct hash *h, void *key, uint32_t keylen) {
90     struct list_node *ln;
91     struct hash_entry *e;
92
93     if (!h)
94         return 0;
95     pthread_mutex_lock(&h->mutex);
96     for (ln = list_first(h->hashlist); ln; ln = list_next(ln)) {
97         e = (struct hash_entry *)ln->data;
98         if (e->keylen == keylen && !memcmp(e->key, key, keylen)) {
99             free(e->key);
100             list_removedata(h->hashlist, e);
101             free(e);
102             pthread_mutex_unlock(&h->mutex);
103             return e->data;
104         }
105     }
106     pthread_mutex_unlock(&h->mutex);
107     return NULL;
108 }
109
110 /* returns first entry */
111 struct hash_entry *hash_first(struct hash *hash) {
112     struct list_node *ln;
113     struct hash_entry *e;
114     if (!hash || !((ln = list_first(hash->hashlist))))
115         return NULL;
116     e = (struct hash_entry *)ln->data;
117     e->next = ln->next;
118     return e;
119 }
120
121 /* returns the next node after the argument */
122 struct hash_entry *hash_next(struct hash_entry *entry) {
123     struct hash_entry *e;
124     if (!entry || !entry->next)
125         return NULL;
126     e = (struct hash_entry *)entry->next->data;
127     e->next = (struct list_node *)entry->next->next;
128     return e;
129 }
130
131 /* Local Variables: */
132 /* c-file-style: "stroustrup" */
133 /* End: */