Statistics
| Revision:

root / trunk / plugins / jsonrpc / linkhash.c @ 1859

History | View | Annotate | Download (5 KB)

1
/* 
2
 * $Id: linkhash.c,v 1.2 2004/07/21 01:24:33 mclark Exp $
3
 *
4
 * Copyright Metaparadigm Pte. Ltd. 2004.
5
 * Michael Clark 
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public (LGPL)
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details: https://www.gnu.org/
16
 *
17
 */
18

                
19
#include 
20
#include 
21
#include 
22
#include 
23

                
24
#include "linkhash.h"
25

                
26

                
27
void lh_abort(const char *msg, ...)
28
{
29
        va_list ap;
30
        va_start(ap, msg);
31
        vprintf(msg, ap);
32
        exit(1);
33
}
34

                
35

                
36
#pragma GCC diagnostic push
37
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
38
unsigned long lh_ptr_hash(void *k)
39
{
40
        return ((long)k * LH_PRIME) >> 4;
41
}
42
#pragma GCC diagnostic pop
43

                
44

                
45
int lh_ptr_equal(void *k1, void *k2)
46
{
47
        return (k1 == k2);
48
}
49

                
50

                
51
unsigned long lh_char_hash(void *k)
52
{
53
        unsigned int h = 0;
54
        const char* data = k;
55
 
56
        while( *data!=0 ) h = h*129 + (unsigned int)(*data++) + LH_PRIME;
57

                
58
        return h;
59
}
60

                
61

                
62
int lh_char_equal(void *k1, void *k2)
63
{
64
        return (strcmp((char*)k1, (char*)k2) == 0);
65
}
66

                
67

                
68
struct lh_table* lh_table_new(int size, char *name,
69
                              lh_entry_free_fn *free_fn,
70
                              lh_hash_fn *hash_fn,
71
                              lh_equal_fn *equal_fn)
72
{
73
        int i;
74
        struct lh_table *t;
75

                
76
        t = calloc(1, sizeof(struct lh_table));
77
        if(!t) lh_abort("lh_table_new: calloc failed\n");
78
        t->count = 0;
79
        t->size = size;
80
        t->name = name;
81
        t->table = calloc(size, sizeof(struct lh_entry));
82
        if(!t->table) lh_abort("lh_table_new: calloc failed\n");
83
        t->free_fn = free_fn;
84
        t->hash_fn = hash_fn;
85
        t->equal_fn = equal_fn;
86
        for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY;
87
        return t;
88
}
89

                
90

                
91
struct lh_table* lh_kchar_table_new(int size, char *name,
92
                                    lh_entry_free_fn *free_fn)
93
{
94
        return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal);
95
}
96

                
97

                
98
struct lh_table* lh_kptr_table_new(int size, char *name,
99
                                   lh_entry_free_fn *free_fn)
100
{
101
        return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal);
102
}
103

                
104

                
105
void lh_table_resize(struct lh_table *t, int new_size)
106
{
107
        struct lh_table *new_t;
108
        struct lh_entry *ent;
109

                
110
        new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn);
111
        ent = t->head;
112
        while(ent) {
113
                lh_table_insert(new_t, ent->k, ent->v);
114
                ent = ent->next;
115
        }
116
        free(t->table);
117
        t->table = new_t->table;
118
        t->size = new_size;
119
        t->head = new_t->head;
120
        t->tail = new_t->tail;
121
        t->resizes++;
122
        free(new_t);
123
}
124

                
125

                
126
void lh_table_free(struct lh_table *t)
127
{
128
        struct lh_entry *c;
129
        for(c = t->head; c != NULL; c = c->next) {
130
                if(t->free_fn) {
131
                        t->free_fn(c);
132
                }
133
        }
134
        free(t->table);
135
        free(t);
136
}
137

                
138

                
139
int lh_table_insert(struct lh_table *t, void *k, void *v)
140
{
141
        unsigned long h, n;
142

                
143
        t->inserts++;
144
        if(t->count > t->size * 0.66) lh_table_resize(t, t->size * 2);
145

                
146
        h = t->hash_fn(k);
147
        n = h % t->size;
148

                
149
        while( 1 ) {
150
                if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break;
151
                t->collisions++;
152
                if(++n == t->size) n = 0;
153
        }
154

                
155
        t->table[n].k = k;
156
        t->table[n].v = v;
157
        t->count++;
158

                
159
        if(t->head == NULL) {
160
                t->head = t->tail = &t->table[n];
161
                t->table[n].next = t->table[n].prev = NULL;
162
        } else {
163
                t->tail->next = &t->table[n];
164
                t->table[n].prev = t->tail;
165
                t->table[n].next = NULL;
166
                t->tail = &t->table[n];
167
        }
168

                
169
        return 0;
170
}
171

                
172

                
173
struct lh_entry* lh_table_lookup_entry(struct lh_table *t, void *k)
174
{
175
        unsigned long h = t->hash_fn(k);
176
        unsigned long n = h % t->size;
177

                
178
        t->lookups++;
179
        while( 1 ) {
180
                if(t->table[n].k == LH_EMPTY) return NULL;
181
                if(t->table[n].k != LH_FREED &&
182
                   t->equal_fn(t->table[n].k, k)) return &t->table[n];
183
                if(++n == t->size) n = 0;
184
        }
185
        return NULL;
186
}
187

                
188

                
189
void* lh_table_lookup(struct lh_table *t, void *k)
190
{
191
        struct lh_entry *e = lh_table_lookup_entry(t, k);
192
        if(e) return e->v;
193
        return NULL;
194
}
195

                
196

                
197
int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
198
{
199
        int n = e - t->table;
200
        if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1;
201
        t->count--;
202
        if(t->free_fn) t->free_fn(e);
203
        t->table[n].v = NULL;
204
        t->table[n].k = LH_FREED;
205
        if(t->tail == &t->table[n] && t->head == &t->table[n]) {
206
                t->head = t->tail = NULL;
207
        } else if (t->head == &t->table[n]) {
208
                t->head->next->prev = NULL;
209
                t->head = t->head->next;
210
        } else if (t->tail == &t->table[n]) {
211
                t->tail->prev->next = NULL;
212
                t->tail = t->tail->prev;
213
        } else {
214
                t->table[n].prev->next = t->table[n].next;
215
                t->table[n].next->prev = t->table[n].prev;
216
        }
217
        t->table[n].next = t->table[n].prev = NULL;
218
        return 0;
219
}
220

                
221

                
222
int lh_table_delete(struct lh_table *t, void *k)
223
{
224
        struct lh_entry *e = lh_table_lookup_entry(t, k);
225
        if(!e) return -1;
226
        return lh_table_delete_entry(t, e);
227
}
228