In Files

  • psych/lib/psych/scalar_scanner.rb

Psych::ScalarScanner

Scan scalars for built in types

Attributes

class_loader[R]

Public Class Methods

new(class_loader) click to toggle source

Create a new scanner

 
               # File psych/lib/psych/scalar_scanner.rb, line 25
def initialize class_loader
  @string_cache = {}
  @symbol_cache = {}
  @class_loader = class_loader
end
            

Public Instance Methods

parse_int(string) click to toggle source

Parse and return an int from string

 
               # File psych/lib/psych/scalar_scanner.rb, line 115
def parse_int string
  return unless INTEGER === string
  Integer(string)
end
            
parse_time(string) click to toggle source

Parse and return a Time from string

 
               # File psych/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) click to toggle source

Tokenize string returning the Ruby object

 
               # File psych/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!@#\$%\^&\*\(\)\{\}\<\>\|\/\~;=]+/
    if string.length > 5
      @string_cache[string] = true
      return string
    end

    case string
    when /^[^ytonf~]/
      @string_cache[string] = true
      string
    when '~', /^null$/
      nil
    when /^(yes|true|on)$/
      true
    when /^(no|false|off)$/
      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$/
    Float::INFINITY
  when /^-\.inf$/
    -Float::INFINITY
  when /^\.nan$/
    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
            

Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.

If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.

If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.

If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.

blog comments powered by Disqus