New method result set method rs_hits that returns the number of
[idzebra-moved-to-github.git] / rset / rsbool.c
1 /*
2  * Copyright (C) 1994-1995, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: rsbool.c,v $
7  * Revision 1.13  1997-12-18 10:54:24  adam
8  * New method result set method rs_hits that returns the number of
9  * hits in result-set (if known). The ranked result set returns real
10  * number of hits but only when not combined with other operands.
11  *
12  * Revision 1.12  1997/10/31 12:37:01  adam
13  * Code calls xfree() instead of free().
14  *
15  * Revision 1.11  1997/09/09 13:38:15  adam
16  * Partial port to WIN95/NT.
17  *
18  * Revision 1.10  1996/10/29 13:55:20  adam
19  * Include of zebrautl.h instead of alexutil.h.
20  *
21  * Revision 1.9  1995/12/11 09:15:22  adam
22  * New set types: sand/sor/snot - ranked versions of and/or/not in
23  * ranked/semi-ranked result sets.
24  * Note: the snot not finished yet.
25  * New rset member: flag.
26  * Bug fix: r_delete in rsrel.c did free bad memory block.
27  *
28  * Revision 1.8  1995/10/12  12:41:55  adam
29  * Private info (buf) moved from struct rset_control to struct rset.
30  * Bug fixes in relevance.
31  *
32  * Revision 1.7  1995/10/10  14:00:03  adam
33  * Function rset_open changed its wflag parameter to general flags.
34  *
35  * Revision 1.6  1995/10/06  14:38:05  adam
36  * New result set method: r_score.
37  * Local no (sysno) and score is transferred to retrieveCtrl.
38  *
39  * Revision 1.5  1995/09/08  14:52:41  adam
40  * Work on relevance feedback.
41  *
42  * Revision 1.4  1995/09/08  08:54:04  adam
43  * More efficient and operation.
44  *
45  * Revision 1.3  1995/09/07  13:58:43  adam
46  * New parameter: result-set file descriptor (RSFD) to support multiple
47  * positions within the same result-set.
48  * Boolean operators: and, or, not implemented.
49  *
50  * Revision 1.2  1995/09/06  16:11:55  adam
51  * More work on boolean sets.
52  *
53  * Revision 1.1  1995/09/06  13:27:15  adam
54  * New set type: bool. Not finished yet.
55  *
56  */
57
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <assert.h>
62
63 #include <rsbool.h>
64 #include <zebrautl.h>
65
66 static void *r_create(const struct rset_control *sel, void *parms,
67                       int *flags);
68 static RSFD r_open (RSET ct, int flag);
69 static void r_close (RSFD rfd);
70 static void r_delete (RSET ct);
71 static void r_rewind (RSFD rfd);
72 static int r_count (RSET ct);
73 static int r_hits (RSET ct, void *oi);
74 static int r_read_and (RSFD rfd, void *buf);
75 static int r_read_or (RSFD rfd, void *buf);
76 static int r_read_not (RSFD rfd, void *buf);
77 static int r_write (RSFD rfd, const void *buf);
78 static int r_score (RSFD rfd, int *score);
79
80 static const rset_control control_and = 
81 {
82     "and",
83     r_create,
84     r_open,
85     r_close,
86     r_delete,
87     r_rewind,
88     r_count,
89     r_hits,
90     r_read_and,
91     r_write,
92     r_score
93 };
94
95 static const rset_control control_or = 
96 {
97     "or",
98     r_create,
99     r_open,
100     r_close,
101     r_delete,
102     r_rewind,
103     r_count,
104     r_hits,
105     r_read_or,
106     r_write,
107     r_score
108 };
109
110 static const rset_control control_not = 
111 {
112     "not",
113     r_create,
114     r_open,
115     r_close,
116     r_delete,
117     r_rewind,
118     r_count,
119     r_hits,
120     r_read_not,
121     r_write,
122     r_score
123 };
124
125
126 const rset_control *rset_kind_and = &control_and;
127 const rset_control *rset_kind_or = &control_or;
128 const rset_control *rset_kind_not = &control_not;
129
130 struct rset_bool_info {
131     int key_size;
132     RSET rset_l;
133     RSET rset_r;
134     int (*cmp)(const void *p1, const void *p2);
135     struct rset_bool_rfd *rfd_list;
136 };
137
138 struct rset_bool_rfd {
139     RSFD rfd_l;
140     RSFD rfd_r;
141     int  more_l;
142     int  more_r;
143     void *buf_l;
144     void *buf_r;
145     struct rset_bool_rfd *next;
146     struct rset_bool_info *info;
147 };    
148
149 static void *r_create (const struct rset_control *sel, void *parms,
150                        int *flags)
151 {
152     rset_bool_parms *bool_parms = parms;
153     struct rset_bool_info *info;
154
155     info = xmalloc (sizeof(*info));
156     info->key_size = bool_parms->key_size;
157     info->rset_l = bool_parms->rset_l;
158     info->rset_r = bool_parms->rset_r;
159     if (rset_is_volatile(info->rset_l) || rset_is_volatile(info->rset_r))
160         *flags |= RSET_FLAG_VOLATILE;
161     info->cmp = bool_parms->cmp;
162     info->rfd_list = NULL;
163     return info;
164 }
165
166 static RSFD r_open (RSET ct, int flag)
167 {
168     struct rset_bool_info *info = ct->buf;
169     struct rset_bool_rfd *rfd;
170
171     if (flag & RSETF_WRITE)
172     {
173         logf (LOG_FATAL, "bool set type is read-only");
174         return NULL;
175     }
176     rfd = xmalloc (sizeof(*rfd));
177     rfd->next = info->rfd_list;
178     info->rfd_list = rfd;
179     rfd->info = info;
180
181     rfd->buf_l = xmalloc (info->key_size);
182     rfd->buf_r = xmalloc (info->key_size);
183     rfd->rfd_l = rset_open (info->rset_l, RSETF_READ|RSETF_SORT_SYSNO);
184     rfd->rfd_r = rset_open (info->rset_r, RSETF_READ|RSETF_SORT_SYSNO);
185     rfd->more_l = rset_read (info->rset_l, rfd->rfd_l, rfd->buf_l);
186     rfd->more_r = rset_read (info->rset_r, rfd->rfd_r, rfd->buf_r);
187     return rfd;
188 }
189
190 static void r_close (RSFD rfd)
191 {
192     struct rset_bool_info *info = ((struct rset_bool_rfd*)rfd)->info;
193     struct rset_bool_rfd **rfdp;
194     
195     for (rfdp = &info->rfd_list; *rfdp; rfdp = &(*rfdp)->next)
196         if (*rfdp == rfd)
197         {
198             xfree ((*rfdp)->buf_l);
199             xfree ((*rfdp)->buf_r);
200             rset_close (info->rset_l, (*rfdp)->rfd_l);
201             rset_close (info->rset_r, (*rfdp)->rfd_r);
202             *rfdp = (*rfdp)->next;
203             xfree (rfd);
204             return;
205         }
206     logf (LOG_FATAL, "r_close but no rfd match!");
207     assert (0);
208 }
209
210 static void r_delete (RSET ct)
211 {
212     struct rset_bool_info *info = ct->buf;
213
214     assert (info->rfd_list == NULL);
215     rset_delete (info->rset_l);
216     rset_delete (info->rset_r);
217     xfree (info);
218 }
219
220 static void r_rewind (RSFD rfd)
221 {
222     struct rset_bool_info *info = ((struct rset_bool_rfd*)rfd)->info;
223     struct rset_bool_rfd *p = rfd;
224
225     logf (LOG_DEBUG, "rsbool_rewind");
226     rset_rewind (info->rset_l, p->rfd_l);
227     rset_rewind (info->rset_r, p->rfd_r);
228     p->more_l = rset_read (info->rset_l, p->rfd_l, p->buf_l);
229     p->more_r = rset_read (info->rset_r, p->rfd_r, p->buf_r);
230 }
231
232 static int r_count (RSET ct)
233 {
234     return 0;
235 }
236
237 static int r_hits (RSET ct, void *oi)
238 {
239     return -1;
240 }
241
242 static int r_read_and (RSFD rfd, void *buf)
243 {
244     struct rset_bool_rfd *p = rfd;
245     struct rset_bool_info *info = p->info;
246
247     while (p->more_l && p->more_r)
248     {
249         int cmp;
250
251         cmp = (*info->cmp)(p->buf_l, p->buf_r);
252         if (!cmp)
253         {
254             memcpy (buf, p->buf_l, info->key_size);
255             p->more_l = rset_read (info->rset_l, p->rfd_l, p->buf_l);
256             p->more_r = rset_read (info->rset_r, p->rfd_r, p->buf_r);
257             return 1;
258         }
259         else if (cmp == 1)
260         {
261             memcpy (buf, p->buf_r, info->key_size);
262             p->more_r = rset_read (info->rset_r, p->rfd_r, p->buf_r);
263             return 1;
264         }
265         else if (cmp == -1)
266         {
267             memcpy (buf, p->buf_l, info->key_size);
268             p->more_l = rset_read (info->rset_l, p->rfd_l, p->buf_l);
269             return 1;
270         }
271         else if (cmp > 1)
272             p->more_r = rset_read (info->rset_r, p->rfd_r, p->buf_r);
273         else
274             p->more_l = rset_read (info->rset_l, p->rfd_l, p->buf_l);
275     }
276     return 0;
277 }
278
279 static int r_read_or (RSFD rfd, void *buf)
280 {
281     struct rset_bool_rfd *p = rfd;
282     struct rset_bool_info *info = p->info;
283
284     while (p->more_l || p->more_r)
285     {
286         int cmp;
287
288         if (p->more_l && p->more_r)
289             cmp = (*info->cmp)(p->buf_l, p->buf_r);
290         else if (p->more_r)
291             cmp = 2;
292         else
293             cmp = -2;
294         if (!cmp)
295         {
296             memcpy (buf, p->buf_l, info->key_size);
297             p->more_l = rset_read (info->rset_l, p->rfd_l, p->buf_l);
298             p->more_r = rset_read (info->rset_r, p->rfd_r, p->buf_r);
299             return 1;
300         }
301         else if (cmp > 0)
302         {
303             memcpy (buf, p->buf_r, info->key_size);
304             p->more_r = rset_read (info->rset_r, p->rfd_r, p->buf_r);
305             return 1;
306         }
307         else
308         {
309             memcpy (buf, p->buf_l, info->key_size);
310             p->more_l = rset_read (info->rset_l, p->rfd_l, p->buf_l);
311             return 1;
312         }
313     }
314     return 0;
315 }
316
317 static int r_read_not (RSFD rfd, void *buf)
318 {
319     struct rset_bool_rfd *p = rfd;
320     struct rset_bool_info *info = p->info;
321
322     while (p->more_l || p->more_r)
323     {
324         int cmp;
325
326         if (p->more_l && p->more_r)
327             cmp = (*info->cmp)(p->buf_l, p->buf_r);
328         else if (p->more_r)
329             cmp = 2;
330         else
331             cmp = -2;
332         if (cmp < -1)
333         {
334             memcpy (buf, p->buf_l, info->key_size);
335             p->more_l = rset_read (info->rset_l, p->rfd_l, p->buf_l);
336             return 1;
337         }
338         else if (cmp > 1)
339             p->more_r = rset_read (info->rset_r, p->rfd_r, p->buf_r);
340         else
341         {
342             memcpy (buf, p->buf_l, info->key_size);
343             do
344             {
345                 p->more_l = rset_read (info->rset_l, p->rfd_l, p->buf_l);
346                 if (!p->more_l)
347                     break;
348                 cmp = (*info->cmp)(p->buf_l, buf);
349             } while (cmp >= -1 && cmp <= 1);
350             do
351             {
352                 p->more_r = rset_read (info->rset_r, p->rfd_r, p->buf_r);
353                 if (!p->more_r)
354                     break;
355                 cmp = (*info->cmp)(p->buf_r, buf);
356             } while (cmp >= -1 && cmp <= 1);
357         }
358     }
359     return 0;
360 }
361
362
363 static int r_write (RSFD rfd, const void *buf)
364 {
365     logf (LOG_FATAL, "bool set type is read-only");
366     return -1;
367 }
368
369 static int r_score (RSFD rfd, int *score)
370 {
371     *score = -1;
372     return -1;
373 }
374