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