Put local variables footer in all c, h files.
[idzebra-moved-to-github.git] / index / reckeys.c
1 /* $Id: reckeys.c,v 1.4 2006-05-10 08:13:22 adam Exp $
2    Copyright (C) 1995-2005
3    Index Data ApS
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra.  If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <assert.h>
26 #include <ctype.h>
27
28 #include <yaz/nmem.h>
29 #include "index.h"
30 #include "reckeys.h"
31
32 struct zebra_rec_key_entry {
33     char *buf;
34     size_t len;
35     struct it_key key;
36     struct zebra_rec_key_entry *next;
37 };
38
39 struct zebra_rec_keys_t_ {
40     size_t buf_used;
41     size_t buf_max;
42     size_t fetch_offset;
43     char *buf;
44     void *encode_handle;
45     void *decode_handle;
46     char owner_of_buffer;
47
48     NMEM nmem;
49     size_t hash_size;
50     struct zebra_rec_key_entry **entries; 
51 };
52
53
54 struct zebra_rec_key_entry **zebra_rec_keys_mk_hash(zebra_rec_keys_t p,
55                                                     const char *buf,
56                                                     size_t len)
57 {
58     unsigned h = 0;
59     size_t i;
60     for (i = 0; i<len; i++)
61         h = h * 65509 + buf[i];
62     return &p->entries[h % (unsigned) p->hash_size];
63 }
64
65 static void init_hash(zebra_rec_keys_t p)
66 {
67     p->entries = 0;
68     nmem_reset(p->nmem);
69     if (p->hash_size)
70     {
71         size_t i;
72         p->entries = nmem_malloc(p->nmem, p->hash_size * sizeof(*p->entries));
73         for (i = 0; i<p->hash_size; i++)
74             p->entries[i] = 0;
75     }
76 }
77
78 zebra_rec_keys_t zebra_rec_keys_open()
79 {
80     zebra_rec_keys_t p = xmalloc(sizeof(*p));
81     p->buf_used = 0;
82     p->buf_max = 0;
83     p->fetch_offset = 0;
84     p->buf = 0;
85     p->owner_of_buffer = 1;
86     p->encode_handle = iscz1_start();
87     p->decode_handle = iscz1_start(); 
88
89     p->nmem = nmem_create();
90     p->hash_size = 127;
91     p->entries = 0;
92
93     init_hash(p);
94
95     return p;
96 }
97
98 void zebra_rec_keys_set_buf(zebra_rec_keys_t p, char *buf, size_t sz,
99                             int copy_buf)
100 {
101     if (p->owner_of_buffer)
102         xfree(p->buf);
103     p->buf_used = sz;
104     p->buf_max = sz;
105     if (!copy_buf)
106     {
107         p->buf = buf;
108     }
109     else
110     {
111         if (!sz)
112             p->buf = 0;
113         else
114         {
115             p->buf = xmalloc(sz);
116             memcpy(p->buf, buf, sz);
117         }
118     }
119     p->owner_of_buffer = copy_buf;
120 }
121         
122 void zebra_rec_keys_get_buf(zebra_rec_keys_t p, char **buf, size_t *sz)
123 {
124     *buf = p->buf;
125     *sz = p->buf_used;
126
127     p->buf = 0;
128     p->buf_max = 0;
129     p->buf_used = 0;
130 }
131
132 void zebra_rec_keys_close(zebra_rec_keys_t p)
133 {
134     if (!p)
135         return;
136     
137     if (p->owner_of_buffer)
138         xfree(p->buf);
139     if (p->encode_handle)
140         iscz1_stop(p->encode_handle);
141     if (p->decode_handle)
142         iscz1_stop(p->decode_handle);
143     nmem_destroy(p->nmem);
144     xfree(p);
145 }
146
147 int zebra_rec_keys_add_hash(zebra_rec_keys_t keys, 
148                             const char *str, size_t slen,
149                             const struct it_key *key)
150 {
151     struct zebra_rec_key_entry **kep = zebra_rec_keys_mk_hash(keys, str, slen);
152     while (*kep)
153     {
154         struct zebra_rec_key_entry *e = *kep;
155         if (slen == e->len && !memcmp(str, e->buf, slen) &&
156             !key_compare(key, &e->key))
157         {
158             return 0;
159         }
160         kep = &(*kep)->next;
161     }
162     *kep = nmem_malloc(keys->nmem, sizeof(**kep));
163     (*kep)->next = 0;
164     (*kep)->len = slen;
165     memcpy(&(*kep)->key, key, sizeof(*key));
166     (*kep)->buf = nmem_malloc(keys->nmem, slen);
167     memcpy((*kep)->buf, str, slen);
168     return 1;
169 }
170
171 void zebra_rec_keys_write(zebra_rec_keys_t keys, 
172                           const char *str, size_t slen,
173                           const struct it_key *key)
174 {
175     char *dst;
176     const char *src = (char*) key;
177     
178     assert(keys->owner_of_buffer);
179
180     if (!zebra_rec_keys_add_hash(keys, str, slen, key))
181         return;  /* key already there . Omit it */
182     if (keys->buf_used+1024 > keys->buf_max)
183     {
184         char *b = (char *) xmalloc (keys->buf_max += 128000);
185         if (keys->buf_used > 0)
186             memcpy (b, keys->buf, keys->buf_used);
187         xfree (keys->buf);
188         keys->buf = b;
189     }
190     dst = keys->buf + keys->buf_used;
191
192     iscz1_encode(keys->encode_handle, &dst, &src);
193
194     memcpy (dst, str, slen);
195     dst += slen;
196     *dst++ = '\0';
197     keys->buf_used = dst - keys->buf;
198 }
199
200 void zebra_rec_keys_reset(zebra_rec_keys_t keys)
201 {
202     assert(keys);
203     keys->buf_used = 0;
204     
205     iscz1_reset(keys->encode_handle);
206
207     init_hash(keys);
208
209 }
210
211 int zebra_rec_keys_rewind(zebra_rec_keys_t keys)
212 {
213     assert(keys);
214     iscz1_reset(keys->decode_handle);
215     keys->fetch_offset = 0;
216     if (keys->buf_used == 0)
217         return 0;
218     return 1;
219 }
220
221 int zebra_rec_keys_empty(zebra_rec_keys_t keys)
222 {
223     if (keys->buf_used == 0)
224         return 1;
225     return 0;
226 }
227
228 int zebra_rec_keys_read(zebra_rec_keys_t keys,
229                         const char **str, size_t *slen,
230                         struct it_key *key)
231 {
232     assert(keys);
233     if (keys->fetch_offset == keys->buf_used)
234         return 0;
235     else
236     {
237         const char *src = keys->buf + keys->fetch_offset;
238         char *dst = (char*) key;
239         
240         assert (keys->fetch_offset < keys->buf_used);
241
242         /* store the destination key */
243         iscz1_decode(keys->decode_handle, &dst, &src);
244         
245         /* store pointer to string and length of it */
246         *str = src;
247         *slen = strlen(src);
248         src += *slen + 1;
249         
250         keys->fetch_offset = src - keys->buf;
251     }
252     return 1;
253 }
254 /*
255  * Local variables:
256  * c-basic-offset: 4
257  * indent-tabs-mode: nil
258  * End:
259  * vim: shiftwidth=4 tabstop=8 expandtab
260  */
261