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