Put local variables footer in all c, h files.
[idzebra-moved-to-github.git] / rset / rsmultiandor.c
index 06005bd..ccf57de 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: rsmultiandor.c,v 1.16 2005-04-26 10:09:38 adam Exp $
+/* $Id: rsmultiandor.c,v 1.20 2006-05-10 08:13:33 adam Exp $
    Copyright (C) 1995-2005
    Index Data ApS
 
@@ -101,19 +101,18 @@ struct heap_item {
 struct heap {
     int heapnum;
     int heapmax;
-    const struct key_control *kctrl;
+    const struct rset_key_control *kctrl;
     struct heap_item **heap; /* ptrs to the rfd */
 };
 typedef struct heap *HEAP;
 
 
-struct rset_multiandor_info {
-    int     no_rsets;
-    RSET    *rsets;
+struct rset_private {
+    int dummy;
 };
 
 
-struct rset_multiandor_rfd {
+struct rfd_private {
     int flag;
     struct heap_item *items; /* we alloc and free them here */
     HEAP h; /* and move around here */
@@ -222,7 +221,7 @@ static void heap_insert (HEAP h, struct heap_item *hi)
 
 
 static
-HEAP heap_create (NMEM nmem, int size, const struct key_control *kctrl)
+HEAP heap_create (NMEM nmem, int size, const struct rset_key_control *kctrl)
 {
     HEAP h = (HEAP) nmem_malloc (nmem, sizeof(*h));
 
@@ -263,56 +262,51 @@ int compare_ands(const void *x, const void *y)
 
 /* Creating and deleting rsets ***********************/
 
-static RSET rsmulti_andor_create( NMEM nmem, const struct key_control *kcontrol, 
-                           int scope, int no_rsets, RSET* rsets, 
-                           const struct rset_control *ctrl)
+static RSET rsmulti_andor_create(NMEM nmem,
+                                struct rset_key_control *kcontrol, 
+                                int scope, TERMID termid,
+                                int no_rsets, RSET* rsets, 
+                                const struct rset_control *ctrl)
 {
-    RSET rnew = rset_create_base(ctrl, nmem,kcontrol, scope,0);
-    struct rset_multiandor_info *info;
+    RSET rnew = rset_create_base(ctrl, nmem, kcontrol, scope, termid,
+                                no_rsets, rsets);
+    struct rset_private *info;
     if (!log_level_initialized)
     {
         log_level = yaz_log_module_level("rsmultiandor");
         log_level_initialized = 1;
     }
-    info = (struct rset_multiandor_info *) nmem_malloc(rnew->nmem,sizeof(*info));
-    info->no_rsets = no_rsets;
-    info->rsets = (RSET*)nmem_malloc(rnew->nmem, no_rsets*sizeof(*rsets));
-    memcpy(info->rsets,rsets,no_rsets*sizeof(*rsets));
+    yaz_log(log_level, "rsmultiand_andor_create scope=%d", scope);
+    info = (struct rset_private *) nmem_malloc(rnew->nmem, sizeof(*info));
     rnew->priv = info;
     return rnew;
 }
 
-RSET rsmulti_or_create(NMEM nmem, const struct key_control *kcontrol,
-                      int scope, int no_rsets, RSET* rsets)
+RSET rsmulti_or_create(NMEM nmem, struct rset_key_control *kcontrol,
+                      int scope, TERMID termid, int no_rsets, RSET* rsets)
 {
-    return rsmulti_andor_create(nmem, kcontrol, scope, 
+    return rsmulti_andor_create(nmem, kcontrol, scope, termid,
                                 no_rsets, rsets, &control_or);
 }
 
-RSET rsmulti_and_create(NMEM nmem, const struct key_control *kcontrol,
+RSET rsmulti_and_create(NMEM nmem, struct rset_key_control *kcontrol,
                        int scope, int no_rsets, RSET* rsets)
 {
-    return rsmulti_andor_create(nmem, kcontrol, scope, 
+    return rsmulti_andor_create(nmem, kcontrol, scope, 0,
                                 no_rsets, rsets, &control_and);
 }
 
 static void r_delete (RSET ct)
 {
-    struct rset_multiandor_info *info = (struct rset_multiandor_info *) ct->priv;
-    int i;
-    for(i = 0; i<info->no_rsets; i++)
-        rset_delete(info->rsets[i]);
 }
 
-
 /* Opening and closing fd's on them *********************/
 
 static RSFD r_open_andor (RSET ct, int flag, int is_and)
 {
     RSFD rfd;
-    struct rset_multiandor_rfd *p;
-    struct rset_multiandor_info *info = (struct rset_multiandor_info *) ct->priv;
-    const struct key_control *kctrl = ct->keycontrol;
+    struct rfd_private *p;
+    const struct rset_key_control *kctrl = ct->keycontrol;
     int i;
 
     if (flag & RSETF_WRITE)
@@ -322,26 +316,27 @@ static RSFD r_open_andor (RSET ct, int flag, int is_and)
     }
     rfd = rfd_create_base(ct);
     if (rfd->priv) {
-        p = (struct rset_multiandor_rfd *)rfd->priv;
+        p = (struct rfd_private *)rfd->priv;
         if (!is_and)
             heap_clear(p->h);
         assert(p->items);
         /* all other pointers shouls already be allocated, in right sizes! */
     }
     else {
-        p = (struct rset_multiandor_rfd *) nmem_malloc (ct->nmem,sizeof(*p));
+        p = (struct rfd_private *) nmem_malloc (ct->nmem,sizeof(*p));
         rfd->priv = p;
         p->h = 0;
         p->tailbits = 0;
         if (is_and)
-            p->tailbits = nmem_malloc(ct->nmem, info->no_rsets*sizeof(char) );
+            p->tailbits = nmem_malloc(ct->nmem, ct->no_children*sizeof(char) );
         else 
-            p->h = heap_create( ct->nmem, info->no_rsets, kctrl);
-        p->items=(struct heap_item *) nmem_malloc(ct->nmem,
-                              info->no_rsets*sizeof(*p->items));
-        for (i = 0; i<info->no_rsets; i++){
-            p->items[i].rset = info->rsets[i];
-            p->items[i].buf = nmem_malloc(ct->nmem,kctrl->key_size);
+            p->h = heap_create( ct->nmem, ct->no_children, kctrl);
+        p->items = (struct heap_item *) 
+           nmem_malloc(ct->nmem, ct->no_children*sizeof(*p->items));
+        for (i = 0; i<ct->no_children; i++)
+       {
+            p->items[i].rset = ct->children[i];
+            p->items[i].buf = nmem_malloc(ct->nmem, kctrl->key_size);
         }
     }
     p->flag = flag;
@@ -350,17 +345,17 @@ static RSFD r_open_andor (RSET ct, int flag, int is_and)
     p->tailcount = 0;
     if (is_and)
     { /* read the array and sort it */
-        for (i = 0; i<info->no_rsets; i++){
-            p->items[i].fd = rset_open(info->rsets[i],RSETF_READ);
+        for (i = 0; i<ct->no_children; i++){
+            p->items[i].fd = rset_open(ct->children[i], RSETF_READ);
             if (!rset_read(p->items[i].fd, p->items[i].buf, &p->items[i].term))
                 p->eof = 1;
             p->tailbits[i] = 0;
         }
-        qsort(p->items, info->no_rsets, sizeof(p->items[0]), compare_ands);
+        qsort(p->items, ct->no_children, sizeof(p->items[0]), compare_ands);
     } else
     { /* fill the heap for ORing */
-        for (i = 0; i<info->no_rsets; i++){
-            p->items[i].fd = rset_open(info->rsets[i],RSETF_READ);
+        for (i = 0; i<ct->no_children; i++){
+            p->items[i].fd = rset_open(ct->children[i],RSETF_READ);
             if ( rset_read(p->items[i].fd, p->items[i].buf, &p->items[i].term))
                 heap_insert(p->h, &(p->items[i]));
         }
@@ -381,26 +376,23 @@ static RSFD r_open_and (RSET ct, int flag)
 
 static void r_close (RSFD rfd)
 {
-    struct rset_multiandor_info *info=
-        (struct rset_multiandor_info *)(rfd->rset->priv);
-    struct rset_multiandor_rfd *p=(struct rset_multiandor_rfd *)(rfd->priv);
+    struct rfd_private *p=(struct rfd_private *)(rfd->priv);
     int i;
 
     if (p->h)
         heap_destroy (p->h);
-    for (i = 0; i<info->no_rsets; i++) 
+    for (i = 0; i<rfd->rset->no_children; i++) 
         if (p->items[i].fd)
             rset_close(p->items[i].fd);
-    rfd_delete_base(rfd);
 }
 
 
 
 static int r_forward_or(RSFD rfd, void *buf, 
-                        TERMID *term,const void *untilbuf)
+                        TERMID *term, const void *untilbuf)
 { /* while heap head behind untilbuf, forward it and rebalance heap */
-    struct rset_multiandor_rfd *p = rfd->priv;
-    const struct key_control *kctrl = rfd->rset->keycontrol;
+    struct rfd_private *p = rfd->priv;
+    const struct rset_key_control *kctrl = rfd->rset->keycontrol;
     if (heap_empty(p->h))
         return 0;
     while ( (*kctrl->cmp)(p->h->heap[1]->buf,untilbuf) < -rfd->rset->scope )
@@ -416,22 +408,29 @@ static int r_forward_or(RSFD rfd, void *buf,
         }
 
     }
-    return r_read_or(rfd,buf,term);
+    return r_read_or(rfd, buf, term);
 }
 
 
 static int r_read_or (RSFD rfd, void *buf, TERMID *term)
 {
-    struct rset_multiandor_rfd *mrfd = rfd->priv;
-    const struct key_control *kctrl = rfd->rset->keycontrol;
+    RSET rset = rfd->rset;
+    struct rfd_private *mrfd = rfd->priv;
+    const struct rset_key_control *kctrl = rset->keycontrol;
     struct heap_item *it;
     int rdres;
     if (heap_empty(mrfd->h))
         return 0;
     it = mrfd->h->heap[1];
-    memcpy(buf,it->buf, kctrl->key_size); 
+    memcpy(buf, it->buf, kctrl->key_size);
     if (term)
-        *term = it->term;
+    {
+       if (rset->term)
+           *term = rset->term;
+       else
+           *term = it->term;
+       assert(*term);
+    }
     (mrfd->hits)++;
     rdres = rset_read(it->fd, it->buf, &it->term);
     if ( rdres )
@@ -451,9 +450,9 @@ static int r_read_and (RSFD rfd, void *buf, TERMID *term)
   /* Once a hit has been found, scan all items for the smallest */
   /* value. Mark all as being in the tail. Read next from that */
   /* item, and if not in the same record, clear its tail bit */
-    struct rset_multiandor_rfd *p = rfd->priv;
-    const struct key_control *kctrl = rfd->rset->keycontrol;
-    struct rset_multiandor_info *info = rfd->rset->priv;
+    struct rfd_private *p = rfd->priv;
+    RSET ct = rfd->rset;
+    const struct rset_key_control *kctrl = ct->keycontrol;
     int i, mintail;
     int cmp;
 
@@ -461,9 +460,9 @@ static int r_read_and (RSFD rfd, void *buf, TERMID *term)
         if (p->tailcount) 
         { /* we are tailing, find lowest tail and return it */
             mintail = 0;
-            while ((mintail<info->no_rsets) && !p->tailbits[mintail])
+            while ((mintail<ct->no_children) && !p->tailbits[mintail])
                 mintail++; /* first tail */
-            for (i = mintail+1; i<info->no_rsets; i++)
+            for (i = mintail+1; i<ct->no_children; i++)
             {
                 if (p->tailbits[i])
                 {
@@ -480,16 +479,18 @@ static int r_read_and (RSFD rfd, void *buf, TERMID *term)
                            &p->items[mintail].term))
             {
                 p->eof = 1; /* game over, once tails have been returned */
-                p->tailbits[mintail]=0; 
+                p->tailbits[mintail] = 0; 
                 (p->tailcount)--;
+               (p->hits)++;
                 return 1;
             }
             /* still a tail? */
-            cmp=(*kctrl->cmp)(p->items[mintail].buf,buf);
+            cmp = (*kctrl->cmp)(p->items[mintail].buf,buf);
             if (cmp >= rfd->rset->scope){
-                p->tailbits[mintail]=0;
+                p->tailbits[mintail] = 0;
                 (p->tailcount)--;
             }
+           (p->hits)++;
             return 1;
         } 
         /* not tailing, forward until all reocrds match, and set up */
@@ -497,9 +498,9 @@ static int r_read_and (RSFD rfd, void *buf, TERMID *term)
         if (p->eof)
             return 0; /* nothing more to see */
         i = 1; /* assume items[0] is highest up */
-        while (i<info->no_rsets) {
-            cmp=(*kctrl->cmp)(p->items[0].buf,p->items[i].buf);
-            if (cmp<=-rfd->rset->scope) { /* [0] was behind, forward it */
+        while (i<ct->no_children) {
+            cmp = (*kctrl->cmp)(p->items[0].buf, p->items[i].buf);
+            if (cmp <= -rfd->rset->scope) { /* [0] was behind, forward it */
                 if (!rset_forward(p->items[0].fd, p->items[0].buf, 
                                   &p->items[0].term, p->items[i].buf))
                 {
@@ -521,9 +522,9 @@ static int r_read_and (RSFD rfd, void *buf, TERMID *term)
         /* if we get this far, all rsets are now within +- scope of [0] */
         /* ergo, we have a hit. Mark them all as tailing, and let the */
         /* upper 'if' return the hits in right order */
-        for (i = 0; i<info->no_rsets; i++)
+        for (i = 0; i<ct->no_children; i++)
             p->tailbits[i] = 1;
-        p->tailcount = info->no_rsets;
+        p->tailcount = ct->no_children;
     } /* while 1 */
 }
 
@@ -531,14 +532,14 @@ static int r_read_and (RSFD rfd, void *buf, TERMID *term)
 static int r_forward_and(RSFD rfd, void *buf, TERMID *term, 
                          const void *untilbuf)
 { 
-    struct rset_multiandor_rfd *p = rfd->priv;
-    const struct key_control *kctrl = rfd->rset->keycontrol;
-    struct rset_multiandor_info *info = rfd->rset->priv;
+    struct rfd_private *p = rfd->priv;
+    RSET ct = rfd->rset;
+    const struct rset_key_control *kctrl = ct->keycontrol;
     int i;
     int cmp;
     int killtail = 0;
 
-    for (i = 0; i<info->no_rsets; i++)
+    for (i = 0; i<ct->no_children; i++)
     {
         cmp = (*kctrl->cmp)(p->items[i].buf,untilbuf);
         if (cmp <= -rfd->rset->scope)
@@ -555,7 +556,7 @@ static int r_forward_and(RSFD rfd, void *buf, TERMID *term,
     }
     if (killtail) 
     {
-        for (i = 0; i<info->no_rsets; i++)
+        for (i = 0; i<ct->no_children; i++)
             p->tailbits[i] = 0;
         p->tailcount = 0;
     }
@@ -564,14 +565,13 @@ static int r_forward_and(RSFD rfd, void *buf, TERMID *term,
 
 static void r_pos (RSFD rfd, double *current, double *total)
 {
-    struct rset_multiandor_info *info =
-       (struct rset_multiandor_info *)(rfd->rset->priv);
-    struct rset_multiandor_rfd *mrfd = 
-       (struct rset_multiandor_rfd *)(rfd->priv);
+    RSET ct = rfd->rset;
+    struct rfd_private *mrfd = 
+       (struct rfd_private *)(rfd->priv);
     double cur, tot;
     double scur = 0.0, stot = 0.0;
     int i;
-    for (i = 0; i<info->no_rsets; i++){
+    for (i = 0; i<ct->no_children; i++){
         rset_pos(mrfd->items[i].fd, &cur, &tot);
         yaz_log(log_level, "r_pos: %d %0.1f %0.1f", i, cur,tot); 
         scur += cur;
@@ -597,23 +597,36 @@ static int r_write (RSFD rfd, const void *buf)
 }
 
 static void r_get_terms(RSET ct, TERMID *terms, int maxterms, int *curterm)
-    /* Special case: Some multi-ors have all terms pointing to the same */
-    /* term. We do not want to duplicate those. Other multiors (and ands) */
-    /* have different terms under them. Those we want. */
 {
-    struct rset_multiandor_info *info = 
-        (struct rset_multiandor_info *) ct->priv;
-    int firstterm= *curterm;
-    int i;
-    for (i = 0; i<info->no_rsets; i++)
+    if (ct->term)
+       rset_get_one_term(ct, terms, maxterms, curterm);
+    else
     {
-        rset_getterms(info->rsets[i], terms, maxterms, curterm);
-        if ( ( *curterm > firstterm+1 ) &&
-            ( *curterm <= maxterms ) &&
-            ( terms[(*curterm)-1] == terms[firstterm] ) 
-           )
-            (*curterm)--; /* forget the term, seen that before */
+       /* Special case: Some multi-ors have all terms pointing to the same 
+          term. We do not want to duplicate those. Other multiors (and ands)
+          have different terms under them. Those we want. 
+       */
+       int firstterm= *curterm;
+       int i;
+
+       for (i = 0; i<ct->no_children; i++)
+       {
+           rset_getterms(ct->children[i], terms, maxterms, curterm);
+           if ( ( *curterm > firstterm+1 ) &&
+                ( *curterm <= maxterms ) &&
+                ( terms[(*curterm)-1] == terms[firstterm] ) 
+               )
+               (*curterm)--; /* forget the term, seen that before */
+       }
     }
 }
 
 
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+