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