Examples using Bib-1 use attributes
[idzebra-moved-to-github.git] / util / strmap.c
1 /* This file is part of the Zebra server.
2    Copyright (C) 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
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
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
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
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
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
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
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
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
157 void zebra_strmap_it_destroy(zebra_strmap_it it)
158 {
159     xfree(it);
160 }
161
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