Class: Psych::ScalarScanner
Overview
Scan scalars for built in types
Constant Summary collapse
- TIME =
Taken from yaml.org/type/timestamp.html
/^-?\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)?))?$/
- FLOAT =
Taken from yaml.org/type/float.html
/^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10) |[-+]?[0-9][0-9_,]*(:[0-5]?[0-9])+\.[0-9_]*(?# base 60) |[-+]?\.(inf|Inf|INF)(?# infinity) |\.(nan|NaN|NAN)(?# not a number))$/x
- INTEGER =
Taken from yaml.org/type/int.html
/^(?:[-+]?0b[0-1_]+ (?# base 2) |[-+]?0[0-7_]+ (?# base 8) |[-+]?(?:0|[1-9][0-9_]*) (?# base 10) |[-+]?0x[0-9a-fA-F_]+ (?# base 16))$/x
Instance Attribute Summary collapse
-
#class_loader ⇒ Object
readonly
Returns the value of attribute class_loader.
Instance Method Summary collapse
-
#initialize(class_loader) ⇒ ScalarScanner
constructor
Create a new scanner.
-
#parse_int(string) ⇒ Object
Parse and return an int from
string
. -
#parse_time(string) ⇒ Object
Parse and return a Time from
string
. -
#tokenize(string) ⇒ Object
Tokenize
string
returning the Ruby object.
Constructor Details
#initialize(class_loader) ⇒ ScalarScanner
Create a new scanner
25 26 27 28 29 |
# File 'lib/psych/scalar_scanner.rb', line 25 def initialize class_loader @string_cache = {} @symbol_cache = {} @class_loader = class_loader end |
Instance Attribute Details
#class_loader ⇒ Object (readonly)
Returns the value of attribute class_loader
22 23 24 |
# File 'lib/psych/scalar_scanner.rb', line 22 def class_loader @class_loader end |
Instance Method Details
#parse_int(string) ⇒ Object
Parse and return an int from string
115 116 117 118 |
# File 'lib/psych/scalar_scanner.rb', line 115 def parse_int string return unless INTEGER === string Integer(string) end |
#parse_time(string) ⇒ Object
Parse and return a Time from string
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/psych/scalar_scanner.rb', line 122 def parse_time string klass = class_loader.load 'Time' date, time = *(string.split(/[ tT]/, 2)) (yy, m, dd) = date.match(/^(-?\d{4})-(\d{1,2})-(\d{1,2})/).captures.map { |x| x.to_i } md = time.match(/(\d+:\d+:\d+)(?:\.(\d*))?\s*(Z|[-+]\d+(:\d\d)?)?/) (hh, mm, ss) = md[1].split(':').map { |x| x.to_i } us = (md[2] ? Rational("0.#{md[2]}") : 0) * 1000000 time = klass.utc(yy, m, dd, hh, mm, ss, us) return time if 'Z' == md[3] return klass.at(time.to_i, us) unless md[3] tz = md[3].match(/^([+\-]?\d{1,2})\:?(\d{1,2})?$/)[1..-1].compact.map { |digit| Integer(digit, 10) } offset = tz.first * 3600 if offset < 0 offset -= ((tz[1] || 0) * 60) else offset += ((tz[1] || 0) * 60) end klass.at((time - offset).to_i, us) end |
#tokenize(string) ⇒ Object
Tokenize string
returning the Ruby object
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/psych/scalar_scanner.rb', line 32 def tokenize string return nil if string.empty? return string if @string_cache.key?(string) return @symbol_cache[string] if @symbol_cache.key?(string) case string # Check for a String type, being careful not to get caught by hash keys, hex values, and # special floats (e.g., -.inf). when /^[^\d\.:-]?[A-Za-z_\s!@#\$%\^&\*\(\)\{\}\<\>\|\/\\~;=]+/, /\n/ 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 when /^(yes|true|on)$/i true when /^(no|false|off)$/i false else @string_cache[string] = true string end when TIME begin parse_time string rescue ArgumentError string end when /^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/ require 'date' begin class_loader.date.strptime(string, '%Y-%m-%d') rescue ArgumentError string end when /^\.inf$/i Float::INFINITY when /^-\.inf$/i -Float::INFINITY when /^\.nan$/i Float::NAN when /^:./ if string =~ /^:(["'])(.*)\1/ @symbol_cache[string] = class_loader.symbolize($2.sub(/^:/, '')) else @symbol_cache[string] = class_loader.symbolize(string.sub(/^:/, '')) end when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+$/ i = 0 string.split(':').each_with_index do |n,e| i += (n.to_i * 60 ** (e - 2).abs) end i when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]*$/ i = 0 string.split(':').each_with_index do |n,e| i += (n.to_f * 60 ** (e - 2).abs) end i when FLOAT if string =~ /\A[-+]?\.\Z/ @string_cache[string] = true string else Float(string.gsub(/[,_]|\.$/, '')) end else int = parse_int string.gsub(/[,_]/, '') return int if int @string_cache[string] = true string end end |