Implemented snot operation.
[idzebra-moved-to-github.git] / rset / rssbool.c
1 /*
2  * Copyright (C) 1994-1996, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: rssbool.c,v $
7  * Revision 1.2  1996-05-15 18:35:17  adam
8  * Implemented snot operation.
9  *
10  * Revision 1.1  1995/12/11  09:15:27  adam
11  * New set types: sand/sor/snot - ranked versions of and/or/not in
12  * ranked/semi-ranked result sets.
13  * Note: the snot not finished yet.
14  * New rset member: flag.
15  * Bug fix: r_delete in rsrel.c did free bad memory block.
16  *
17  */
18
19 #include <stdio.h>
20 #include <assert.h>
21
22 #include <rsbool.h>
23 #include <alexutil.h>
24
25 static void *r_create_and(const struct rset_control *sel, void *parms,
26                          int *flags);
27 static void *r_create_or(const struct rset_control *sel, void *parms,
28                          int *flags);
29 static void *r_create_not(const struct rset_control *sel, void *parms,
30                          int *flags);
31 static RSFD r_open (RSET ct, int flag);
32 static void r_close (RSFD rfd);
33 static void r_delete (RSET ct);
34 static void r_rewind (RSFD rfd);
35 static int r_count (RSET ct);
36 static int r_read (RSFD rfd, void *buf);
37 static int r_write (RSFD rfd, const void *buf);
38 static int r_score (RSFD rfd, int *score);
39
40 static const rset_control control_sand = 
41 {
42     "sand",
43     r_create_and,
44     r_open,
45     r_close,
46     r_delete,
47     r_rewind,
48     r_count,
49     r_read,
50     r_write,
51     r_score
52 };
53
54 static const rset_control control_sor = 
55 {
56     "sor",
57     r_create_or,
58     r_open,
59     r_close,
60     r_delete,
61     r_rewind,
62     r_count,
63     r_read,
64     r_write,
65     r_score
66 };
67
68 static const rset_control control_snot = 
69 {
70     "snot",
71     r_create_not,
72     r_open,
73     r_close,
74     r_delete,
75     r_rewind,
76     r_count,
77     r_read,
78     r_write,
79     r_score
80 };
81
82
83 const rset_control *rset_kind_sand = &control_sand;
84 const rset_control *rset_kind_sor = &control_sor;
85 const rset_control *rset_kind_snot = &control_snot;
86
87 struct rset_bool_info {
88     int key_size;
89     RSET rset_l;
90     RSET rset_r;
91     char *key_buf;
92     int *score_buf;
93     int key_no;
94     int key_max;
95     int (*cmp)(const void *p1, const void *p2);
96     struct rset_bool_rfd *rfd_list;
97 };
98
99 struct rset_bool_rfd {
100     struct rset_bool_rfd *next;
101     struct rset_bool_info *info;
102     int position;
103     int last_pos;
104     int open_flag;
105 };    
106
107 static void *r_create_common (const struct rset_control *sel, 
108                               rset_bool_parms *bool_parms, int *flags);
109             
110 static void key_add (struct rset_bool_info *info,
111                      char *buf, int score)
112 {
113     if (info->key_no == info->key_max)
114         return;
115     memcpy (info->key_buf + info->key_size * info->key_no,
116             buf, info->key_size);
117     info->score_buf[info->key_no] = score;
118     (info->key_no)++;
119 }
120
121 static void *r_create_and (const struct rset_control *sel, void *parms,
122                            int *flags)
123 {
124     int more_l, more_r;
125     RSFD fd_l, fd_r;
126     char *buf_l, *buf_r;
127
128     struct rset_bool_info *info;
129     info = r_create_common (sel, parms, flags);
130
131     buf_l = xmalloc (info->key_size);
132     buf_r = xmalloc (info->key_size);
133     fd_l = rset_open (info->rset_l, RSETF_SORT_SYSNO|RSETF_READ);
134     fd_r = rset_open (info->rset_r, RSETF_SORT_SYSNO|RSETF_READ);
135
136     more_l = rset_read(info->rset_l, fd_l, buf_l);
137     more_r = rset_read(info->rset_r, fd_r, buf_r);
138
139     while (more_l || more_r)
140     {
141         int cmp;
142         int score, score_l, score_r;
143
144         if (more_l && more_r)
145             cmp = (*info->cmp)(buf_l, buf_r);
146         else if (more_r)
147             cmp = 2;
148         else 
149             cmp = -2;
150
151         if (cmp >= -1 && cmp <= 1)
152         {
153             rset_score (info->rset_l, fd_l, &score_l);
154             rset_score (info->rset_r, fd_r, &score_r);
155             if (score_l == -1)
156                 score = score_r;
157             else if (score_r == -1)
158                 score = score_l;
159             else
160                 score = score_l > score_r ? score_r : score_l;
161             key_add (info, buf_l, score);
162     
163             more_l = rset_read (info->rset_l, fd_l, buf_l);
164             more_r = rset_read (info->rset_r, fd_r, buf_r);
165         }
166         else if (cmp > 1)
167         {
168             rset_score (info->rset_r, fd_r, &score_r);
169             if (score_r != -1)
170                 key_add (info, buf_r, 1);
171             more_r = rset_read (info->rset_r, fd_r, buf_r);
172         }
173         else
174         {
175             rset_score (info->rset_l, fd_l, &score_l);
176             if (score_l != -1)
177                 key_add (info, buf_l, 1);
178             more_l = rset_read (info->rset_l, fd_l, buf_l);
179         }
180     }
181     rset_close (info->rset_l, fd_l);
182     rset_close (info->rset_r, fd_r);
183     rset_delete (info->rset_l);
184     rset_delete (info->rset_r);
185     xfree (buf_l);
186     xfree (buf_r);
187     return info;
188 }
189
190 static void *r_create_or (const struct rset_control *sel, void *parms,
191                           int *flags)
192 {
193     int more_l, more_r;
194     RSFD fd_l, fd_r;
195     char *buf_l, *buf_r;
196
197     struct rset_bool_info *info;
198     info = r_create_common (sel, parms, flags);
199
200     buf_l = xmalloc (info->key_size);
201     buf_r = xmalloc (info->key_size);
202     fd_l = rset_open (info->rset_l, RSETF_SORT_SYSNO|RSETF_READ);
203     fd_r = rset_open (info->rset_r, RSETF_SORT_SYSNO|RSETF_READ);
204
205     more_l = rset_read(info->rset_l, fd_l, buf_l);
206     more_r = rset_read(info->rset_r, fd_r, buf_r);
207
208     while (more_l || more_r)
209     {
210         int cmp;
211         int score, score_l, score_r;
212
213         if (more_l && more_r)
214             cmp = (*info->cmp)(buf_l, buf_r);
215         else if (more_r)
216             cmp = 2;
217         else 
218             cmp = -2;
219
220         if (cmp >= -1 && cmp <= 1)
221         {
222             rset_score (info->rset_l, fd_l, &score_l);
223             rset_score (info->rset_r, fd_r, &score_r);
224             if (score_l == -1)
225                 score = score_r;
226             else if (score_r == -1)
227                 score = score_l;
228             else
229                 score = score_r > score_l ? score_r : score_l;
230             key_add (info, buf_l, score);
231     
232             more_l = rset_read (info->rset_l, fd_l, buf_l);
233             more_r = rset_read (info->rset_r, fd_r, buf_r);
234         }
235         else if (cmp > 1)
236         {
237             rset_score (info->rset_r, fd_r, &score_r);
238             if (score_r != -1)
239                 key_add (info, buf_r, score_r / 2);
240             more_r = rset_read (info->rset_r, fd_r, buf_r);
241         }
242         else
243         {
244             rset_score (info->rset_l, fd_l, &score_l);
245             if (score_l != -1)
246                 key_add (info, buf_l, score_l / 2);
247             more_l = rset_read (info->rset_l, fd_l, buf_l);
248         }
249     }
250     rset_close (info->rset_l, fd_l);
251     rset_close (info->rset_r, fd_r);
252     rset_delete (info->rset_l);
253     rset_delete (info->rset_r);
254     xfree (buf_l);
255     xfree (buf_r);
256     return info;
257 }
258
259 static void *r_create_not (const struct rset_control *sel, void *parms,
260                            int *flags)
261 {
262     char *buf_l, *buf_r;
263     int more_l, more_r;
264     RSFD fd_l, fd_r;
265
266     struct rset_bool_info *info;
267     info = r_create_common (sel, parms, flags);
268
269     buf_l = xmalloc (info->key_size);
270     buf_r = xmalloc (info->key_size);
271
272     fd_l = rset_open (info->rset_l, RSETF_SORT_SYSNO|RSETF_READ);
273     fd_r = rset_open (info->rset_r, RSETF_SORT_SYSNO|RSETF_READ);
274
275     more_l = rset_read(info->rset_l, fd_l, buf_l);
276     more_r = rset_read(info->rset_r, fd_r, buf_r);
277
278     while (more_l || more_r)
279     {
280         int cmp;
281         int score;
282
283         if (more_l && more_r)
284             cmp = (*info->cmp)(buf_l, buf_r);
285         else if (more_r)
286             cmp = 2;
287         else 
288             cmp = -2;
289
290         if (cmp >= -1 && cmp <= 1)
291             more_l = rset_read (info->rset_l, fd_l, buf_l);
292         else if (cmp > 1)
293         {
294             more_r = rset_read (info->rset_r, fd_r, buf_r);
295         }
296         else
297         {
298             rset_score (info->rset_l, fd_l, &score);
299             key_add (info, buf_l, score == -1 ? 1 : score);
300             more_l = rset_read (info->rset_l, fd_l, buf_l);
301         }
302     }
303     rset_close (info->rset_l, fd_l);
304     rset_close (info->rset_r, fd_r);
305
306     rset_delete (info->rset_l);
307     rset_delete (info->rset_r);
308     xfree (buf_l);
309     xfree (buf_r);
310     return info;
311 }
312
313 static void *r_create_common (const struct rset_control *sel, 
314                               rset_bool_parms *bool_parms, int *flags)
315 {
316     struct rset_bool_info *info;
317
318     info = xmalloc (sizeof(*info));
319     info->key_size = bool_parms->key_size;
320     info->rset_l = bool_parms->rset_l;
321     info->rset_r = bool_parms->rset_r;
322     info->cmp = bool_parms->cmp;
323     info->rfd_list = NULL;
324     
325     if (rset_is_ranked(info->rset_l) || rset_is_ranked(info->rset_r))
326         *flags |= RSET_FLAG_RANKED;
327
328     info->key_max = rset_count(bool_parms->rset_l)
329                    +rset_count(bool_parms->rset_r);
330     if (!info->key_max)
331         info->key_max = 1;
332     if (info->key_max > 1000)
333         info->key_max = 1000;
334     info->key_buf = xmalloc (info->key_size * info->key_max);
335     info->score_buf = xmalloc (info->key_max * sizeof(*info->score_buf));
336     info->key_no = 0;
337
338     return info;
339 }
340
341 static RSFD r_open (RSET ct, int flag)
342 {
343     struct rset_bool_info *info = ct->buf;
344     struct rset_bool_rfd *rfd;
345
346     if (flag & RSETF_WRITE)
347     {
348         logf (LOG_FATAL, "sbool set type is read-only");
349         return NULL;
350     }
351     rfd = xmalloc (sizeof(*rfd));
352     rfd->next = info->rfd_list;
353     info->rfd_list = rfd;
354     rfd->info = info;
355
356     rfd->position = 0;
357     rfd->last_pos = 0;
358     rfd->open_flag = flag;
359
360     return rfd;
361 }
362
363 static void r_close (RSFD rfd)
364 {
365     struct rset_bool_info *info = ((struct rset_bool_rfd*)rfd)->info;
366     struct rset_bool_rfd **rfdp;
367     
368     for (rfdp = &info->rfd_list; *rfdp; rfdp = &(*rfdp)->next)
369         if (*rfdp == rfd)
370         {
371             *rfdp = (*rfdp)->next;
372             xfree (rfd);
373             return;
374         }
375     logf (LOG_FATAL, "r_close but no rfd match!");
376     assert (0);
377 }
378
379 static void r_delete (RSET ct)
380 {
381     struct rset_bool_info *info = ct->buf;
382
383     assert (info->rfd_list == NULL);
384     xfree (info->score_buf);
385     xfree (info->key_buf);
386     xfree (info);
387 }
388
389 static void r_rewind (RSFD rfd)
390 {
391     struct rset_bool_rfd *p = rfd;
392
393     logf (LOG_DEBUG, "rsbool_rewind");
394     p->position = p->last_pos = 0;
395 }
396
397 static int r_count (RSET ct)
398 {
399     struct rset_bool_info *info = ct->buf;
400
401     return info->key_no;
402 }
403
404 static int r_read (RSFD rfd, void *buf)
405 {
406     struct rset_bool_rfd *p = rfd;
407     struct rset_bool_info *info = p->info;
408
409     if (p->position >= info->key_no)
410         return 0;
411     p->last_pos = (p->position)++;
412     memcpy (buf, info->key_buf + info->key_size * p->last_pos,
413             info->key_size);
414     return 1;
415 }
416
417 static int r_write (RSFD rfd, const void *buf)
418 {
419     logf (LOG_FATAL, "sbool set type is read-only");
420     return -1;
421 }
422
423 static int r_score (RSFD rfd, int *score)
424 {
425     struct rset_bool_rfd *p = rfd;
426     struct rset_bool_info *info = p->info;
427
428     *score = info->score_buf[p->last_pos];
429     return 1;
430 }
431