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