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