From 39f466a51d1aedd89c32eabc6ff8ee6ae41f5bed Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 15 Jan 2010 20:03:16 -0800 Subject: caching string conversions in the scalar scanner --- lib/psych/scalar_scanner.rb | 22 +++++++++++++--------- lib/psych/visitors/to_ruby.rb | 15 ++++++++------- lib/psych/visitors/yaml_tree.rb | 3 ++- 3 files changed, 23 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/psych/scalar_scanner.rb b/lib/psych/scalar_scanner.rb index aa00d37..3d10276 100644 --- a/lib/psych/scalar_scanner.rb +++ b/lib/psych/scalar_scanner.rb @@ -5,24 +5,26 @@ module Psych # Scan scalars for built in types class ScalarScanner # Taken from http://yaml.org/type/timestamp.html - TIME = /\d{4}-\d{1,2}-\d{1,2}([Tt]|\s+)\d{1,2}:\d\d:\d\d(\.\d*)?(\s*Z|[-+]\d{1,2}(:\d\d)?)?/ + TIME = /^\d{4}-\d{1,2}-\d{1,2}([Tt]|\s+)\d{1,2}:\d\d:\d\d(\.\d*)?(\s*Z|[-+]\d{1,2}(:\d\d)?)?/ - def initialize string - @string = string + def initialize + @string_cache = {} end - def tokenize - self.class.tokenize @string - end - - def self.tokenize string + def tokenize string return nil if string.empty? + return string if @string_cache.key?(string) case string when /^[A-Za-z~]/ - return string if string.length > 5 + if string.length > 5 + @string_cache[string] = true + return string + end + case string when /^[^ytonf~]/i + @string_cache[string] = true string when '~', /^null$/i nil @@ -31,6 +33,7 @@ module Psych when /^(no|false|off)$/i false else + @string_cache[string] = true string end when TIME @@ -77,6 +80,7 @@ module Psych else return Integer(string.gsub(/[,_]/, '')) rescue ArgumentError return Float(string.gsub(/[,_]/, '')) rescue ArgumentError + @string_cache[string] = true string end end diff --git a/lib/psych/visitors/to_ruby.rb b/lib/psych/visitors/to_ruby.rb index 9217ccc..6d6dae0 100644 --- a/lib/psych/visitors/to_ruby.rb +++ b/lib/psych/visitors/to_ruby.rb @@ -8,12 +8,13 @@ module Psych def initialize super @st = {} + @ss = ScalarScanner.new end def accept target result = super - return result if Psych.domain_types.empty? return result unless target.tag + return result if Psych.domain_types.empty? short_name = target.tag.sub(/^!/, '').split('/', 2).last if Psych.domain_types.key? short_name @@ -28,7 +29,7 @@ module Psych @st[o.anchor] = o.value if o.anchor return o.value if o.quoted - return ScalarScanner.tokenize(o.value) unless o.tag + return @ss.tokenize(o.value) unless o.tag case o.tag when '!binary', 'tag:yaml.org,2002:binary' @@ -40,7 +41,7 @@ module Psych when "!ruby/object:Rational" Rational(o.value) when "tag:yaml.org,2002:float", "!float" - Float(ScalarScanner.tokenize(o.value)) + Float(@ss.tokenize(o.value)) when "!ruby/regexp" o.value =~ /^\/(.*)\/([mix]*)$/ source = $1 @@ -62,7 +63,7 @@ module Psych args.push(args.delete_at(1) == '...') Range.new(*args) else - ScalarScanner.tokenize o.value + @ss.tokenize o.value end end @@ -89,7 +90,7 @@ module Psych members = Hash[*o.children.map { |c| accept c }] string = members.delete 'str' init_with(string, members.map { |k,v| [k.to_s.sub(/^@/, ''),v] }) - when /!ruby\/struct:?(.*)?$/ + when /^!ruby\/struct:?(.*)?$/ klass = resolve_class($1) if klass @@ -118,7 +119,7 @@ module Psych h = Hash[*o.children.map { |c| accept c }] Range.new(h['begin'], h['end'], h['excl']) - when /!ruby\/exception:?(.*)?$/ + when /^!ruby\/exception:?(.*)?$/ h = Hash[*o.children.map { |c| accept c }] e = build_exception((resolve_class($1) || Exception), @@ -142,7 +143,7 @@ module Psych h = Hash[*o.children.map { |c| accept c }] Rational(h['numerator'], h['denominator']) - when /!ruby\/object:?(.*)?$/ + when /^!ruby\/object:?(.*)?$/ name = $1 || 'Object' h = Hash[*o.children.map { |c| accept c }] s = name.split('::').inject(Object) { |k,sub| diff --git a/lib/psych/visitors/yaml_tree.rb b/lib/psych/visitors/yaml_tree.rb index 6b97799..8732200 100644 --- a/lib/psych/visitors/yaml_tree.rb +++ b/lib/psych/visitors/yaml_tree.rb @@ -9,6 +9,7 @@ module Psych @tree.children << Nodes::Document.new @stack = @tree.children.dup @st = {} + @ss = ScalarScanner.new @dispatch_cache = Hash.new do |h,klass| method = "visit_#{(klass.name || '').split('::').join('_')}" @@ -149,7 +150,7 @@ module Psych else str = o tag = nil - quote = !(String === ScalarScanner.new(o).tokenize) + quote = !(String === @ss.tokenize(o)) plain = !quote end -- cgit v1.2.3