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