Only store unique nodes in XML::NodeSet.

It's called a "set" after all.
This commit is contained in:
Yorick Peterse 2014-08-17 22:03:44 +02:00
parent bb503728af
commit d1735750c1
2 changed files with 38 additions and 8 deletions

View File

@ -1,10 +1,10 @@
module Oga module Oga
module XML module XML
## ##
# The NodeSet class contains a set of {Oga::XML::Node} instances that can # The NodeSet class contains a set of unique {Oga::XML::Node} instances that
# be queried and modified. Optionally NodeSet instances can take ownership # can be queried and modified. Optionally NodeSet instances can take
# of a node (besides just containing it). This allows the nodes to query # ownership of a node (besides just containing it). This allows the nodes to
# their previous and next elements. # query their previous and next elements.
# #
# There are two types of sets: # There are two types of sets:
# #
@ -44,7 +44,7 @@ module Oga
# @param [Oga::XML::NodeSet] owner The owner of the set. # @param [Oga::XML::NodeSet] owner The owner of the set.
# #
def initialize(nodes = [], owner = nil) def initialize(nodes = [], owner = nil)
@nodes = nodes @nodes = nodes.uniq
@owner = owner @owner = owner
@nodes.each { |node| take_ownership(node) } @nodes.each { |node| take_ownership(node) }
@ -105,6 +105,8 @@ module Oga
# @param [Oga::XML::Node] node # @param [Oga::XML::Node] node
# #
def push(node) def push(node)
return if @nodes.include?(node)
@nodes << node @nodes << node
take_ownership(node) take_ownership(node)
@ -118,6 +120,8 @@ module Oga
# @param [Oga::XML::Node] node # @param [Oga::XML::Node] node
# #
def unshift(node) def unshift(node)
return if @nodes.include?(node)
@nodes.unshift(node) @nodes.unshift(node)
take_ownership(node) take_ownership(node)
@ -176,7 +180,7 @@ module Oga
# @return [Oga::XML::NodeSet] # @return [Oga::XML::NodeSet]
# #
def +(other) def +(other)
return self.class.new(to_a + other.to_a) return self.class.new(to_a | other.to_a)
end end
## ##

View File

@ -25,6 +25,13 @@ describe Oga::XML::NodeSet do
node.node_set.should == set node.node_set.should == set
end end
example 'only store unique nodes' do
n1 = Oga::XML::Element.new(:name => 'a')
set = described_class.new([n1, n1])
set.length.should == 1
end
end end
context '#each' do context '#each' do
@ -94,6 +101,15 @@ describe Oga::XML::NodeSet do
@set.length.should == 1 @set.length.should == 1
end end
example 'do not push a node that is already part of the set' do
element = Oga::XML::Element.new(:name => 'a')
@set.push(element)
@set.push(element)
@set.length.should == 1
end
example 'take ownership of a node if the set has an owner' do example 'take ownership of a node if the set has an owner' do
child = Oga::XML::Element.new child = Oga::XML::Element.new
@set.owner = Oga::XML::Element.new @set.owner = Oga::XML::Element.new
@ -106,8 +122,8 @@ describe Oga::XML::NodeSet do
context '#unshift' do context '#unshift' do
before do before do
n1 = Oga::XML::Element.new(:name => 'a') @n1 = Oga::XML::Element.new(:name => 'a')
@set = described_class.new([n1]) @set = described_class.new([@n1])
end end
example 'push a node at the beginning of the set' do example 'push a node at the beginning of the set' do
@ -118,6 +134,12 @@ describe Oga::XML::NodeSet do
@set.first.should == n2 @set.first.should == n2
end end
example 'do not push a node if it is already part of the set' do
@set.unshift(@n1)
@set.length.should == 1
end
example 'take ownership of a node if the set has an owner' do example 'take ownership of a node if the set has an owner' do
child = Oga::XML::Element.new child = Oga::XML::Element.new
@set.owner = Oga::XML::Element.new @set.owner = Oga::XML::Element.new
@ -207,6 +229,10 @@ describe Oga::XML::NodeSet do
example 'merge two sets together' do example 'merge two sets together' do
(@set1 + @set2).to_a.should == [@n1, @n2] (@set1 + @set2).to_a.should == [@n1, @n2]
end end
example 'ignore duplicate nodes' do
(@set1 + described_class.new([@n1])).length.should == 1
end
end end
context '#remove' do context '#remove' do