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