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