649ec1cdc74658919befecd85d3ed2cc59fafc72
[idzebra-moved-to-github.git] / index / reckeys.c
1 /* $Id: reckeys.c,v 1.6 2006-06-07 10:14:41 adam Exp $
2    Copyright (C) 1995-2006
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                                                     const struct it_key *key)
58 {
59     unsigned h = 0;
60     size_t i;
61     int j;
62     for (i = 0; i<len; i++)
63         h = h * 65509 + buf[i];
64     for (j = 0; j<key->len; j++)
65         h = h * 65509 + CAST_ZINT_TO_INT(key->mem[j]);
66     return &p->entries[h % (unsigned) p->hash_size];
67 }
68
69 static void init_hash(zebra_rec_keys_t p)
70 {
71     p->entries = 0;
72     nmem_reset(p->nmem);
73     if (p->hash_size)
74     {
75         size_t i;
76         p->entries = nmem_malloc(p->nmem, p->hash_size * sizeof(*p->entries));
77         for (i = 0; i<p->hash_size; i++)
78             p->entries[i] = 0;
79     }
80 }
81
82 zebra_rec_keys_t zebra_rec_keys_open()
83 {
84     zebra_rec_keys_t p = xmalloc(sizeof(*p));
85     p->buf_used = 0;
86     p->buf_max = 0;
87     p->fetch_offset = 0;
88     p->buf = 0;
89     p->owner_of_buffer = 1;
90     p->encode_handle = iscz1_start();
91     p->decode_handle = iscz1_start(); 
92
93     p->nmem = nmem_create();
94     p->hash_size = 1023;
95     p->entries = 0;
96
97     init_hash(p);
98
99     return p;
100 }
101
102 void zebra_rec_keys_set_buf(zebra_rec_keys_t p, char *buf, size_t sz,
103                             int copy_buf)
104 {
105     if (p->owner_of_buffer)
106         xfree(p->buf);
107     p->buf_used = sz;
108     p->buf_max = sz;
109     if (!copy_buf)
110     {
111         p->buf = buf;
112     }
113     else
114     {
115         if (!sz)
116             p->buf = 0;
117         else
118         {
119             p->buf = xmalloc(sz);
120             memcpy(p->buf, buf, sz);
121         }
122     }
123     p->owner_of_buffer = copy_buf;
124 }
125         
126 void zebra_rec_keys_get_buf(zebra_rec_keys_t p, char **buf, size_t *sz)
127 {
128     *buf = p->buf;
129     *sz = p->buf_used;
130
131     p->buf = 0;
132     p->buf_max = 0;
133     p->buf_used = 0;
134 }
135
136 void zebra_rec_keys_close(zebra_rec_keys_t p)
137 {
138     if (!p)
139         return;
140     
141     if (p->owner_of_buffer)
142         xfree(p->buf);
143     if (p->encode_handle)
144         iscz1_stop(p->encode_handle);
145     if (p->decode_handle)
146         iscz1_stop(p->decode_handle);
147     nmem_destroy(p->nmem);
148     xfree(p);
149 }
150
151 int zebra_rec_keys_add_hash(zebra_rec_keys_t keys, 
152                             const char *str, size_t slen,
153                             const struct it_key *key)
154 {
155     struct zebra_rec_key_entry **kep = zebra_rec_keys_mk_hash(keys,
156                                                               str, slen, key);
157     while (*kep)
158     {
159         struct zebra_rec_key_entry *e = *kep;
160         if (slen == e->len && !memcmp(str, e->buf, slen) &&
161             !key_compare(key, &e->key))
162         {
163             return 0;
164         }
165         kep = &(*kep)->next;
166     }
167     *kep = nmem_malloc(keys->nmem, sizeof(**kep));
168     (*kep)->next = 0;
169     (*kep)->len = slen;
170     memcpy(&(*kep)->key, key, sizeof(*key));
171     (*kep)->buf = nmem_malloc(keys->nmem, slen);
172     memcpy((*kep)->buf, str, slen);
173     return 1;
174 }
175
176 void zebra_rec_keys_write(zebra_rec_keys_t keys, 
177                           const char *str, size_t slen,
178                           const struct it_key *key)
179 {
180     char *dst;
181     const char *src = (char*) key;
182     
183     assert(keys->owner_of_buffer);
184
185     if (!zebra_rec_keys_add_hash(keys, str, slen, key))
186         return;  /* key already there . Omit it */
187     if (keys->buf_used+1024 > keys->buf_max)
188     {
189         char *b = (char *) xmalloc (keys->buf_max += 128000);
190         if (keys->buf_used > 0)
191             memcpy (b, keys->buf, keys->buf_used);
192         xfree (keys->buf);
193         keys->buf = b;
194     }
195     dst = keys->buf + keys->buf_used;
196
197     iscz1_encode(keys->encode_handle, &dst, &src);
198
199     memcpy (dst, str, slen);
200     dst += slen;
201     *dst++ = '\0';
202     keys->buf_used = dst - keys->buf;
203 }
204
205 void zebra_rec_keys_reset(zebra_rec_keys_t keys)
206 {
207     assert(keys);
208     keys->buf_used = 0;
209     
210     iscz1_reset(keys->encode_handle);
211
212     init_hash(keys);
213
214 }
215
216 int zebra_rec_keys_rewind(zebra_rec_keys_t keys)
217 {
218     assert(keys);
219     iscz1_reset(keys->decode_handle);
220     keys->fetch_offset = 0;
221     if (keys->buf_used == 0)
222         return 0;
223     return 1;
224 }
225
226 int zebra_rec_keys_empty(zebra_rec_keys_t keys)
227 {
228     if (keys->buf_used == 0)
229         return 1;
230     return 0;
231 }
232
233 int zebra_rec_keys_read(zebra_rec_keys_t keys,
234                         const char **str, size_t *slen,
235                         struct it_key *key)
236 {
237     assert(keys);
238     if (keys->fetch_offset == keys->buf_used)
239         return 0;
240     else
241     {
242         const char *src = keys->buf + keys->fetch_offset;
243         char *dst = (char*) key;
244         
245         assert (keys->fetch_offset < keys->buf_used);
246
247         /* store the destination key */
248         iscz1_decode(keys->decode_handle, &dst, &src);
249         
250         /* store pointer to string and length of it */
251         *str = src;
252         *slen = strlen(src);
253         src += *slen + 1;
254         
255         keys->fetch_offset = src - keys->buf;
256     }
257     return 1;
258 }
259 /*
260  * Local variables:
261  * c-basic-offset: 4
262  * indent-tabs-mode: nil
263  * End:
264  * vim: shiftwidth=4 tabstop=8 expandtab
265  */
266