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