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