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