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