WIN32 compile (again)
[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_encode (int ch, char *out)
257 {
258     int i;
259     for (i = 0; ch; i++)
260     {
261         if (ch >= 64)
262             out[i] = 65 + (ch & 63);
263         else
264             out[i] = 1 + ch;
265         ch = ch >> 6;
266     }
267     return i;
268     /* in   out
269        0     1
270        1     2
271        63    64
272        64    65, 2
273        65    66, 2
274        127   128, 2
275        128   65, 3
276        191   128, 3
277        192   65, 4
278     */
279 }
280
281 int key_SU_decode (int *ch, const unsigned char *out)
282 {
283     int len = 1;
284     int fact = 1;
285     *ch = 0;
286     for (len = 1; *out >= 65; len++, out++)
287     {
288         *ch += (*out - 65) * fact;
289         fact <<= 6;
290     }
291     *ch += (*out - 1) * fact;
292     return len;
293 }
294
295 /* 
296  * $Log: kcompare.c,v $
297  * Revision 1.37  2001-11-19 23:08:30  adam
298  * Added const qualifier for name parameter of key_SU_decode.
299  *
300  * Revision 1.36  2001/10/15 19:53:43  adam
301  * POSIX thread updates. First work on term sets.
302  *
303  * Revision 1.35  1999/11/30 13:48:03  adam
304  * Improved installation. Updated for inclusion of YAZ header files.
305  *
306  * Revision 1.34  1999/07/14 13:21:34  heikki
307  * Added isam-d files. Compiles (almost) clean. Doesn't work at all
308  *
309  * Revision 1.33  1999/07/14 10:59:26  adam
310  * Changed functions isc_getmethod, isams_getmethod.
311  * Improved fatal error handling (such as missing EXPLAIN schema).
312  *
313  * Revision 1.32  1999/07/13 13:21:15  heikki
314  * Managing negative deltas
315  *
316  * Revision 1.31  1999/07/06 09:37:04  heikki
317  * Working on isamh - not ready yet.
318  *
319  * Revision 1.30  1999/06/30 15:07:23  heikki
320  * Adding isamh stuff
321  *
322  * Revision 1.29  1999/06/30 09:08:23  adam
323  * Added coder to reset.
324  *
325  * Revision 1.28  1999/05/26 07:49:13  adam
326  * C++ compilation.
327  *
328  * Revision 1.27  1999/05/12 13:08:06  adam
329  * First version of ISAMS.
330  *
331  * Revision 1.26  1999/02/02 14:50:54  adam
332  * Updated WIN32 code specific sections. Changed header.
333  *
334  * Revision 1.25  1998/06/08 15:26:06  adam
335  * Minor changes.
336  *
337  * Revision 1.24  1998/06/08 14:43:12  adam
338  * Added suport for EXPLAIN Proxy servers - added settings databasePath
339  * and explainDatabase to facilitate this. Increased maximum number
340  * of databases and attributes in one register.
341  *
342  * Revision 1.23  1998/03/05 08:45:12  adam
343  * New result set model and modular ranking system. Moved towards
344  * descent server API. System information stored as "SGML" records.
345  *
346  * Revision 1.22  1997/09/22 12:39:06  adam
347  * Added get_pos method for the ranked result sets.
348  *
349  * Revision 1.21  1997/09/17 12:19:13  adam
350  * Zebra version corresponds to YAZ version 1.4.
351  * Changed Zebra server so that it doesn't depend on global common_resource.
352  *
353  * Revision 1.20  1996/12/23 15:30:44  adam
354  * Work on truncation.
355  * Bug fix: result sets weren't deleted after server shut down.
356  *
357  * Revision 1.19  1996/12/11 12:08:00  adam
358  * Added better compression.
359  *
360  * Revision 1.18  1996/10/29 14:09:44  adam
361  * Use of cisam system - enabled if setting isamc is 1.
362  *
363  * Revision 1.17  1996/06/04 10:18:58  adam
364  * Minor changes - removed include of ctype.h.
365  *
366  * Revision 1.16  1996/05/13  14:23:05  adam
367  * Work on compaction of set/use bytes in dictionary.
368  *
369  * Revision 1.15  1995/11/20  16:59:46  adam
370  * New update method: the 'old' keys are saved for each records.
371  *
372  * Revision 1.14  1995/10/30  15:08:08  adam
373  * Bug fixes.
374  *
375  * Revision 1.13  1995/10/27  14:00:11  adam
376  * Implemented detection of database availability.
377  *
378  * Revision 1.12  1995/10/17  18:02:08  adam
379  * New feature: databases. Implemented as prefix to words in dictionary.
380  *
381  * Revision 1.11  1995/10/06  16:33:37  adam
382  * Use attribute mappings.
383  *
384  * Revision 1.10  1995/09/29  14:01:41  adam
385  * Bug fixes.
386  *
387  * Revision 1.9  1995/09/28  12:10:32  adam
388  * Bug fixes. Field prefix used in queries.
389  *
390  * Revision 1.8  1995/09/28  09:19:42  adam
391  * xfree/xmalloc used everywhere.
392  * Extract/retrieve method seems to work for text records.
393  *
394  * Revision 1.7  1995/09/27  12:22:28  adam
395  * More work on extract in record control.
396  * Field name is not in isam keys but in prefix in dictionary words.
397  *
398  * Revision 1.6  1995/09/14  07:48:23  adam
399  * Record control management.
400  *
401  * Revision 1.5  1995/09/11  13:09:34  adam
402  * More work on relevance feedback.
403  *
404  * Revision 1.4  1995/09/08  14:52:27  adam
405  * Minor changes. Dictionary is lower case now.
406  *
407  * Revision 1.3  1995/09/07  13:58:36  adam
408  * New parameter: result-set file descriptor (RSFD) to support multiple
409  * positions within the same result-set.
410  * Boolean operators: and, or, not implemented.
411  * Result-set references.
412  *
413  * Revision 1.2  1995/09/06  16:11:17  adam
414  * Option: only one word key per file.
415  *
416  * Revision 1.1  1995/09/04  09:10:36  adam
417  * More work on index add/del/update.
418  * Merge sort implemented.
419  * Initial work on z39 server.
420  *
421  */