Added coder to reset.
[idzebra-moved-to-github.git] / index / kcompare.c
1 /*
2  * Copyright (C) 1994-1999, Index Data
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: kcompare.c,v $
7  * Revision 1.29  1999-06-30 09:08:23  adam
8  * Added coder to reset.
9  *
10  * Revision 1.28  1999/05/26 07:49:13  adam
11  * C++ compilation.
12  *
13  * Revision 1.27  1999/05/12 13:08:06  adam
14  * First version of ISAMS.
15  *
16  * Revision 1.26  1999/02/02 14:50:54  adam
17  * Updated WIN32 code specific sections. Changed header.
18  *
19  * Revision 1.25  1998/06/08 15:26:06  adam
20  * Minor changes.
21  *
22  * Revision 1.24  1998/06/08 14:43:12  adam
23  * Added suport for EXPLAIN Proxy servers - added settings databasePath
24  * and explainDatabase to facilitate this. Increased maximum number
25  * of databases and attributes in one register.
26  *
27  * Revision 1.23  1998/03/05 08:45:12  adam
28  * New result set model and modular ranking system. Moved towards
29  * descent server API. System information stored as "SGML" records.
30  *
31  * Revision 1.22  1997/09/22 12:39:06  adam
32  * Added get_pos method for the ranked result sets.
33  *
34  * Revision 1.21  1997/09/17 12:19:13  adam
35  * Zebra version corresponds to YAZ version 1.4.
36  * Changed Zebra server so that it doesn't depend on global common_resource.
37  *
38  * Revision 1.20  1996/12/23 15:30:44  adam
39  * Work on truncation.
40  * Bug fix: result sets weren't deleted after server shut down.
41  *
42  * Revision 1.19  1996/12/11 12:08:00  adam
43  * Added better compression.
44  *
45  * Revision 1.18  1996/10/29 14:09:44  adam
46  * Use of cisam system - enabled if setting isamc is 1.
47  *
48  * Revision 1.17  1996/06/04 10:18:58  adam
49  * Minor changes - removed include of ctype.h.
50  *
51  * Revision 1.16  1996/05/13  14:23:05  adam
52  * Work on compaction of set/use bytes in dictionary.
53  *
54  * Revision 1.15  1995/11/20  16:59:46  adam
55  * New update method: the 'old' keys are saved for each records.
56  *
57  * Revision 1.14  1995/10/30  15:08:08  adam
58  * Bug fixes.
59  *
60  * Revision 1.13  1995/10/27  14:00:11  adam
61  * Implemented detection of database availability.
62  *
63  * Revision 1.12  1995/10/17  18:02:08  adam
64  * New feature: databases. Implemented as prefix to words in dictionary.
65  *
66  * Revision 1.11  1995/10/06  16:33:37  adam
67  * Use attribute mappings.
68  *
69  * Revision 1.10  1995/09/29  14:01:41  adam
70  * Bug fixes.
71  *
72  * Revision 1.9  1995/09/28  12:10:32  adam
73  * Bug fixes. Field prefix used in queries.
74  *
75  * Revision 1.8  1995/09/28  09:19:42  adam
76  * xfree/xmalloc used everywhere.
77  * Extract/retrieve method seems to work for text records.
78  *
79  * Revision 1.7  1995/09/27  12:22:28  adam
80  * More work on extract in record control.
81  * Field name is not in isam keys but in prefix in dictionary words.
82  *
83  * Revision 1.6  1995/09/14  07:48:23  adam
84  * Record control management.
85  *
86  * Revision 1.5  1995/09/11  13:09:34  adam
87  * More work on relevance feedback.
88  *
89  * Revision 1.4  1995/09/08  14:52:27  adam
90  * Minor changes. Dictionary is lower case now.
91  *
92  * Revision 1.3  1995/09/07  13:58:36  adam
93  * New parameter: result-set file descriptor (RSFD) to support multiple
94  * positions within the same result-set.
95  * Boolean operators: and, or, not implemented.
96  * Result-set references.
97  *
98  * Revision 1.2  1995/09/06  16:11:17  adam
99  * Option: only one word key per file.
100  *
101  * Revision 1.1  1995/09/04  09:10:36  adam
102  * More work on index add/del/update.
103  * Merge sort implemented.
104  * Initial work on z39 server.
105  *
106  */
107
108 #include <stdlib.h>
109 #include <string.h>
110 #include <stdio.h>
111 #include <assert.h>
112
113 #include "index.h"
114
115 void key_logdump (int logmask, const void *p)
116 {
117     struct it_key key;
118
119     memcpy (&key, p, sizeof(key));
120     logf (logmask, "%7d s=%-4d", key.sysno, key.seqno);
121 }
122
123 int key_compare_it (const void *p1, const void *p2)
124 {
125     if (((struct it_key *) p1)->sysno != ((struct it_key *) p2)->sysno)
126     {
127         if (((struct it_key *) p1)->sysno > ((struct it_key *) p2)->sysno)
128             return 2;
129         else
130             return -2;
131     }
132     if (((struct it_key *) p1)->seqno != ((struct it_key *) p2)->seqno)
133     {
134         if (((struct it_key *) p1)->seqno > ((struct it_key *) p2)->seqno)
135             return 1;
136         else
137             return -1;
138     }
139     return 0;
140 }
141
142 int key_compare (const void *p1, const void *p2)
143 {
144     struct it_key i1, i2;
145     memcpy (&i1, p1, sizeof(i1));
146     memcpy (&i2, p2, sizeof(i2));
147     if (i1.sysno != i2.sysno)
148     {
149         if (i1.sysno > i2.sysno)
150             return 2;
151         else
152             return -2;
153     }
154     if (i1.seqno != i2.seqno)
155     {
156         if (i1.seqno > i2.seqno)
157             return 1;
158         else
159             return -1;
160     }
161     return 0;
162 }
163
164 int key_qsort_compare (const void *p1, const void *p2)
165 {
166     int r;
167     size_t l;
168     char *cp1 = *(char **) p1;
169     char *cp2 = *(char **) p2;
170  
171     if ((r = strcmp (cp1, cp2)))
172         return r;
173     l = strlen(cp1)+1;
174     if ((r = key_compare (cp1+l+1, cp2+l+1)))
175         return r;
176     return cp1[l] - cp2[l];
177 }
178
179 int key_get_pos (const void *p)
180 {
181     struct it_key key;
182     memcpy (&key, p, sizeof(key));
183     return key.seqno;
184 }
185
186 struct iscz1_code_info {
187     struct it_key key;
188 };
189
190 static void *iscz1_code_start (int mode)
191 {
192     struct iscz1_code_info *p = (struct iscz1_code_info *)
193         xmalloc (sizeof(*p));
194     p->key.sysno = 0;
195     p->key.seqno = 0;
196     return p;
197 }
198
199 static void iscz1_code_reset (void *vp)
200 {
201     struct iscz1_code_info *p = (struct iscz1_code_info *) vp;
202     p->key.sysno = 0;
203     p->key.seqno = 0;
204 }
205
206 static void iscz1_code_stop (int mode, void *p)
207 {
208     xfree (p);
209 }
210
211 void iscz1_encode_int (unsigned d, char **dst)
212 {
213     unsigned char *bp = (unsigned char*) *dst;
214
215     if (d <= 63)
216         *bp++ = d;
217     else if (d <= 16383)
218     {
219         *bp++ = 64 + (d>>8);
220        *bp++ = d & 255;
221     }
222     else if (d <= 4194303)
223     {
224         *bp++ = 128 + (d>>16);
225         *bp++ = (d>>8) & 255;
226         *bp++ = d & 255;
227     }
228     else
229     {
230         *bp++ = 192 + (d>>24);
231         *bp++ = (d>>16) & 255;
232         *bp++ = (d>>8) & 255;
233         *bp++ = d & 255;
234     }
235     *dst = (char *) bp;
236 }
237
238 int iscz1_decode_int (unsigned char **src)
239 {
240     unsigned c = *(*src)++;
241     switch (c & 192)
242     {
243     case 0:
244         return c;
245     case 64:
246         return ((c & 63) << 8) + *(*src)++;
247     case 128:
248         c = ((c & 63) << 8) + *(*src)++;
249         c = (c << 8) + *(*src)++;
250         return c;
251     }
252     c = ((c & 63) << 8) + *(*src)++;
253     c = (c << 8) + *(*src)++;
254     c = (c << 8) + *(*src)++;
255     return c;
256 }
257
258 static void iscz1_code_item (int mode, void *vp, char **dst, char **src)
259 {
260     struct iscz1_code_info *p = (struct iscz1_code_info *) vp;
261     struct it_key tkey;
262     int d;
263
264     if (mode == ISAMC_ENCODE)
265     {
266         memcpy (&tkey, *src, sizeof(struct it_key));
267         d = tkey.sysno - p->key.sysno;
268         if (d)
269         {
270             iscz1_encode_int (2*tkey.seqno + 1, dst);
271             iscz1_encode_int (d, dst);
272             p->key.sysno += d;
273             p->key.seqno = tkey.seqno;
274         }
275         else
276         {
277             iscz1_encode_int (2*(tkey.seqno - p->key.seqno), dst);
278             p->key.seqno = tkey.seqno;
279         }
280         (*src) += sizeof(struct it_key);
281     }
282     else
283     {
284         d = iscz1_decode_int ((unsigned char **) src);
285         if (d & 1)
286         {
287             p->key.seqno = d>>1;
288             p->key.sysno += iscz1_decode_int ((unsigned char **) src);
289         }
290         else
291             p->key.seqno += d>>1;
292         memcpy (*dst, &p->key, sizeof(struct it_key));
293         (*dst) += sizeof(struct it_key);
294     }
295 }
296
297 ISAMC_M key_isamc_m (Res res)
298 {
299     static ISAMC_M me = NULL;
300
301     if (me)
302         return me;
303
304     me = isc_getmethod ();
305
306     me->compare_item = key_compare;
307
308     me->code_start = iscz1_code_start;
309     me->code_item = iscz1_code_item;
310     me->code_stop = iscz1_code_stop;
311     me->code_reset = iscz1_code_reset;
312
313     me->debug = atoi(res_get_def (res, "isamcDebug", "0"));
314
315     return me;
316 }
317
318 ISAMS_M key_isams_m (Res res)
319 {
320     static ISAMS_M me = NULL;
321
322     if (me)
323         return me;
324
325     me = isams_getmethod ();
326
327     me->compare_item = key_compare;
328
329     me->code_start = iscz1_code_start;
330     me->code_item = iscz1_code_item;
331     me->code_stop = iscz1_code_stop;
332
333     me->debug = atoi(res_get_def (res, "isamsDebug", "0"));
334
335     return me;
336 }
337
338
339 int key_SU_code (int ch, char *out)
340 {
341     int i;
342     for (i = 0; ch; i++)
343     {
344         if (ch > 63)
345             out[i] = 128 + (ch & 63);
346         else
347             out[i] = 1 + ch;
348         ch = ch >> 6;
349     }
350     return i;
351 }