@@ -27,17 +27,63 @@ pub const TreeWalker = struct {
2727 root : * parser.Node ,
2828 current_node : * parser.Node ,
2929 what_to_show : u32 ,
30- filter : ? Env.Callback ,
30+ filter : ? Env.Function ,
31+
32+ depth : usize ,
33+
34+ pub const TreeWalkerOpts = union (enum ) {
35+ function : Env.Function ,
36+ object : struct { acceptNode : Env .Function },
37+ };
38+
39+ pub fn init (node : * parser.Node , what_to_show : ? u32 , filter : ? TreeWalkerOpts ) ! TreeWalker {
40+ var filter_func : ? Env.Function = null ;
41+
42+ if (filter ) | f | {
43+ filter_func = switch (f ) {
44+ .function = > | func | func ,
45+ .object = > | o | o .acceptNode ,
46+ };
47+ }
3148
32- pub fn init (node : * parser.Node , what_to_show : ? u32 , filter : ? Env.Callback ) TreeWalker {
3349 return .{
3450 .root = node ,
3551 .current_node = node ,
3652 .what_to_show = what_to_show orelse NodeFilter ._SHOW_ALL ,
37- .filter = filter ,
53+ .filter = filter_func ,
54+ .depth = 0 ,
55+ };
56+ }
57+
58+ fn verify_what_to_show (self : * const TreeWalker , node : * parser.Node ) ! bool {
59+ const node_type = try parser .nodeType (node );
60+ const what_to_show = self .what_to_show ;
61+ return switch (node_type ) {
62+ .attribute = > what_to_show & NodeFilter ._SHOW_ATTRIBUTE != 0 ,
63+ .cdata_section = > what_to_show & NodeFilter ._SHOW_CDATA_SECTION != 0 ,
64+ .comment = > what_to_show & NodeFilter ._SHOW_COMMENT != 0 ,
65+ .document = > what_to_show & NodeFilter ._SHOW_DOCUMENT != 0 ,
66+ .document_fragment = > what_to_show & NodeFilter ._SHOW_DOCUMENT_FRAGMENT != 0 ,
67+ .document_type = > what_to_show & NodeFilter ._SHOW_DOCUMENT_TYPE != 0 ,
68+ .element = > what_to_show & NodeFilter ._SHOW_ELEMENT != 0 ,
69+ .entity = > what_to_show & NodeFilter ._SHOW_ENTITY != 0 ,
70+ .entity_reference = > what_to_show & NodeFilter ._SHOW_ENTITY_REFERENCE != 0 ,
71+ .notation = > what_to_show & NodeFilter ._SHOW_NOTATION != 0 ,
72+ .processing_instruction = > what_to_show & NodeFilter ._SHOW_PROCESSING_INSTRUCTION != 0 ,
73+ .text = > what_to_show & NodeFilter ._SHOW_TEXT != 0 ,
3874 };
3975 }
4076
77+ fn verify_filter (self : * const TreeWalker , node : * parser.Node ) ! bool {
78+ if (self .filter ) | f | {
79+ const filter = try f .call (u32 , .{node });
80+ return switch (filter ) {
81+ NodeFilter ._FILTER_ACCEPT = > true ,
82+ else = > false ,
83+ };
84+ } else return true ;
85+ }
86+
4187 pub fn get_root (self : * TreeWalker ) * parser.Node {
4288 return self .root ;
4389 }
@@ -50,45 +96,92 @@ pub const TreeWalker = struct {
5096 return self .what_to_show ;
5197 }
5298
53- pub fn get_filter (self : * TreeWalker ) ? Env.Callback {
99+ pub fn get_filter (self : * TreeWalker ) ? Env.Function {
54100 return self .filter ;
55101 }
56102
57- pub fn _firstChild (self : * TreeWalker ) ? * parser.Node {
58- const first_child = parser .nodeFirstChild (self .current_node ) catch return null ;
59- self .current_node = first_child orelse return null ;
60- return first_child ;
103+ pub fn _firstChild (self : * TreeWalker ) ! ? * parser.Node {
104+ const children = try parser .nodeGetChildNodes (self .current_node );
105+ const child_count = try parser .nodeListLength (children );
106+
107+ for (0.. child_count ) | i | {
108+ const index : u32 = @intCast (i );
109+ const child = (try parser .nodeListItem (children , index )) orelse return null ;
110+
111+ if (! try self .verify_what_to_show (child )) continue ;
112+ if (! try self .verify_filter (child )) continue ;
113+
114+ self .depth += 1 ;
115+ self .current_node = child ;
116+ return child ;
117+ }
118+
119+ return null ;
61120 }
62121
63- pub fn _lastChild (self : * TreeWalker ) ? * parser.Node {
64- const last_child = parser .nodeLastChild (self .current_node ) catch return null ;
65- self .current_node = last_child orelse return null ;
66- return last_child ;
122+ pub fn _lastChild (self : * TreeWalker ) ! ? * parser.Node {
123+ const children = try parser .nodeGetChildNodes (self .current_node );
124+ const child_count = try parser .nodeListLength (children );
125+
126+ for (0.. child_count ) | i | {
127+ const index : u32 = @intCast (child_count - 1 - i );
128+ const child = (try parser .nodeListItem (children , index )) orelse return null ;
129+
130+ if (! try self .verify_what_to_show (child )) continue ;
131+ if (! try self .verify_filter (child )) continue ;
132+
133+ self .depth += 1 ;
134+ self .current_node = child ;
135+ return child ;
136+ }
137+
138+ return null ;
67139 }
68140
69- pub fn _nextNode (self : * TreeWalker ) ? * parser.Node {
141+ pub fn _nextNode (self : * TreeWalker ) ! ? * parser.Node {
70142 return self ._firstChild ();
71143 }
72144
73- pub fn _nextSibling (self : * TreeWalker ) ? * parser.Node {
74- const next_sibling = parser .nodeNextSibling (self .current_node ) catch return null ;
75- self .current_node = next_sibling orelse return null ;
76- return next_sibling ;
145+ pub fn _nextSibling (self : * TreeWalker ) ! ? * parser.Node {
146+ var current = self .current_node ;
147+
148+ while (true ) {
149+ current = (try parser .nodeNextSibling (current )) orelse return null ;
150+ if (! try self .verify_what_to_show (current )) continue ;
151+ if (! try self .verify_filter (current )) continue ;
152+ break ;
153+ }
154+
155+ return current ;
77156 }
78157
79- pub fn _parentNode (self : * TreeWalker ) ? * parser.Node {
80- const parent = parser .nodeParentNode (self .current_node ) catch return null ;
81- self .current_node = parent orelse return null ;
158+ pub fn _parentNode (self : * TreeWalker ) ! ? * parser.Node {
159+ if (self .depth == 0 ) return null ;
160+
161+ const parent = (try parser .nodeParentNode (self .current_node )) orelse return null ;
162+
163+ if (! try self .verify_what_to_show (parent )) return null ;
164+ if (! try self .verify_filter (parent )) return null ;
165+
166+ self .depth -= 1 ;
167+ self .current_node = parent ;
82168 return parent ;
83169 }
84170
85- pub fn _previousNode (self : * TreeWalker ) ? * parser.Node {
171+ pub fn _previousNode (self : * TreeWalker ) ! ? * parser.Node {
86172 return self ._parentNode ();
87173 }
88174
89- pub fn _previousSibling (self : * TreeWalker ) ? * parser.Node {
90- const previous_sibling = parser .nodePreviousSibling (self .current_node ) catch return null ;
91- self .current_node = previous_sibling orelse return null ;
92- return previous_sibling ;
175+ pub fn _previousSibling (self : * TreeWalker ) ! ? * parser.Node {
176+ var current = self .current_node ;
177+
178+ while (true ) {
179+ current = (try parser .nodePreviousSibling (current )) orelse return null ;
180+ if (! try self .verify_what_to_show (current )) continue ;
181+ if (! try self .verify_filter (current )) continue ;
182+ break ;
183+ }
184+
185+ return current ;
93186 }
94187};
0 commit comments