1 /* This file is part of the Zebra server.
2 Copyright (C) 2004-2013 Index Data
3
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
18 */
19
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #include <stddef.h>
24 #include <string.h>
25 #include <zebra_strmap.h>
26 #include <yaz/nmem.h>
27 #include <yaz/xmalloc.h>
28
29 struct strmap_entry {
30 char *name;
31 size_t data_len;
32 void *data_buf;
33 struct strmap_entry *next;
34 };
35
36 struct zebra_strmap {
37 NMEM nmem_str;
38 NMEM nmem_ent;
39 int hsize;
40 int size;
41 struct strmap_entry **entries;
42 struct strmap_entry *free_entries;
43 };
44
zebra_strmap_create(void)45 zebra_strmap_t zebra_strmap_create(void)
46 {
47 int i;
48 NMEM nmem_ent = nmem_create();
49 zebra_strmap_t st = nmem_malloc(nmem_ent, sizeof(*st));
50 st->nmem_ent = nmem_ent;
51 st->nmem_str = nmem_create();
52 st->hsize = 1001;
53 st->size = 0;
54 st->free_entries = 0;
55 st->entries = nmem_malloc(nmem_ent, st->hsize * sizeof(*st->entries));
56 for (i = 0; i < st->hsize; i++)
57 st->entries[i] = 0;
58 return st;
59 }
60
zebra_strmap_destroy(zebra_strmap_t st)61 void zebra_strmap_destroy(zebra_strmap_t st)
62 {
63 if (st)
64 {
65 nmem_destroy(st->nmem_str);
66 nmem_destroy(st->nmem_ent);
67 }
68 }
69
hash(zebra_strmap_t st,const char * name)70 static struct strmap_entry **hash(zebra_strmap_t st, const char *name)
71 {
72 unsigned hash = 0;
73 int i;
74 for (i = 0; name[i]; i++)
75 hash += hash*65519 + name[i];
76 hash = hash % st->hsize;
77 return st->entries + hash;
78 }
79
zebra_strmap_add(zebra_strmap_t st,const char * name,void * data_buf,size_t data_len)80 void zebra_strmap_add(zebra_strmap_t st, const char *name,
81 void *data_buf, size_t data_len)
82 {
83 struct strmap_entry **e = hash(st, name);
84 struct strmap_entry *ne = st->free_entries;
85
86 if (ne)
87 st->free_entries = ne->next;
88 else
89 ne = nmem_malloc(st->nmem_ent, sizeof(*ne));
90 ne->next = *e;
91 *e = ne;
92 ne->name = nmem_strdup(st->nmem_str, name);
93 ne->data_buf = nmem_malloc(st->nmem_str, data_len);
94 memcpy(ne->data_buf, data_buf, data_len);
95 ne->data_len = data_len;
96 (st->size)++;
97 }
98
zebra_strmap_lookup(zebra_strmap_t st,const char * name,int no,size_t * data_len)99 void *zebra_strmap_lookup(zebra_strmap_t st, const char *name, int no,
100 size_t *data_len)
101 {
102 struct strmap_entry *e = *hash(st, name);
103 int i = 0;
104 for (; e ; e = e->next)
105 if (!strcmp(name, e->name))
106 {
107 if (i == no)
108 {
109 if (data_len)
110 *data_len = e->data_len;
111 return e->data_buf;
112 }
113 i++;
114 }
115 return 0;
116 }
117
zebra_strmap_remove(zebra_strmap_t st,const char * name)118 int zebra_strmap_remove(zebra_strmap_t st, const char *name)
119 {
120 struct strmap_entry **e = hash(st, name);
121 for (; *e ; e = &(*e)->next)
122 if (!strcmp(name, (*e)->name))
123 {
124 struct strmap_entry *tmp = *e;
125 *e = (*e)->next;
126
127 tmp->next = st->free_entries;
128 st->free_entries = tmp;
129
130 --(st->size);
131 return 1;
132 }
133 return 0;
134 }
135
zebra_strmap_get_size(zebra_strmap_t st)136 int zebra_strmap_get_size(zebra_strmap_t st)
137 {
138 return st->size;
139 }
140
141 struct zebra_strmap_it_s {
142 int hno;
143 struct strmap_entry *ent;
144 zebra_strmap_t st;
145
146 };
147
zebra_strmap_it_create(zebra_strmap_t st)148 zebra_strmap_it zebra_strmap_it_create(zebra_strmap_t st)
149 {
150 zebra_strmap_it it = (zebra_strmap_it) xmalloc(sizeof(*it));
151 it->hno = 0;
152 it->ent = 0;
153 it->st = st;
154 return it;
155 }
156
zebra_strmap_it_destroy(zebra_strmap_it it)157 void zebra_strmap_it_destroy(zebra_strmap_it it)
158 {
159 xfree(it);
160 }
161
zebra_strmap_it_next(zebra_strmap_it it,void ** data_buf,size_t * data_len)162 const char *zebra_strmap_it_next(zebra_strmap_it it, void **data_buf,
163 size_t *data_len)
164 {
165 struct strmap_entry *ent = 0;
166 while (!it->ent && it->hno < it->st->hsize)
167 {
168 it->ent = it->st->entries[it->hno];
169 it->hno++;
170 }
171 if (it->ent)
172 {
173 ent = it->ent;
174 it->ent = ent->next;
175 }
176 if (ent)
177 {
178 if (data_buf)
179 *data_buf = ent->data_buf;
180 if (data_len)
181 *data_len = ent->data_len;
182 return ent->name;
183 }
184 return 0;
185 }
186
187 /*
188 * Local variables:
189 * c-basic-offset: 4
190 * c-file-style: "Stroustrup"
191 * indent-tabs-mode: nil
192 * End:
193 * vim: shiftwidth=4 tabstop=8 expandtab
194 */
195
196