cd8db71e49e699d1c2e95b0f5d4a74f43b3899ad
[SXSI/XMLTree.git] / xml-tree-inc.hpp
1 #ifndef XML_TREE_INTERNAL__
2 #error "xml-tree-inc.hpp should not be included directly"
3 #endif
4
5 #ifndef XML_TREE_INC_HPP_
6 #define XML_TREE_INC_HPP_
7
8 #include <cstdio>
9
10 #if 0
11 #define ASSERT_NODE(orig, res) do {                                     \
12     if (res < -1 || res >= par->n|| (res != -1 && res < orig))          \
13     fprintf(stderr,                                                     \
14       "Assertion failure: original node %i, result %i, line %i\n",      \
15             orig, res, __LINE__);                                       \
16   } while (0)
17 #else
18 #define ASSERT_NODE(orig, res)
19 #endif
20
21 inline uint32_t xml_tree::size() const
22 {
23   return tag_seq_len / 2;
24 }
25
26 inline uint32_t xml_tree::num_tags() const
27 {
28   return tag_names->size();
29 }
30
31 inline uint32_t xml_tree::subtree_size(xml_tree::node_t x) const
32 {
33   return bp_subtree_size(this->par, x);
34 }
35
36 inline uint32_t
37 xml_tree::subtree_tags(xml_tree::node_t x, xml_tree::tag_t label) const
38 {
39   xml_tree::node_t y = bp_find_close(this->par, x);
40   if (y - x < 10) {
41     uint32_t count = 0;
42     for(xml_tree::node_t i = x; i < y; i++)
43       count += (tag(i) == label);
44     return count;
45   } else {
46     return tags->rank(label, y) - tags->rank(label, x);
47   };
48 }
49
50 inline bool xml_tree::is_leaf(xml_tree::node_t x) const
51 {
52   return !bp_inspect(this->par, x+1);
53 }
54
55 inline bool xml_tree::is_ancestor(xml_tree::node_t x,
56                                   xml_tree::node_t y) const
57 {
58   return bp_is_ancestor(this->par, x, y);
59 }
60
61 inline bool
62 xml_tree::is_right_descendant(xml_tree::node_t x,
63                               xml_tree::node_t y) const
64 {
65   return
66     (x > root())
67     && (y <= bp_parent_close(this->par, x))
68     && (y >= bp_find_close(this->par, x));
69 }
70
71 inline bool xml_tree::is_first_child(xml_tree::node_t x) const
72 {
73   return (x <= this->root()) || (bp_inspect(this->par, x - 1));
74 }
75
76 inline bool xml_tree::is_nil(xml_tree::node_t x) const
77 {
78   return (x == xml_tree::NIL);
79 }
80
81 inline xml_tree::tag_t xml_tree::tag(xml_tree::node_t x) const
82 {
83   if (bits_per_tag == 8)
84     return  (xml_tree::tag_t) (((unsigned char*) tag_seq)[x]);
85   else
86     return get_field(tag_seq, bits_per_tag, x);
87 }
88
89 inline xml_tree::node_t xml_tree::root() const
90 {
91   return xml_tree::ROOT;
92 }
93
94
95 inline xml_tree::node_t xml_tree::parent(xml_tree::node_t x) const
96 {
97   return bp_parent(this->par, x);
98 }
99
100 inline xml_tree::node_t xml_tree::first_child(node_t x) const
101 {
102   xml_tree::node_t result = bp_first_child(this->par, x);
103   ASSERT_NODE(x, result);
104   return result;
105 }
106
107 inline xml_tree::node_t xml_tree::last_child(xml_tree::node_t x) const
108 {
109   if (is_leaf(x))
110     return  xml_tree::NIL;
111   else
112     return bp_find_open(this->par, bp_find_close(this->par, x) - 1);
113 }
114
115 inline xml_tree::node_t xml_tree::next_sibling(xml_tree::node_t x) const
116 {
117   xml_tree::node_t result = bp_next_sibling(this->par, x);
118   ASSERT_NODE(x, result);
119   return result;
120 }
121
122 inline xml_tree::node_t xml_tree::prev_sibling(xml_tree::node_t x) const
123 {
124   return bp_prev_sibling(this->par, x);
125 }
126
127 inline xml_tree::node_t xml_tree::first_element(xml_tree::node_t x) const
128 {
129   xml_tree::node_t n = first_child(x);
130   if (is_nil(n)) return xml_tree::NIL;
131   switch (tag(n)) {
132   case xml_tree::ATTRIBUTE_OPEN_TAG_ID:
133     n = next_sibling(n);
134     if (is_nil(n) || tag(n) != xml_tree::PCDATA_OPEN_TAG_ID) return n;
135     //Fallthrough
136   case PCDATA_OPEN_TAG_ID:
137     n = n + 2;
138     return bp_inspect(this->par, n) ? n : xml_tree::NIL;
139   default:
140     return n;
141   };
142 }
143
144 inline xml_tree::node_t xml_tree::next_element(xml_tree::node_t x) const
145 {
146   x = next_sibling(x);
147   if (is_nil(x)) return x;
148   if (tag(x) == xml_tree::PCDATA_OPEN_TAG_ID){
149     xml_tree::node_t y = x + 2;
150     return bp_inspect(this->par, y) ? y : xml_tree::NIL;
151   } else
152     return x;
153 }
154
155 inline xml_tree::node_t xml_tree::tagged_next(node_t x, tag_t tag) const
156 {
157   return this->tags->select_next(tag, x);
158 }
159
160 inline xml_tree::node_t
161 xml_tree::tagged_descendant(xml_tree::node_t x,
162                             xml_tree::tag_t tag) const
163 {
164   xml_tree::node_t y = tagged_next(x, tag);
165   return is_nil(y) || !is_ancestor(x, y) ? xml_tree::NIL : y;
166 }
167
168 inline xml_tree::node_t
169 xml_tree::tagged_following_before(xml_tree::node_t x,
170                                   xml_tree::tag_t tag,
171                                   xml_tree::node_t limit) const
172 {
173   xml_tree::node_t close = bp_find_close(this->par, x);
174   xml_tree::node_t s = tagged_next(close, tag);
175   return (s < limit) ? s : xml_tree::NIL;
176 }
177
178
179 inline xml_tree::node_t xml_tree::tagged_child(xml_tree::node_t x,
180                                                xml_tree::tag_t t) const
181 {
182   xml_tree::node_t c = first_child(x);
183   xml_tree::node_t result;
184   if (is_nil(c) || tag(c) == t)
185     return c;
186   else
187     return tagged_sibling(c, t);
188   /*  ASSERT_NODE(x, result);
189       return result;*/
190 }
191
192 inline xml_tree::node_t xml_tree::tagged_sibling(xml_tree::node_t x,
193                                                  xml_tree::tag_t t) const
194 {
195   xml_tree::node_t sibling = next_sibling(x);
196   xml_tree::tag_t stag;
197   while (sibling  != xml_tree::NIL) {
198     stag = tag(sibling);
199     if (stag == t) {
200       ASSERT_NODE(x, sibling);
201       return  sibling;
202     }
203     sibling = next_sibling(sibling);
204   };
205   ASSERT_NODE(x, sibling);
206   return sibling;
207 }
208
209 xml_tree::node_t xml_tree::closing(xml_tree::node_t x) const
210 {
211   return bp_find_close(this->par, x);
212 }
213
214
215 inline SXSI::TextCollection *xml_tree::get_text_collection() const
216 {
217   return text_collection;
218 }
219
220 inline xml_tree::node_t xml_tree::parent_node(int32_t d) const
221 {
222   return (xml_tree::node_t) text_positions->select1(d + 1);
223 }
224
225 inline SXSI::TextCollection::document_result
226 xml_tree::prefix(uchar const *s) const
227 {
228   return text_collection->Prefix(s);
229 }
230
231 inline SXSI::TextCollection::document_result
232 xml_tree::suffix(uchar const *s) const
233 {
234   return text_collection->Suffix(s);
235 }
236
237 inline SXSI::TextCollection::document_result
238 xml_tree::equals(uchar const *s) const
239 {
240   return text_collection->Equal(s);
241 }
242
243 inline SXSI::TextCollection::document_result
244 xml_tree::contains(uchar const *s) const
245 {
246   return text_collection->Contains(s);
247 }
248
249 inline SXSI::TextCollection::document_result
250 xml_tree::less_than(uchar const *s) const
251 {
252   return text_collection->LessThan(s);
253 }
254
255
256 #endif //XML_TREE_INC_HPP_