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