Added Retrieval (data management) functions en masse.
[yaz-moved-to-github.git] / retrieval / d1_doespec.c
1 /*
2  * Copyright (c) 1995, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: d1_doespec.c,v $
7  * Revision 1.1  1995-11-01 11:56:07  quinn
8  * Added Retrieval (data management) functions en masse.
9  *
10  *
11  */
12
13
14 #include <assert.h>
15 #include <log.h>
16 #include <proto.h>
17 #include "data1.h"
18
19 static int match_children(data1_node *n, Z_ETagUnit **t, int num);
20
21 static int match_children_wildpath(data1_node *n, Z_ETagUnit **t, int num)
22 {return 0;}
23
24 static int match_children_here(data1_node *n, Z_ETagUnit **t, int num)
25 {
26     int counter = 0, hits = 0;
27     data1_node *c;
28     Z_ETagUnit *tp = *t;
29     Z_Occurrences *occur;
30
31     for (c = n->child; c ; c = c->next)
32     {
33         data1_tag *tag = 0;
34
35         if (c->which != DATA1N_tag)
36             return 0;
37
38         if (tp->which == Z_ETagUnit_specificTag)
39         {
40             Z_SpecificTag *want = tp->u.specificTag;
41             occur = want->occurrences;
42             if (c->u.tag.element)
43                 tag = c->u.tag.element->tag;
44             if (*want->tagType != (tag ? tag->tagset->type : 3))
45                 continue;
46             if (want->tagValue->which == Z_StringOrNumeric_numeric)
47             {
48                 if (!tag || tag->which != DATA1T_numeric)
49                     continue;
50                 if (*want->tagValue->u.numeric != tag->value.numeric)
51                     continue;
52             }
53             else
54             {
55                 assert(want->tagValue->which == Z_StringOrNumeric_string);
56                 if (tag && tag->which != DATA1T_string)
57                     continue;
58                 if (data1_matchstr(want->tagValue->u.string,
59                     tag ? tag->value.string : c->u.tag.tag))
60                     continue;
61             }
62         }
63         else
64             occur = tp->u.wildThing;
65
66         /*
67          * Ok, so we have a matching tag. Are we within occurrences-range?
68          */
69         counter++;
70         if (occur && occur->which == Z_Occurrences_last)
71         {
72             logf(LOG_WARN, "Can't do occurrences=last (yet)");
73             return 0;
74         }
75         if (!occur || occur->which == Z_Occurrences_all ||
76             (occur->which == Z_Occurrences_values && counter >=
77             *occur->u.values->start))
78         {
79             if (match_children(c, t + 1, num - 1))
80             {
81                 c->u.tag.node_selected = 1;
82                 hits++;
83                 /*
84                  * have we looked at enough children?
85                  */
86                 if (!occur || (occur->which == Z_Occurrences_values &&
87                     counter - *occur->u.values->start >=
88                     *occur->u.values->howMany - 1))
89                     return hits;
90             }
91         }
92     }
93     return hits;
94 }
95
96 static void mark_children(data1_node *n)
97 {
98     data1_node *c;
99
100     for (c = n->child; c; c = c->next)
101     {
102         if (c->which != DATA1N_tag)
103             continue;
104         c->u.tag.node_selected = 1;
105         mark_children(c);
106     }
107 }
108
109 static int match_children(data1_node *n, Z_ETagUnit **t, int num)
110 {
111     if (!num)
112     {
113         mark_children(n); /* Here there shall be variants, like, dude */
114         return 1;
115     }
116     switch (t[0]->which)
117     {
118         case Z_ETagUnit_wildThing:
119         case Z_ETagUnit_specificTag: return match_children_here(n, t, num);
120         case Z_ETagUnit_wildPath: return match_children_wildpath(n, t, num);
121         default:
122             abort();
123     }
124 }
125
126 int data1_doespec1(data1_node *n, Z_Espec1 *e)
127 {
128     int i;
129
130     for (i = 0; i < e->num_elements; i++)
131         match_children(n,  e->elements[i]->u.simpleElement->path->tags,
132             e->elements[i]->u.simpleElement->path->num_tags);
133     return 0;
134 }