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