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