-
Notifications
You must be signed in to change notification settings - Fork 301
Support isEqualNode
#1246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: zigdom
Are you sure you want to change the base?
Support isEqualNode
#1246
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -227,6 +227,81 @@ pub fn nodeType(self: *const Node) u8 { | |||
| }; | ||||
| } | ||||
|
|
||||
| pub fn isEqualNode(self: *Node, other: *Node, page: *Page) bool { | ||||
| // Make sure types match. | ||||
| if (self.nodeType() != other.nodeType()) { | ||||
| return false; | ||||
| } | ||||
|
|
||||
| // TODO: Compare `localName` and prefix. | ||||
| switch (self._type) { | ||||
| .element => { | ||||
| const e1 = self.as(Element); | ||||
| const e2 = other.as(Element); | ||||
|
|
||||
| const e1_tag = e1.getTagNameSpec(&page.buf); | ||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you can use |
||||
| var buf: [Page.BUF_SIZE]u8 = undefined; | ||||
| const e2_tag = e2.getTagNameSpec(&buf); | ||||
|
|
||||
| // Compare attributes. | ||||
| var e1_iter = e1.attributeIterator(); | ||||
| var e2_iter = e2.attributeIterator(); | ||||
| var iter1_count: usize = 0; | ||||
| var iter2_count: usize = 0; | ||||
|
|
||||
| while (e1_iter.next()) |attrib1| : (iter1_count += 1) { | ||||
| const attrib2 = e2_iter.next() orelse return false; | ||||
| iter2_count += 1; | ||||
|
|
||||
| if (attrib1._name.eql(attrib2._name) and attrib1._value.eql(attrib2._value)) { | ||||
| continue; | ||||
| } | ||||
|
|
||||
| return false; | ||||
| } | ||||
|
|
||||
| if (e1._namespace != e2._namespace or !std.mem.eql(u8, e1_tag, e2_tag) or iter1_count != iter2_count) { | ||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both more efficient and easier to read if you group these a little better. Check the tags names and namespaces where you get them, before iterating through all the attributes and comparing htem. |
||||
| return false; | ||||
| } | ||||
| }, | ||||
| .attribute => { | ||||
| const a1 = self.as(Element.Attribute); | ||||
| const a2 = other.as(Element.Attribute); | ||||
| return std.mem.eql(u8, a1.getName(), a2.getName()) and std.mem.eql(u8, a1.getValue(), a2.getValue()); | ||||
| }, | ||||
| .cdata => { | ||||
| const c1 = self.as(CData); | ||||
| const c2 = other.as(CData); | ||||
|
|
||||
| return std.mem.eql(u8, c1.getData(), c2.getData()); | ||||
| }, | ||||
| else => @panic("NIY"), | ||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||
| } | ||||
|
|
||||
| // `Node.childNodes` allocate memory, this seems like a better option. | ||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, childrenIterator is meant for internal iteration within the Zig code, specifically to avoid the overhead of childNodes necessary to fulfill the webapi of that type. |
||||
| var self_iter = self.childrenIterator(); | ||||
| var other_iter = other.childrenIterator(); | ||||
| var self_child_count: usize = 0; | ||||
| var other_child_count: usize = 0; | ||||
|
|
||||
| while (self_iter.next()) |self_node| : (self_child_count += 1) { | ||||
| const other_node = other_iter.next() orelse { | ||||
| // iter1 has node still but iter2 reached end. | ||||
| return false; | ||||
| }; | ||||
| // Increase 1 since not null. | ||||
| other_child_count += 1; | ||||
|
|
||||
| // We may investigate iterative approach if recursive version | ||||
| // causes stack issues for large nodes. | ||||
| if (!isEqualNode(self_node, other_node, page)) { | ||||
| return false; | ||||
| } | ||||
| } | ||||
|
|
||||
| return self_child_count == other_child_count; | ||||
| } | ||||
|
|
||||
| pub fn isInShadowTree(self: *Node) bool { | ||||
| var node = self._parent; | ||||
| while (node) |n| { | ||||
|
|
@@ -751,6 +826,7 @@ pub const JsApi = struct { | |||
| pub const cloneNode = bridge.function(Node.cloneNode, .{ .dom_exception = true }); | ||||
| pub const compareDocumentPosition = bridge.function(Node.compareDocumentPosition, .{}); | ||||
| pub const getRootNode = bridge.function(Node.getRootNode, .{}); | ||||
| pub const isEqualNode = bridge.function(Node.isEqualNode, .{}); | ||||
|
|
||||
| pub const toString = bridge.function(_toString, .{}); | ||||
| fn _toString(self: *const Node) []const u8 { | ||||
|
|
||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could push this logic into each type, e.g.