Skip to content

Commit

Permalink
updated tests, fixed gc problem, and made locate not open up an element
Browse files Browse the repository at this point in the history
  • Loading branch information
ohler55 committed Sep 29, 2013
1 parent 5713afe commit 5e488ff
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 35 deletions.
5 changes: 3 additions & 2 deletions README.md
Expand Up @@ -34,10 +34,11 @@ A fast XML parser and Object marshaller as a Ruby gem.


## <a name="release">Release Notes</a> ## <a name="release">Release Notes</a>


### Release 2.0.9 ### Release 2.0.10


- Fixed bug that did not allow ISO-8859-1 characters and caused a crash. - Small fix to not create an empty element from a closed element when using locate().


- Fixed to keep objects from being garbages collected in Ruby 2.x.


## <a name="description">Description</a> ## <a name="description">Description</a>


Expand Down
1 change: 1 addition & 0 deletions ext/ox/extconf.rb
Expand Up @@ -30,6 +30,7 @@
'HAS_RSTRUCT' => ('ruby' == type || 'ree' == type) ? 1 : 0, 'HAS_RSTRUCT' => ('ruby' == type || 'ree' == type) ? 1 : 0,
'HAS_IVAR_HELPERS' => ('ruby' == type && ('1' == version[0] && '9' == version[1]) || '2' <= version[0]) ? 1 : 0, 'HAS_IVAR_HELPERS' => ('ruby' == type && ('1' == version[0] && '9' == version[1]) || '2' <= version[0]) ? 1 : 0,
'HAS_PROC_WITH_BLOCK' => ('ruby' == type && ('1' == version[0] && '9' == version[1]) || '2' <= version[0]) ? 1 : 0, 'HAS_PROC_WITH_BLOCK' => ('ruby' == type && ('1' == version[0] && '9' == version[1]) || '2' <= version[0]) ? 1 : 0,
'HAS_GC_GUARD' => ('jruby' != type && 'rubinius' != type) ? 1 : 0,
'HAS_TOP_LEVEL_ST_H' => ('ree' == type || ('ruby' == type && '1' == version[0] && '8' == version[1])) ? 1 : 0, 'HAS_TOP_LEVEL_ST_H' => ('ree' == type || ('ruby' == type && '1' == version[0] && '8' == version[1])) ? 1 : 0,
'NEEDS_UIO' => (RUBY_PLATFORM =~ /(win|w)32$/) ? 0 : 1, 'NEEDS_UIO' => (RUBY_PLATFORM =~ /(win|w)32$/) ? 0 : 1,
} }
Expand Down
3 changes: 3 additions & 0 deletions ext/ox/gen_load.c
Expand Up @@ -94,6 +94,9 @@ create_doc(PInfo pi) {


helper_stack_init(&pi->helpers); helper_stack_init(&pi->helpers);
doc = rb_obj_alloc(ox_document_clas); doc = rb_obj_alloc(ox_document_clas);
#if HAS_GC_GUARD
RB_GC_GUARD(doc);
#endif
nodes = rb_ary_new(); nodes = rb_ary_new();
rb_ivar_set(doc, ox_attributes_id, rb_hash_new()); rb_ivar_set(doc, ox_attributes_id, rb_hash_new());
rb_ivar_set(doc, ox_nodes_id, nodes); rb_ivar_set(doc, ox_nodes_id, nodes);
Expand Down
17 changes: 17 additions & 0 deletions ext/ox/ox.c
Expand Up @@ -402,10 +402,17 @@ to_obj(VALUE self, VALUE ruby_xml) {
xml = ALLOCA_N(char, len); xml = ALLOCA_N(char, len);
} }
memcpy(xml, x, len); memcpy(xml, x, len);
#if HAS_GC_GUARD
rb_gc_disable();
#endif
obj = ox_parse(xml, ox_obj_callbacks, 0, &options, &err); obj = ox_parse(xml, ox_obj_callbacks, 0, &options, &err);
if (SMALL_XML < len) { if (SMALL_XML < len) {
xfree(xml); xfree(xml);
} }
#if HAS_GC_GUARD
RB_GC_GUARD(obj);
rb_gc_enable();
#endif
if (err_has(&err)) { if (err_has(&err)) {
ox_err_raise(&err); ox_err_raise(&err);
} }
Expand Down Expand Up @@ -514,7 +521,14 @@ load(char *xml, int argc, VALUE *argv, VALUE self, VALUE encoding, Err err) {
xml = defuse_bom(xml, &options); xml = defuse_bom(xml, &options);
switch (options.mode) { switch (options.mode) {
case ObjMode: case ObjMode:
#if HAS_GC_GUARD
rb_gc_disable();
#endif
obj = ox_parse(xml, ox_obj_callbacks, 0, &options, err); obj = ox_parse(xml, ox_obj_callbacks, 0, &options, err);
#if HAS_GC_GUARD
RB_GC_GUARD(obj);
rb_gc_enable();
#endif
break; break;
case GenMode: case GenMode:
obj = ox_parse(xml, ox_gen_callbacks, 0, &options, err); obj = ox_parse(xml, ox_gen_callbacks, 0, &options, err);
Expand Down Expand Up @@ -971,5 +985,8 @@ _ox_raise_error(const char *msg, const char *xml, const char *current, const cha
xline++; xline++;
} }
} }
#if HAS_GC_GUARD
rb_gc_enable();
#endif
rb_raise(ox_parse_error_class, "%s at line %d, column %d [%s:%d]\n", msg, xline, col, file, line); rb_raise(ox_parse_error_class, "%s at line %d, column %d [%s:%d]\n", msg, xline, col, file, line);
} }
4 changes: 2 additions & 2 deletions lib/ox/element.rb
Expand Up @@ -49,16 +49,16 @@ def initialize(name)
# Element. # Element.
# @return [Array] all child Nodes. # @return [Array] all child Nodes.
def nodes def nodes
@nodes = [] if !instance_variable_defined?(:@nodes) or @nodes.nil? return [] if !instance_variable_defined?(:@nodes) or @nodes.nil?
@nodes @nodes
end end


# Appends a Node to the Element's nodes array. Returns the element itself # Appends a Node to the Element's nodes array. Returns the element itself
# so multiple appends can be chained together. # so multiple appends can be chained together.
# @param [Node] node Node to append to the nodes array # @param [Node] node Node to append to the nodes array
def <<(node) def <<(node)
@nodes = [] if !instance_variable_defined?(:@nodes) or @nodes.nil?
raise "argument to << must be a String or Ox::Node." unless node.is_a?(String) or node.is_a?(Node) raise "argument to << must be a String or Ox::Node." unless node.is_a?(String) or node.is_a?(Node)
@nodes = [] if !instance_variable_defined?(:@nodes) or @nodes.nil?
@nodes << node @nodes << node
self self
end end
Expand Down
2 changes: 1 addition & 1 deletion lib/ox/version.rb
@@ -1,5 +1,5 @@


module Ox module Ox
# Current version of the module. # Current version of the module.
VERSION = '2.0.9' VERSION = '2.0.10'
end end
42 changes: 25 additions & 17 deletions test/perf_gen.rb
Expand Up @@ -86,28 +86,32 @@
if do_load if do_load
perf = Perf.new() perf = Perf.new()
perf.add('Ox', 'parse') { Ox.parse(xml) } perf.add('Ox', 'parse') { Ox.parse(xml) }
perf.add('Nokogiri', 'parse') { Nokogiri::XML::Document.parse(xml) } perf.add('Nokogiri', 'parse') { Nokogiri::XML::Document.parse(xml) } unless defined?(::Nokogiri).nil?
perf.add('LibXML', 'parse') { LibXML::XML::Document.string(xml) } perf.add('LibXML', 'parse') { LibXML::XML::Document.string(xml) } unless defined?(::LibXML).nil?
perf.run($iter) perf.run($iter)
end end


if do_dump if do_dump
perf = Perf.new() perf = Perf.new()
perf.add('Ox', 'dump') { Ox.dump($obj, :indent => 2) } perf.add('Ox', 'dump') { Ox.dump($obj, :indent => 2) }
perf.before('Ox') { $obj = d[:ox] } perf.before('Ox') { $obj = d[:ox] }
perf.add('Nokogiri', 'dump') { $obj.to_xml(:indent => 2) } unless defined?(::Nokogiri).nil?
perf.before('Nokogiri') { $obj = d[:nokogiri] } perf.add('Nokogiri', 'dump') { $obj.to_xml(:indent => 2) }
perf.add('LibXML', 'dump') { $obj.to_s() } perf.before('Nokogiri') { $obj = d[:nokogiri] }
perf.before('LibXML') { $obj = d[:libxml] } end
unless defined?(::LibXML).nil?
perf.add('LibXML', 'dump') { $obj.to_s() }
perf.before('LibXML') { $obj = d[:libxml] }
end
perf.run($iter) perf.run($iter)
end end


if do_read if do_read
$filename = d[:file] $filename = d[:file]
perf = Perf.new() perf = Perf.new()
perf.add('Ox', 'load_file') { Ox.load_file($filename, :mode => :generic) } perf.add('Ox', 'load_file') { Ox.load_file($filename, :mode => :generic) }
perf.add('Nokogiri', 'parse') { Nokogiri::XML::Document.parse(File.open($filename)) } perf.add('Nokogiri', 'parse') { Nokogiri::XML::Document.parse(File.open($filename)) } unless defined?(::Nokogiri).nil?
perf.add('LibXML', 'parse') { LibXML::XML::Document.file($filename) } perf.add('LibXML', 'parse') { LibXML::XML::Document.file($filename) } unless defined?(::LibXML).nil?
perf.run($iter) perf.run($iter)
end end


Expand All @@ -116,16 +120,20 @@
perf = Perf.new() perf = Perf.new()
perf.add('Ox', 'to_file') { Ox.to_file($filename, $obj, :indent => 0) } perf.add('Ox', 'to_file') { Ox.to_file($filename, $obj, :indent => 0) }
perf.before('Ox') { $obj = d[:ox] } perf.before('Ox') { $obj = d[:ox] }
perf.add('Nokogiri', 'dump') { unless defined?(::Nokogiri).nil?
xml = $obj.to_xml(:indent => 0) perf.add('Nokogiri', 'dump') {
File.open($filename, "w") { |f| f.write(xml) } xml = $obj.to_xml(:indent => 0)
} File.open($filename, "w") { |f| f.write(xml) }
}
end
perf.before('Nokogiri') { $obj = d[:nokogiri] } perf.before('Nokogiri') { $obj = d[:nokogiri] }
perf.add('LibXML', 'dump') { unless defined?(::LibXML).nil?
xml = $obj.to_s() perf.add('LibXML', 'dump') {
File.open($filename, "w") { |f| f.write(xml) } xml = $obj.to_s()
} File.open($filename, "w") { |f| f.write(xml) }
perf.before('LibXML') { $obj = d[:libxml] } }
perf.before('LibXML') { $obj = d[:libxml] }
end
perf.run($iter) perf.run($iter)
end end


Expand Down
28 changes: 15 additions & 13 deletions test/perf_obj.rb
Expand Up @@ -13,10 +13,13 @@


require 'optparse' require 'optparse'
require 'ox' require 'ox'
require 'oj'
require 'perf' require 'perf'
require 'sample' require 'sample'
require 'files' require 'files'
begin
require 'oj'
rescue Exception
end


$circular = false $circular = false
$indent = 0 $indent = 0
Expand Down Expand Up @@ -64,29 +67,30 @@
$obj = do_sample ? sample_doc(2) : files('..') $obj = do_sample ? sample_doc(2) : files('..')
$mars = Marshal.dump($obj) $mars = Marshal.dump($obj)
$xml = Ox.dump($obj, :indent => $indent, :circular => $circular) $xml = Ox.dump($obj, :indent => $indent, :circular => $circular)
$json = Oj.dump($obj, :indent => $indent, :circular => $circular)
File.open('sample.xml', 'w') { |f| f.write($xml) } File.open('sample.xml', 'w') { |f| f.write($xml) }
File.open('sample.json', 'w') { |f| f.write($json) }
File.open('sample.marshal', 'w') { |f| f.write($mars) } File.open('sample.marshal', 'w') { |f| f.write($mars) }
unless defined?(::Oj).nil?
$json = Oj.dump($obj, :indent => $indent, :circular => $circular)
File.open('sample.json', 'w') { |f| f.write($json) }
end
else else
puts "loading and parsing #{files}\n\n" puts "loading and parsing #{files}\n\n"
# TBD change to allow xml and json files.map do |f|
data = files.map do |f|
$xml = File.read(f) $xml = File.read(f)
$obj = Ox.load($xml); $obj = Ox.load($xml);
$mars = Marshal.dump($obj) $mars = Marshal.dump($obj)
$json = Oj.dump($obj, :indent => $indent, :circular => $circular) $json = Oj.dump($obj, :indent => $indent, :circular => $circular) unless defined?(::Oj).nil?
end end
end end


Oj.default_options = { :mode => :object, :indent => $indent } Oj.default_options = { :mode => :object, :indent => $indent } unless defined?(::Oj).nil?


if do_load if do_load
puts '-' * 80 puts '-' * 80
puts "Load Performance" puts "Load Performance"
perf = Perf.new() perf = Perf.new()
perf.add('Ox', 'load') { Ox.load($xml, :mode => :object) } perf.add('Ox', 'load') { Ox.load($xml, :mode => :object) }
perf.add('Oj', 'load') { Oj.load($json) } perf.add('Oj', 'load') { Oj.load($json) } unless defined?(::Oj).nil?
perf.add('Marshal', 'load') { Marshal.load($mars) } perf.add('Marshal', 'load') { Marshal.load($mars) }
perf.run($iter) perf.run($iter)
end end
Expand All @@ -96,7 +100,7 @@
puts "Dump Performance" puts "Dump Performance"
perf = Perf.new() perf = Perf.new()
perf.add('Ox', 'dump') { Ox.dump($obj, :indent => $indent, :circular => $circular) } perf.add('Ox', 'dump') { Ox.dump($obj, :indent => $indent, :circular => $circular) }
perf.add('Oj', 'dump') { Oj.dump($obj) } perf.add('Oj', 'dump') { Oj.dump($obj) } unless defined?(::Oj).nil?
perf.add('Marshal', 'dump') { Marshal.dump($obj) } perf.add('Marshal', 'dump') { Marshal.dump($obj) }
perf.run($iter) perf.run($iter)
end end
Expand All @@ -106,7 +110,7 @@
puts "Read from file Performance" puts "Read from file Performance"
perf = Perf.new() perf = Perf.new()
perf.add('Ox', 'load_file') { Ox.load_file('sample.xml', :mode => :object) } perf.add('Ox', 'load_file') { Ox.load_file('sample.xml', :mode => :object) }
perf.add('Oj', 'load') { Oj.load_file('sample.json') } perf.add('Oj', 'load') { Oj.load_file('sample.json') } unless defined?(::Oj).nil?
perf.add('Marshal', 'load') { Marshal.load(File.new('sample.marshal')) } perf.add('Marshal', 'load') { Marshal.load(File.new('sample.marshal')) }
perf.run($iter) perf.run($iter)
end end
Expand All @@ -116,9 +120,7 @@
puts "Write to file Performance" puts "Write to file Performance"
perf = Perf.new() perf = Perf.new()
perf.add('Ox', 'to_file') { Ox.to_file('sample.xml', $obj, :indent => $indent, :circular => $circular) } perf.add('Ox', 'to_file') { Ox.to_file('sample.xml', $obj, :indent => $indent, :circular => $circular) }
perf.add('Oj', 'to_file') { Oj.to_file('sample.json', $obj) } perf.add('Oj', 'to_file') { Oj.to_file('sample.json', $obj) } unless defined?(::Oj).nil?
perf.add('Marshal', 'dump') { Marshal.dump($obj, File.new('sample.marshal', 'w')) } perf.add('Marshal', 'dump') { Marshal.dump($obj, File.new('sample.marshal', 'w')) }
perf.run($iter) perf.run($iter)
end end


0 comments on commit 5e488ff

Please sign in to comment.