Do not build for Ubuntu raring, quantal (obsolete)
[idzebra-moved-to-github.git] / rset / rsbool.c
1 /* This file is part of the Zebra server.
2    Copyright (C) Index Data
3
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18 */
19
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27
28 #include <idzebra/util.h>
29 #include <rset.h>
30
31 #ifndef RSET_DEBUG
32 #define RSET_DEBUG 0
33 #endif
34
35 static RSFD r_open(RSET ct, int flag);
36 static void r_close(RSFD rfd);
37 static void r_delete(RSET ct);
38 static int r_forward(RSFD rfd, void *buf, TERMID *term, const void *untilbuf);
39 static void r_pos(RSFD rfd, double *current, double *total);
40 static int r_read_not(RSFD rfd, void *buf, TERMID *term);
41 static void r_get_terms(RSET ct, TERMID *terms, int maxterms, int *curterm);
42
43 static const struct rset_control control_not =
44 {
45     "not",
46     r_delete,
47     r_get_terms,
48     r_open,
49     r_close,
50     r_forward,
51     r_pos,
52     r_read_not,
53     rset_no_write,
54 };
55
56 struct rset_private {
57     RSET rset_l;
58     RSET rset_r;
59 };
60
61 struct rfd_private {
62     zint hits;
63     RSFD rfd_l;
64     RSFD rfd_r;
65     int  more_l;
66     int  more_r;
67     void *buf_l;
68     void *buf_r;
69     TERMID term_l;
70     TERMID term_r;
71     int tail;
72 };
73
74 static RSET rsbool_create_base(const struct rset_control *ctrl,
75                                NMEM nmem,
76                                struct rset_key_control *kcontrol,
77                                int scope, RSET rset_l, RSET rset_r)
78 {
79     RSET children[2], rnew;
80     struct rset_private *info;
81
82     children[0] = rset_l;
83     children[1] = rset_r;
84     rnew = rset_create_base(ctrl, nmem, kcontrol, scope, 0, 2, children);
85     info = (struct rset_private *) nmem_malloc(rnew->nmem, sizeof(*info));
86     info->rset_l = rset_l;
87     info->rset_r = rset_r;
88     rnew->priv = info;
89     return rnew;
90 }
91
92 RSET rset_create_not(NMEM nmem, struct rset_key_control *kcontrol,
93                      int scope, RSET rset_l, RSET rset_r)
94 {
95     return rsbool_create_base(&control_not, nmem, kcontrol,
96                               scope, rset_l, rset_r);
97 }
98
99 static void r_delete(RSET ct)
100 {
101 }
102
103 static RSFD r_open(RSET ct, int flag)
104 {
105     struct rset_private *info = (struct rset_private *) ct->priv;
106     RSFD rfd;
107     struct rfd_private *p;
108
109     if (flag & RSETF_WRITE)
110     {
111         yaz_log(YLOG_FATAL, "bool set type is read-only");
112         return NULL;
113     }
114     rfd = rfd_create_base(ct);
115     if (rfd->priv)
116         p = (struct rfd_private *)rfd->priv;
117     else {
118         p = nmem_malloc(ct->nmem,sizeof(*p));
119         rfd->priv = p;
120         p->buf_l = nmem_malloc(ct->nmem, ct->keycontrol->key_size);
121         p->buf_r = nmem_malloc(ct->nmem, ct->keycontrol->key_size);
122     }
123
124     yaz_log(YLOG_DEBUG,"rsbool (%s) open [%p]", ct->control->desc, rfd);
125     p->hits=0;
126
127     p->rfd_l = rset_open (info->rset_l, RSETF_READ);
128     p->rfd_r = rset_open (info->rset_r, RSETF_READ);
129     p->more_l = rset_read(p->rfd_l, p->buf_l, &p->term_l);
130     p->more_r = rset_read(p->rfd_r, p->buf_r, &p->term_r);
131     p->tail = 0;
132     return rfd;
133 }
134
135 static void r_close (RSFD rfd)
136 {
137     struct rfd_private *prfd=(struct rfd_private *)rfd->priv;
138
139     rset_close (prfd->rfd_l);
140     rset_close (prfd->rfd_r);
141 }
142
143 static int r_forward(RSFD rfd, void *buf, TERMID *term,
144                      const void *untilbuf)
145 {
146     struct rfd_private *p = (struct rfd_private *)rfd->priv;
147     const struct rset_key_control *kctrl=rfd->rset->keycontrol;
148
149     if ( p->more_l && ((kctrl->cmp)(untilbuf,p->buf_l)>=rfd->rset->scope) )
150         p->more_l = rset_forward(p->rfd_l, p->buf_l, &p->term_l, untilbuf);
151     if ( p->more_r && ((kctrl->cmp)(untilbuf,p->buf_r)>=rfd->rset->scope))
152         p->more_r = rset_forward(p->rfd_r, p->buf_r, &p->term_r, untilbuf);
153     p->tail = 0;
154     return rset_read(rfd,buf,term);
155 }
156
157
158 /*
159     1,1         1,3
160     1,9         2,1
161     1,11        3,1
162     2,9
163
164   1,1     1,1
165   1,3     1,3
166           1,9
167           1,11
168   2,1     2,1
169           2,9
170           3,1
171 */
172
173 static int r_read_not(RSFD rfd, void *buf, TERMID *term)
174 {
175     struct rfd_private *p = (struct rfd_private *)rfd->priv;
176     const struct rset_key_control *kctrl = rfd->rset->keycontrol;
177
178     while (p->more_l)
179     {
180         int cmp;
181
182         if (p->more_r)
183             cmp = (*kctrl->cmp)(p->buf_l, p->buf_r);
184         else
185             cmp = -rfd->rset->scope;
186
187         if (cmp <= -rfd->rset->scope)
188         { /* cmp == -2 */
189             memcpy (buf, p->buf_l, kctrl->key_size);
190             if (term)
191                 *term=p->term_l;
192             p->more_l = rset_read(p->rfd_l, p->buf_l, &p->term_l);
193             p->hits++;
194             return 1;
195         }
196         else if (cmp >= rfd->rset->scope)   /* cmp >1 */
197         {
198             p->more_r = rset_forward( p->rfd_r, p->buf_r,
199                                       &p->term_r, p->buf_l);
200         }
201         else
202         { /* cmp== -1, 0, or 1 */
203             memcpy (buf, p->buf_l, kctrl->key_size);
204             if (term)
205                 *term = p->term_l;
206             do
207             {
208                 p->more_l = rset_read(p->rfd_l, p->buf_l, &p->term_l);
209                 if (!p->more_l)
210                     break;
211                 cmp = (*kctrl->cmp)(p->buf_l, buf);
212             } while (abs(cmp)<rfd->rset->scope);
213                 /*  (cmp >= -1 && cmp <= 1) */
214             do
215             {
216                 p->more_r = rset_read(p->rfd_r, p->buf_r, &p->term_r);
217                 if (!p->more_r)
218                     break;
219                 cmp = (*kctrl->cmp)(p->buf_r, buf);
220             } while (abs(cmp)<rfd->rset->scope);
221                /* (cmp >= -1 && cmp <= 1) */
222         }
223     }
224     return 0;
225 }
226
227 static void r_pos(RSFD rfd, double *current, double *total)
228 {
229     struct rfd_private *p = (struct rfd_private *)rfd->priv;
230     double lcur, ltot;
231     double rcur, rtot;
232     double r;
233     ltot = -1;
234     rtot = -1;
235     rset_pos(p->rfd_l, &lcur, &ltot);
236     rset_pos(p->rfd_r, &rcur, &rtot);
237     if ( (rtot<0) && (ltot<0)) { /*no position */
238         *current = rcur;  /* return same as you got */
239         *total = rtot;    /* probably -1 for not available */
240     }
241     if (rtot < 0)
242         rtot = rcur = 0; /* if only one useful, use it */
243     if (ltot < 0)
244         ltot = lcur = 0;
245     if (rtot+ltot < 1)
246     {   /* empty rset */
247         *current = *total = 0;
248         return;
249     }
250     r = 1.0*(lcur+rcur)/(ltot+rtot); /* weighed average of l and r */
251     *current = (double) (p->hits);
252     *total = *current/r ;
253 #if RSET_DEBUG
254     yaz_log(YLOG_DEBUG,"bool_pos: (%s/%s) %0.1f/%0.1f= %0.4f ",
255                     info->rset_l->control->desc, info->rset_r->control->desc,
256                     *current, *total, r);
257 #endif
258 }
259
260 static void r_get_terms(RSET ct, TERMID *terms, int maxterms, int *curterm)
261 {
262     struct rset_private *info = (struct rset_private *) ct->priv;
263     rset_getterms(info->rset_l, terms, maxterms, curterm);
264     rset_getterms(info->rset_r, terms, maxterms, curterm);
265 }
266
267 /*
268  * Local variables:
269  * c-basic-offset: 4
270  * c-file-style: "Stroustrup"
271  * indent-tabs-mode: nil
272  * End:
273  * vim: shiftwidth=4 tabstop=8 expandtab
274  */
275