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