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