diff options
Diffstat (limited to 'lib/yaml')
| -rw-r--r-- | lib/yaml/baseemitter.rb | 241 | ||||
| -rw-r--r-- | lib/yaml/basenode.rb | 216 | ||||
| -rw-r--r-- | lib/yaml/constants.rb | 45 | ||||
| -rw-r--r-- | lib/yaml/dbm.rb | 220 | ||||
| -rw-r--r-- | lib/yaml/emitter.rb | 107 | ||||
| -rw-r--r-- | lib/yaml/encoding.rb | 29 | ||||
| -rw-r--r-- | lib/yaml/error.rb | 33 | ||||
| -rw-r--r-- | lib/yaml/loader.rb | 14 | ||||
| -rw-r--r-- | lib/yaml/rubytypes.rb | 505 | ||||
| -rw-r--r-- | lib/yaml/store.rb | 157 | ||||
| -rw-r--r-- | lib/yaml/stream.rb | 44 | ||||
| -rw-r--r-- | lib/yaml/stringio.rb | 83 | ||||
| -rw-r--r-- | lib/yaml/syck.rb | 27 | ||||
| -rw-r--r-- | lib/yaml/types.rb | 196 | ||||
| -rw-r--r-- | lib/yaml/yaml.gemspec | 30 | ||||
| -rw-r--r-- | lib/yaml/yamlnode.rb | 54 | ||||
| -rw-r--r-- | lib/yaml/ypath.rb | 52 |
17 files changed, 322 insertions, 1731 deletions
diff --git a/lib/yaml/baseemitter.rb b/lib/yaml/baseemitter.rb deleted file mode 100644 index 007ee7be5e..0000000000 --- a/lib/yaml/baseemitter.rb +++ /dev/null @@ -1,241 +0,0 @@ -# -# BaseEmitter -# - -require 'yaml/constants' -require 'yaml/encoding' -require 'yaml/error' - -module YAML - - module BaseEmitter - - def options( opt = nil ) - if opt - @options[opt] || YAML::DEFAULTS[opt] - else - @options - end - end - - def options=( opt ) - @options = opt - end - - # - # Emit binary data - # - def binary_base64( value ) - self << "!binary " - self.node_text( [value].pack("m"), '|' ) - end - - # - # Emit plain, normal flowing text - # - def node_text( value, block = '>' ) - @seq_map = false - valx = value.dup - if options(:UseBlock) - block = '|' - elsif not options(:UseFold) and valx =~ /\n[ \t]/ and not valx =~ /#{YAML::ESCAPE_CHAR}/ - block = '|' - end - str = block.dup - if valx =~ /\n\Z\n/ - str << "+" - elsif valx =~ /\Z\n/ - else - str << "-" - end - if valx =~ /#{YAML::ESCAPE_CHAR}/ - valx = YAML::escape( valx ) - end - if valx =~ /\A[ \t#]/ - str << options(:Indent).to_s - end - if block == '>' - valx = fold( valx ) - end - self << str + indent_text( valx ) + "\n" - end - - # - # Emit a simple, unqouted string - # - def simple( value ) - @seq_map = false - self << value.to_s - end - - # - # Emit double-quoted string - # - def double( value ) - "\"#{YAML.escape( value )}\"" - end - - # - # Emit single-quoted string - # - def single( value ) - "'#{value}'" - end - - # - # Write a text block with the current indent - # - def indent_text( text ) - return "" if text.to_s.empty? - spacing = " " * ( level * options(:Indent) ) - return "\n" + text.gsub( /^([^\n])/, "#{spacing}\\1" ) - end - - # - # Write a current indent - # - def indent - #p [ self.id, @level, :INDENT ] - return " " * ( level * options(:Indent) ) - end - - # - # Add indent to the buffer - # - def indent! - self << indent - end - - # - # Folding paragraphs within a column - # - def fold( value ) - value.gsub!( /\A\n+/, '' ) - folded = $&.to_s - width = (0..options(:BestWidth)) - while not value.empty? - last = value.index( /(\n+)/ ) - chop_s = false - if width.include?( last ) - last += $1.length - 1 - elsif width.include?( value.length ) - last = value.length - else - last = value.rindex( /[ \t]/, options(:BestWidth) ) - chop_s = true - end - folded += value.slice!( 0, width.include?( last ) ? last + 1 : options(:BestWidth) ) - folded.chop! if chop_s - folded += "\n" unless value.empty? - end - folded - end - - # - # Quick mapping - # - def map( type, &e ) - val = Mapping.new - e.call( val ) - self << "#{type} " if type.length.nonzero? - - # - # Empty hashes - # - if val.length.zero? - self << "{}" - @seq_map = false - else - # FIXME - # if @buffer.length == 1 and options(:UseHeader) == false and type.length.zero? - # @headless = 1 - # end - - defkey = @options.delete( :DefaultKey ) - if defkey - seq_map_shortcut - self << "= : " - defkey.to_yaml( :Emitter => self ) - end - - # - # Emit the key and value - # - val.each { |v| - seq_map_shortcut - if v[0].is_complex_yaml? - self << "? " - end - v[0].to_yaml( :Emitter => self ) - if v[0].is_complex_yaml? - self << "\n" - indent! - end - self << ": " - v[1].to_yaml( :Emitter => self ) - } - end - end - - def seq_map_shortcut - # FIXME: seq_map needs to work with the new anchoring system - # if @seq_map - # @anchor_extras[@buffer.length - 1] = "\n" + indent - # @seq_map = false - # else - self << "\n" - indent! - # end - end - - # - # Quick sequence - # - def seq( type, &e ) - @seq_map = false - val = Sequence.new - e.call( val ) - self << "#{type} " if type.length.nonzero? - - # - # Empty arrays - # - if val.length.zero? - self << "[]" - else - # FIXME - # if @buffer.length == 1 and options(:UseHeader) == false and type.length.zero? - # @headless = 1 - # end - - # - # Emit the key and value - # - val.each { |v| - self << "\n" - indent! - self << "- " - @seq_map = true if v.class == Hash - v.to_yaml( :Emitter => self ) - } - end - end - - end - - # - # Emitter helper classes - # - class Mapping < Array - def add( k, v ) - push [k, v] - end - end - - class Sequence < Array - def add( v ) - push v - end - end - -end diff --git a/lib/yaml/basenode.rb b/lib/yaml/basenode.rb deleted file mode 100644 index e88a76f3d2..0000000000 --- a/lib/yaml/basenode.rb +++ /dev/null @@ -1,216 +0,0 @@ -# -# YAML::BaseNode class -# -require 'yaml/ypath' - -module YAML - - # - # YAML Generic Model container - # - module BaseNode - - # - # Search for YPath entry and return - # qualified nodes. - # - def select( ypath_str ) - matches = match_path( ypath_str ) - - # - # Create a new generic view of the elements selected - # - if matches - result = [] - matches.each { |m| - result.push m.last - } - self.class.new( 'seq', result ) - end - end - - # - # Search for YPath entry and return - # transformed nodes. - # - def select!( ypath_str ) - matches = match_path( ypath_str ) - - # - # Create a new generic view of the elements selected - # - if matches - result = [] - matches.each { |m| - result.push m.last.transform - } - result - end - end - - # - # Search for YPath entry and return a list of - # qualified paths. - # - def search( ypath_str ) - matches = match_path( ypath_str ) - - if matches - matches.collect { |m| - path = [] - m.each_index { |i| - path.push m[i] if ( i % 2 ).zero? - } - "/" + path.compact.join( "/" ) - } - end - end - - def at( seg ) - if Hash === @value and @value.has_key?( seg ) - @value[seg][1] - elsif Array === @value and seg =~ /\A\d+\Z/ and @value[seg.to_i] - @value[seg.to_i] - end - end - - # - # YPath search returning a complete depth array - # - def match_path( ypath_str ) - depth = 0 - matches = [] - YPath.each_path( ypath_str ) do |ypath| - seg = match_segment( ypath, 0 ) - matches += seg if seg - end - matches.uniq - end - - # - # Search a node for a single YPath segment - # - def match_segment( ypath, depth ) - deep_nodes = [] - seg = ypath.segments[ depth ] - if seg == "/" - unless String === @value - idx = -1 - @value.collect { |v| - idx += 1 - if Hash === @value - match_init = [v[0], v[1][1]] - match_deep = v[1][1].match_segment( ypath, depth ) - else - match_init = [idx, v] - match_deep = v.match_segment( ypath, depth ) - end - if match_deep - match_deep.each { |m| - deep_nodes.push( match_init + m ) - } - end - } - end - depth += 1 - seg = ypath.segments[ depth ] - end - match_nodes = - case seg - when "." - [[nil, self]] - when ".." - [["..", nil]] - when "*" - if @value.is_a? Enumerable - idx = -1 - @value.collect { |h| - idx += 1 - if Hash === @value - [h[0], h[1][1]] - else - [idx, h] - end - } - end - else - if seg =~ /^"(.*)"$/ - seg = $1 - elsif seg =~ /^'(.*)'$/ - seg = $1 - end - if ( v = at( seg ) ) - [[ seg, v ]] - end - end - return deep_nodes unless match_nodes - pred = ypath.predicates[ depth ] - if pred - case pred - when /^\.=/ - pred = $' - match_nodes.reject! { |n| - n.last.value != pred - } - else - match_nodes.reject! { |n| - n.last.at( pred ).nil? - } - end - end - return match_nodes + deep_nodes unless ypath.segments.length > depth + 1 - - #puts "DEPTH: #{depth + 1}" - deep_nodes = [] - match_nodes.each { |n| - if n[1].is_a? BaseNode - match_deep = n[1].match_segment( ypath, depth + 1 ) - if match_deep - match_deep.each { |m| - deep_nodes.push( n + m ) - } - end - else - deep_nodes = [] - end - } - deep_nodes = nil if deep_nodes.length == 0 - deep_nodes - end - - # - # We want the node to act like as Hash - # if it is. - # - def []( *k ) - if Hash === @value - v = @value.[]( *k ) - v[1] if v - elsif Array === @value - @value.[]( *k ) - end - end - - def children - if Hash === @value - @value.values.collect { |c| c[1] } - elsif Array === @value - @value - end - end - - def children_with_index - if Hash === @value - @value.keys.collect { |i| [self[i], i] } - elsif Array === @value - i = -1; @value.collect { |v| i += 1; [v, i] } - end - end - - def emit - transform.to_yaml - end - end - -end - diff --git a/lib/yaml/constants.rb b/lib/yaml/constants.rb deleted file mode 100644 index fb833d3077..0000000000 --- a/lib/yaml/constants.rb +++ /dev/null @@ -1,45 +0,0 @@ -# -# Constants used throughout the library -# -module YAML - - # - # Constants - # - VERSION = '0.60' - SUPPORTED_YAML_VERSIONS = ['1.0'] - - # - # Parser tokens - # - WORD_CHAR = 'A-Za-z0-9' - PRINTABLE_CHAR = '-_A-Za-z0-9!?/()$\'". ' - NOT_PLAIN_CHAR = '\x7f\x0-\x1f\x80-\x9f' - ESCAPE_CHAR = '[\\x00-\\x09\\x0b-\\x1f]' - INDICATOR_CHAR = '*&!|\\\\^@%{}[]=' - SPACE_INDICATORS = '-#:,?' - RESTRICTED_INDICATORS = '#:,}]' - DNS_COMP_RE = "\\w(?:[-\\w]*\\w)?" - DNS_NAME_RE = "(?:(?:#{DNS_COMP_RE}\\.)+#{DNS_COMP_RE}|#{DNS_COMP_RE})" - ESCAPES = %w{\x00 \x01 \x02 \x03 \x04 \x05 \x06 \a - \x08 \t \n \v \f \r \x0e \x0f - \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 - \x18 \x19 \x1a \e \x1c \x1d \x1e \x1f - } - UNESCAPES = { - 'a' => "\x07", 'b' => "\x08", 't' => "\x09", - 'n' => "\x0a", 'v' => "\x0b", 'f' => "\x0c", - 'r' => "\x0d", 'e' => "\x1b", '\\' => '\\', - } - - # - # Default settings - # - DEFAULTS = { - :Indent => 2, :UseHeader => false, :UseVersion => false, :Version => '1.0', - :SortKeys => false, :AnchorFormat => 'id%03d', :ExplicitTypes => false, - :WidthType => 'absolute', :BestWidth => 80, - :UseBlock => false, :UseFold => false, :Encoding => :None - } - -end diff --git a/lib/yaml/dbm.rb b/lib/yaml/dbm.rb index 87d6009250..a3cbaeccf6 100644 --- a/lib/yaml/dbm.rb +++ b/lib/yaml/dbm.rb @@ -1,23 +1,71 @@ +# frozen_string_literal: false require 'yaml' -require 'dbm' -# -# YAML + DBM = YDBM -# - Same interface as DBM class -# + +begin + require 'dbm' +rescue LoadError +end + module YAML +# YAML + DBM = YDBM +# +# YAML::DBM provides the same interface as ::DBM. +# +# However, while DBM only allows strings for both keys and values, +# this library allows one to use most Ruby objects for values +# by first converting them to YAML. Keys must be strings. +# +# Conversion to and from YAML is performed automatically. +# +# See the documentation for ::DBM and ::YAML for more information. class DBM < ::DBM - VERSION = "0.1" + + # :call-seq: + # ydbm[key] -> value + # + # Return value associated with +key+ from database. + # + # Returns +nil+ if there is no such +key+. + # + # See #fetch for more information. def []( key ) fetch( key ) end + + # :call-seq: + # ydbm[key] = value + # + # Set +key+ to +value+ in database. + # + # +value+ will be converted to YAML before storage. + # + # See #store for more information. def []=( key, val ) store( key, val ) end + + # :call-seq: + # ydbm.fetch( key, ifnone = nil ) + # ydbm.fetch( key ) { |key| ... } + # + # Return value associated with +key+. + # + # If there is no value for +key+ and no block is given, returns +ifnone+. + # + # Otherwise, calls block passing in the given +key+. + # + # See ::DBM#fetch for more information. def fetch( keystr, ifnone = nil ) begin val = super( keystr ) - return YAML::load( val ) if String === val + if String === val + if YAML.respond_to?(:safe_load) + return YAML.safe_load( val ) + else + return YAML.load( val ) + end + end rescue IndexError end if block_given? @@ -26,58 +74,163 @@ class DBM < ::DBM ifnone end end + + # Deprecated, used YAML::DBM#key instead. + # ---- + # Note: + # YAML::DBM#index makes warning from internal of ::DBM#index. + # It says 'DBM#index is deprecated; use DBM#key', but DBM#key + # behaves not same as DBM#index. + # def index( keystr ) super( keystr.to_yaml ) end + + # :call-seq: + # ydbm.key(value) -> string + # + # Returns the key for the specified value. + def key( keystr ) + invert[keystr] + end + + # :call-seq: + # ydbm.values_at(*keys) + # + # Returns an array containing the values associated with the given keys. def values_at( *keys ) keys.collect { |k| fetch( k ) } end + + # :call-seq: + # ydbm.delete(key) + # + # Deletes value from database associated with +key+. + # + # Returns value or +nil+. def delete( key ) v = super( key ) if String === v - v = YAML::load( v ) + if YAML.respond_to?(:safe_load) + v = YAML.safe_load( v ) + else + v = YAML.load( v ) + end end v end - def delete_if + + # :call-seq: + # ydbm.delete_if { |key, value| ... } + # + # Calls the given block once for each +key+, +value+ pair in the database. + # Deletes all entries for which the block returns true. + # + # Returns +self+. + def delete_if # :yields: [key, value] del_keys = keys.dup del_keys.delete_if { |k| yield( k, fetch( k ) ) == false } - del_keys.each { |k| delete( k ) } + del_keys.each { |k| delete( k ) } self end + + # :call-seq: + # ydbm.reject { |key, value| ... } + # + # Converts the contents of the database to an in-memory Hash, then calls + # Hash#reject with the specified code block, returning a new Hash. def reject hsh = self.to_hash hsh.reject { |k,v| yield k, v } end - def each_pair + + # :call-seq: + # ydbm.each_pair { |key, value| ... } + # + # Calls the given block once for each +key+, +value+ pair in the database. + # + # Returns +self+. + def each_pair # :yields: [key, value] keys.each { |k| yield k, fetch( k ) } self end - def each_value - super { |v| yield YAML::load( v ) } + + # :call-seq: + # ydbm.each_value { |value| ... } + # + # Calls the given block for each value in database. + # + # Returns +self+. + def each_value # :yields: value + super { |v| yield YAML.respond_to?(:safe_load) ? YAML.safe_load( v ) : YAML.load( v ) } self end + + # :call-seq: + # ydbm.values + # + # Returns an array of values from the database. def values - super.collect { |v| YAML::load( v ) } + super.collect { |v| YAML.respond_to?(:safe_load) ? YAML.safe_load( v ) : YAML.load( v ) } end + + # :call-seq: + # ydbm.has_value?(value) + # + # Returns true if specified +value+ is found in the database. def has_value?( val ) each_value { |v| return true if v == val } return false end + + # :call-seq: + # ydbm.invert -> hash + # + # Returns a Hash (not a DBM database) created by using each value in the + # database as a key, with the corresponding key as its value. + # + # Note that all values in the hash will be Strings, but the keys will be + # actual objects. def invert h = {} keys.each { |k| h[ self.fetch( k ) ] = k } h end + + # :call-seq: + # ydbm.replace(hash) -> ydbm + # + # Replaces the contents of the database with the contents of the specified + # object. Takes any object which implements the each_pair method, including + # Hash and DBM objects. def replace( hsh ) clear update( hsh ) end + + # :call-seq: + # ydbm.shift -> [key, value] + # + # Removes a [key, value] pair from the database, and returns it. + # If the database is empty, returns +nil+. + # + # The order in which values are removed/returned is not guaranteed. def shift a = super - a[1] = YAML::load( a[1] ) if a + if a + a[1] = YAML.respond_to?(:safe_load) ? YAML.safe_load( a[1] ) : YAML.load( a[1] ) + end a end + + # :call-seq: + # ydbm.select { |key, value| ... } + # ydbm.select(*keys) + # + # If a block is provided, returns a new array containing [key, value] pairs + # for which the block returns true. + # + # Otherwise, same as #values_at def select( *keys ) if block_given? self.keys.collect { |k| v = self[k]; [k, v] if yield k, v }.compact @@ -85,27 +238,58 @@ class DBM < ::DBM values_at( *keys ) end end + + # :call-seq: + # ydbm.store(key, value) -> value + # + # Stores +value+ in database with +key+ as the index. +value+ is converted + # to YAML before being stored. + # + # Returns +value+ def store( key, val ) super( key, val.to_yaml ) val end + + # :call-seq: + # ydbm.update(hash) -> ydbm + # + # Updates the database with multiple values from the specified object. + # Takes any object which implements the each_pair method, including + # Hash and DBM objects. + # + # Returns +self+. def update( hsh ) - hsh.keys.each do |k| - self.store( k, hsh.fetch( k ) ) + hsh.each_pair do |k,v| + self.store( k, v ) end self end + + # :call-seq: + # ydbm.to_a -> array + # + # Converts the contents of the database to an array of [key, value] arrays, + # and returns it. def to_a a = [] keys.each { |k| a.push [ k, self.fetch( k ) ] } a end + + + # :call-seq: + # ydbm.to_hash -> hash + # + # Converts the contents of the database to an in-memory Hash object, and + # returns it. def to_hash h = {} keys.each { |k| h[ k ] = self.fetch( k ) } h end + alias :each :each_pair end -end +end if defined?(DBM) diff --git a/lib/yaml/emitter.rb b/lib/yaml/emitter.rb deleted file mode 100644 index a6be4a6733..0000000000 --- a/lib/yaml/emitter.rb +++ /dev/null @@ -1,107 +0,0 @@ -# -# Output classes and methods -# - -require 'yaml/baseemitter' -require 'yaml/encoding' - -module YAML - - # - # Emit a set of values - # - - class Emitter - - include BaseEmitter - - attr_accessor :options - - def initialize( opts ) - opts = {} if opts.class != Hash - @options = YAML::DEFAULTS.dup.update( opts ) - @headless = 0 - @seq_map = false - @anchors = {} - @anchor_extras = {} - @active_anchors = [] - @level = -1 - self.clear - end - - def clear - @buffer = [] - end - - def level - @level - end - - # - # Version string - # - def version_s - " %YAML:#{@options[:Version]}" if @options[:UseVersion] - end - - # - # Header - # - def header - if @headless.nonzero? - "" - else - "---#{version_s} " - end - end - - # - # Concatenate to the buffer - # - def <<( str ) - #p [ self.id, @level, str ] - @buffer.last << str - end - - # - # Monitor objects and allow references - # - def start_object( oid ) - @level += 1 - @buffer.push( "" ) - #p [ self.id, @level, :OPEN ] - idx = nil - if oid - if @anchors.has_key?( oid ) - idx = @active_anchors.index( oid ) - unless idx - idx = @active_anchors.length - af_str = "&#{@options[:AnchorFormat]} " % [ idx + 1 ] - af_str += @anchor_extras[ @anchors[ oid ] ].to_s - @buffer[ @anchors[ oid ] ][0,0] = af_str - @headless = 0 if @anchors[ oid ].zero? - end - idx += 1 - @active_anchors.push( oid ) - else - @anchors[ oid ] = @buffer.length - 1 - end - end - return idx - end - - # - # Output method - # - def end_object - @level -= 1 - @buffer.push( "" ) - #p [ self.id, @level, :END ] - if @level < 0 - header + @buffer.to_s[@headless..-1].to_s - end - end - end - -end - diff --git a/lib/yaml/encoding.rb b/lib/yaml/encoding.rb deleted file mode 100644 index e361163ac6..0000000000 --- a/lib/yaml/encoding.rb +++ /dev/null @@ -1,29 +0,0 @@ -# -# Handle Unicode-to-Internal conversion -# - -module YAML - - # - # Escape the string, condensing common escapes - # - def YAML.escape( value ) - value.gsub( /\\/, "\\\\\\" ).gsub( /"/, "\\\"" ).gsub( /([\x00-\x1f])/ ) { |x| ESCAPES[ x.unpack("C")[0] ] } - end - - # - # Unescape the condenses escapes - # - def YAML.unescape( value ) - value.gsub( /\\(?:([nevfbart\\])|0?x([0-9a-fA-F]{2})|u([0-9a-fA-F]{4}))/ ) { |x| - if $3 - ["#$3".hex ].pack('U*') - elsif $2 - [$2].pack( "H2" ) - else - UNESCAPES[$1] - end - } - end - -end diff --git a/lib/yaml/error.rb b/lib/yaml/error.rb deleted file mode 100644 index a9df22749b..0000000000 --- a/lib/yaml/error.rb +++ /dev/null @@ -1,33 +0,0 @@ -# -# Error messages and exception class -# - -module YAML - - # - # Error messages - # - - ERROR_NO_HEADER_NODE = "With UseHeader=false, the node Array or Hash must have elements" - ERROR_NEED_HEADER = "With UseHeader=false, the node must be an Array or Hash" - ERROR_BAD_EXPLICIT = "Unsupported explicit transfer: '%s'" - ERROR_MANY_EXPLICIT = "More than one explicit transfer" - ERROR_MANY_IMPLICIT = "More than one implicit request" - ERROR_NO_ANCHOR = "No anchor for alias '%s'" - ERROR_BAD_ANCHOR = "Invalid anchor: %s" - ERROR_MANY_ANCHOR = "More than one anchor" - ERROR_ANCHOR_ALIAS = "Can't define both an anchor and an alias" - ERROR_BAD_ALIAS = "Invalid alias: %s" - ERROR_MANY_ALIAS = "More than one alias" - ERROR_ZERO_INDENT = "Can't use zero as an indentation width" - ERROR_UNSUPPORTED_VERSION = "This release of YAML.rb does not support YAML version %s" - ERROR_UNSUPPORTED_ENCODING = "Attempt to use unsupported encoding: %s" - - # - # YAML Error classes - # - - class Error < StandardError; end - class ParseError < Error; end - -end diff --git a/lib/yaml/loader.rb b/lib/yaml/loader.rb deleted file mode 100644 index eb0709e103..0000000000 --- a/lib/yaml/loader.rb +++ /dev/null @@ -1,14 +0,0 @@ -# -# YAML::Loader class -# .. type handling .. -# -module YAML - class Loader - TRANSFER_DOMAINS = { - 'yaml.org,2002' => {}, - 'ruby.yaml.org,2002' => {} - } - PRIVATE_TYPES = {} - IMPLICIT_TYPES = [ 'null', 'bool', 'time', 'int', 'float' ] - end -end diff --git a/lib/yaml/rubytypes.rb b/lib/yaml/rubytypes.rb deleted file mode 100644 index f718df9b9f..0000000000 --- a/lib/yaml/rubytypes.rb +++ /dev/null @@ -1,505 +0,0 @@ -require 'date' -# -# Type conversions -# - -class Class - def to_yaml( opts = {} ) - raise ArgumentError, "can't dump anonymous class %s" % self.class - end -end - -class Object - def is_complex_yaml? - true - end - def to_yaml_type - "!ruby/object:#{self.class}" - end - def to_yaml_properties - instance_variables.sort - end - def to_yaml( opts = {} ) - YAML::quick_emit( self.object_id, opts ) { |out| - out.map( self.to_yaml_type ) { |map| - to_yaml_properties.each { |m| - map.add( m[1..-1], instance_eval( m ) ) - } - } - } - end -end - -YAML.add_ruby_type( /^object/ ) { |type, val| - type, obj_class = YAML.read_type_class( type, Object ) - YAML.object_maker( obj_class, val ) -} - -# -# Maps: Hash#to_yaml -# -class Hash - def is_complex_yaml? - true - end - def to_yaml_type - if self.class == Hash or self.class == YAML::SpecialHash - "!map" - else - "!ruby/hash:#{self.class}" - end - end - def to_yaml( opts = {} ) - opts[:DocType] = self.class if Hash === opts - YAML::quick_emit( self.object_id, opts ) { |out| - hash_type = to_yaml_type - if not out.options(:ExplicitTypes) and hash_type == "!map" - hash_type = "" - end - out.map( hash_type ) { |map| - # - # Sort the hash - # - if out.options(:SortKeys) - map.concat( self.sort ) - else - map.concat( self.to_a ) - end - } - } - end -end - -hash_proc = Proc.new { |type, val| - if Array === val - val = Hash.[]( *val ) # Convert the map to a sequence - elsif Hash === val - type, obj_class = YAML.read_type_class( type, Hash ) - if obj_class != Hash - o = obj_class.new - o.update( val ) - val = o - end - else - raise YAML::Error, "Invalid map explicitly tagged !map: " + val.inspect - end - val -} -YAML.add_ruby_type( /^hash/, &hash_proc ) - -module YAML - - # - # Ruby-specific collection: !ruby/flexhash - # - class FlexHash < Array - def []( k ) - self.assoc( k ).to_a[1] - end - def []=( k, *rest ) - val, set = rest.reverse - if ( tmp = self.assoc( k ) ) and not set - tmp[1] = val - else - self << [ k, val ] - end - val - end - def has_key?( k ) - self.assoc( k ) ? true : false - end - def is_complex_yaml? - true - end - def to_yaml( opts = {} ) - YAML::quick_emit( self.object_id, opts ) { |out| - out.seq( "!ruby/flexhash" ) { |seq| - self.each { |v| - if v[1] - seq.add( Hash.[]( *v ) ) - else - seq.add( v[0] ) - end - } - } - } - end - end - - YAML.add_ruby_type( 'flexhash' ) { |type, val| - if Array === val - p = FlexHash.new - val.each { |v| - if Hash === v - p.concat( v.to_a ) # Convert the map to a sequence - else - p << [ v, nil ] - end - } - p - else - raise YAML::Error, "Invalid !ruby/flexhash: " + val.inspect - end - } -end - -# -# Structs: export as a !map -# -class Struct - def is_complex_yaml? - true - end - def to_yaml( opts = {} ) - YAML::quick_emit( self.object_id, opts ) { |out| - # - # Basic struct is passed as a YAML map - # - struct_name = self.class.name.gsub( "Struct::", "" ) - out.map( "!ruby/struct:#{struct_name}" ) { |map| - self.members.each { |m| - map.add( m, self[m] ) - } - } - } - end -end - -YAML.add_ruby_type( /^struct/ ) { |type, val| - if Hash === val - struct_type = nil - - # - # Use existing Struct if it exists - # - begin - struct_name, struct_type = YAML.read_type_class( type, Struct ) - rescue NameError - end - if not struct_type - struct_def = [ type.split( ':', 4 ).last ] - struct_type = Struct.new( *struct_def.concat( val.keys.collect { |k| k.intern } ) ) - end - - # - # Set the Struct properties - # - st = struct_type.new - st.members.each { |m| - st.send( "#{m}=", val[m] ) - } - st - else - raise YAML::Error, "Invalid Ruby Struct: " + val.inspect - end -} - -# -# Sequences: Array#to_yaml -# -class Array - def is_complex_yaml? - true - end - def to_yaml_type - if self.class == Array - "!seq" - else - "!ruby/array:#{self.class}" - end - end - def to_yaml( opts = {} ) - opts[:DocType] = self.class if Hash === opts - YAML::quick_emit( self.object_id, opts ) { |out| - array_type = to_yaml_type - if not out.options(:ExplicitTypes) and array_type == "!seq" - array_type = "" - end - - out.seq( array_type ) { |seq| - seq.concat( self ) - } - } - end -end - -array_proc = Proc.new { |type, val| - if Array === val - type, obj_class = YAML.read_type_class( type, Array ) - if obj_class != Array - o = obj_class.new - o.concat( val ) - val = o - end - val - else - val.to_a - end -} -YAML.add_ruby_type( /^array/, &array_proc ) - -# -# Exception#to_yaml -# -class Exception - def is_complex_yaml? - true - end - def to_yaml_type - "!ruby/exception:#{self.class}" - end - def to_yaml( opts = {} ) - YAML::quick_emit( self.object_id, opts ) { |out| - out.map( self.to_yaml_type ) { |map| - map.add( 'message', self.message ) - to_yaml_properties.each { |m| - map.add( m[1..-1], instance_eval( m ) ) - } - } - } - end -end - -YAML.add_ruby_type( /^exception/ ) { |type, val| - type, obj_class = YAML.read_type_class( type, Exception ) - o = YAML.object_maker( obj_class, { 'mesg' => val.delete( 'message' ) }, true ) - val.each_pair { |k,v| - o.instance_eval "@#{k} = v" - } - o -} - - -# -# String#to_yaml -# -class String - def is_complex_yaml? - ( self =~ /\n.+/ ? true : false ) - end - def is_binary_data? - ( self.count( "^ -~", "^\r\n" ) / self.size > 0.3 || self.count( "\x00" ) > 0 ) - end - def to_yaml( opts = {} ) - complex = false - if self.is_complex_yaml? - complex = true - elsif opts[:BestWidth].to_i > 0 - if self.length > opts[:BestWidth] and opts[:UseFold] - complex = true - end - end - YAML::quick_emit( complex ? self.object_id : nil, opts ) { |out| - if complex - if self.is_binary_data? - out.binary_base64( self ) - elsif self =~ /^ |#{YAML::ESCAPE_CHAR}| $/ - complex = false - else - out.node_text( self ) - end - end - if not complex - ostr = if out.options(:KeepValue) - self - elsif empty? - "''" - elsif self =~ /^[^#{YAML::WORD_CHAR}]|#{YAML::ESCAPE_CHAR}|[#{YAML::SPACE_INDICATORS}]( |$)| $|\n|\'/ - "\"#{YAML.escape( self )}\"" - elsif YAML.detect_implicit( self ) != 'str' - "\"#{YAML.escape( self )}\"" - else - self - end - out.simple( ostr ) - end - } - end -end - -# -# Symbol#to_yaml -# -class Symbol - def is_complex_yaml? - false - end - def to_yaml( opts = {} ) - YAML::quick_emit( nil, opts ) { |out| - out << "!ruby/sym " - self.id2name.to_yaml( :Emitter => out ) - } - end -end - -symbol_proc = Proc.new { |type, val| - if String === val - val.intern - else - raise YAML::Error, "Invalid Symbol: " + val.inspect - end -} -YAML.add_ruby_type( 'symbol', &symbol_proc ) -YAML.add_ruby_type( 'sym', &symbol_proc ) - -# -# Range#to_yaml -# -class Range - def is_complex_yaml? - false - end - def to_yaml( opts = {} ) - YAML::quick_emit( nil, opts ) { |out| - out << "!ruby/range " - self.inspect.to_yaml( :Emitter => out ) - } - end -end - -YAML.add_ruby_type( 'range' ) { |type, val| - if String === val and val =~ /^(.*[^.])(\.{2,3})([^.].*)$/ - r1, rdots, r2 = $1, $2, $3 - Range.new( YAML.try_implicit( r1 ), YAML.try_implicit( r2 ), rdots.length == 3 ) - elsif Hash === val - Range.new( val['begin'], val['end'], val['exclude_end?'] ) - else - raise YAML::Error, "Invalid Range: " + val.inspect - end -} - -# -# Make an RegExp -# -class Regexp - def is_complex_yaml? - false - end - def to_yaml( opts = {} ) - YAML::quick_emit( nil, opts ) { |out| - out << "!ruby/regexp " - self.inspect.to_yaml( :Emitter => out ) - } - end -end - -regexp_proc = Proc.new { |type, val| - if String === val and val =~ /^\/(.*)\/([mix]*)$/ - val = { 'REGEXP' => $1, 'MODIFIERS' => $2 } - end - if Hash === val - mods = nil - unless val['MODIFIERS'].to_s.empty? - mods = 0x00 - if val['MODIFIERS'].include?( 'x' ) - mods |= Regexp::EXTENDED - elsif val['MODIFIERS'].include?( 'i' ) - mods |= Regexp::IGNORECASE - elsif val['MODIFIERS'].include?( 'm' ) - mods |= Regexp::POSIXLINE - end - end - Regexp::compile( val['REGEXP'], mods ) - else - raise YAML::Error, "Invalid Regular expression: " + val.inspect - end -} -YAML.add_domain_type( "perl.yaml.org,2002", /^regexp/, ®exp_proc ) -YAML.add_ruby_type( 'regexp', ®exp_proc ) - -# -# Emit a Time object as an ISO 8601 timestamp -# -class Time - def is_complex_yaml? - false - end - def to_yaml( opts = {} ) - YAML::quick_emit( nil, opts ) { |out| - tz = "Z" - # from the tidy Tobias Peters <t-peters@gmx.de> Thanks! - unless self.utc? - utc_same_instant = self.dup.utc - utc_same_writing = Time.utc(year,month,day,hour,min,sec,usec) - difference_to_utc = utc_same_writing - utc_same_instant - if (difference_to_utc < 0) - difference_sign = '-' - absolute_difference = -difference_to_utc - else - difference_sign = '+' - absolute_difference = difference_to_utc - end - difference_minutes = (absolute_difference/60).round - tz = "%s%02d:%02d" % [ difference_sign, difference_minutes / 60, difference_minutes % 60] - end - ( self.strftime( "%Y-%m-%d %H:%M:%S." ) + - "%06d %s" % [usec, tz] ). - to_yaml( :Emitter => out, :KeepValue => true ) - } - end -end - -# -# Emit a Date object as a simple implicit -# -class Date - def is_complex_yaml? - false - end - def to_yaml( opts = {} ) - opts[:KeepValue] = true - self.to_s.to_yaml( opts ) - end -end - -# -# Send Integer, Booleans, NilClass to String -# -class Numeric - def is_complex_yaml? - false - end - def to_yaml( opts = {} ) - str = self.to_s - if str == "Infinity" - str = ".Inf" - elsif str == "-Infinity" - str = "-.Inf" - elsif str == "NaN" - str = ".NaN" - end - opts[:KeepValue] = true - str.to_yaml( opts ) - end -end - -class TrueClass - def is_complex_yaml? - false - end - def to_yaml( opts = {} ) - opts[:KeepValue] = true - "true".to_yaml( opts ) - end -end - -class FalseClass - def is_complex_yaml? - false - end - def to_yaml( opts = {} ) - opts[:KeepValue] = true - "false".to_yaml( opts ) - end -end - -class NilClass - def is_complex_yaml? - false - end - def to_yaml( opts = {} ) - opts[:KeepValue] = true - "".to_yaml( opts ) - end -end - diff --git a/lib/yaml/store.rb b/lib/yaml/store.rb index 2e74b27221..27c823b9f9 100644 --- a/lib/yaml/store.rb +++ b/lib/yaml/store.rb @@ -1,75 +1,98 @@ +# frozen_string_literal: false # # YAML::Store # require 'yaml' -require 'pstore' -module YAML +begin + require 'pstore' +rescue LoadError +end - class Store < PStore - # - # Constructor - # - def initialize( *o ) - @opt = YAML::DEFAULTS.dup - if String === o.first - super(o.shift) - end - if o.last.is_a? Hash - @opt.update(o.pop) - end - end +# YAML::Store provides the same functionality as PStore, except it uses YAML +# to dump objects instead of Marshal. +# +# == Example +# +# require 'yaml/store' +# +# Person = Struct.new :first_name, :last_name +# +# people = [Person.new("Bob", "Smith"), Person.new("Mary", "Johnson")] +# +# store = YAML::Store.new "test.store" +# +# store.transaction do +# store["people"] = people +# store["greeting"] = { "hello" => "world" } +# end +# +# After running the above code, the contents of "test.store" will be: +# +# --- +# people: +# - !ruby/struct:Person +# first_name: Bob +# last_name: Smith +# - !ruby/struct:Person +# first_name: Mary +# last_name: Johnson +# greeting: +# hello: world - # - # Override Pstore#transaction - # - def transaction - raise YAML::Error, "nested transaction" if @transaction - raise YAML::Error, "no filename for transaction" unless @filename - begin - @transaction = true - value = nil - backup = @filename+"~" - if File::exist?(@filename) - file = File::open(@filename, "rb+") - orig = true - else - @table = {} - file = File::open(@filename, "wb+") - file.write( @table.to_yaml( @opt ) ) - end - file.flock(File::LOCK_EX) - if orig - File::copy @filename, backup - @table = YAML::load( file ) - end - begin - catch(:pstore_abort_transaction) do - value = yield(self) - end - rescue Exception - @abort = true - raise - ensure - unless @abort - begin - file.rewind - file.write( @table.to_yaml( @opt ) ) - file.truncate(file.pos) - rescue - File::rename backup, @filename if File::exist?(backup) - raise - end - end - @abort = false - end - ensure - @table = nil - @transaction = false - file.close if file - end - value - end - end +class YAML::Store < PStore -end + # :call-seq: + # initialize( file_name, yaml_opts = {} ) + # initialize( file_name, thread_safe = false, yaml_opts = {} ) + # + # Creates a new YAML::Store object, which will store data in +file_name+. + # If the file does not already exist, it will be created. + # + # YAML::Store objects are always reentrant. But if _thread_safe_ is set to true, + # then it will become thread-safe at the cost of a minor performance hit. + # + # Options passed in through +yaml_opts+ will be used when converting the + # store to YAML via Hash#to_yaml(). + def initialize( *o ) + @opt = {} + if o.last.is_a? Hash + @opt.update(o.pop) + end + super(*o) + end + + # :stopdoc: + + def dump(table) + table.to_yaml(@opt) + end + + def load(content) + table = if YAML.respond_to?(:safe_load) + if Psych::VERSION >= "3.1" + YAML.safe_load(content, permitted_classes: [Symbol]) + else + YAML.safe_load(content, [Symbol]) + end + else + YAML.load(content) + end + if table == false || table == nil + {} + else + table + end + end + + def marshal_dump_supports_canonical_option? + false + end + + def empty_marshal_data + {}.to_yaml(@opt) + end + def empty_marshal_checksum + CHECKSUM_ALGO.digest(empty_marshal_data) + end +end if defined?(::PStore) diff --git a/lib/yaml/stream.rb b/lib/yaml/stream.rb deleted file mode 100644 index 943c51526b..0000000000 --- a/lib/yaml/stream.rb +++ /dev/null @@ -1,44 +0,0 @@ -module YAML - - # - # YAML::Stream -- for emitting many documents - # - class Stream - - attr_accessor :documents, :options - - def initialize( opts = {} ) - @options = opts - @documents = [] - end - - def []( i ) - @documents[ i ] - end - - def add( doc ) - @documents << doc - end - - def edit( doc_num, doc ) - @documents[ doc_num ] = doc - end - - def emit - opts = @options.dup - opts[:UseHeader] = true if @documents.length > 1 - ct = 0 - out = YAML::Syck::Emitter.new( opts ) - @documents.each { |v| - if ct > 0 - out << "\n--- " - end - v.to_yaml( :Emitter => out ) - ct += 1 - } - out.end_object - end - - end - -end diff --git a/lib/yaml/stringio.rb b/lib/yaml/stringio.rb deleted file mode 100644 index 8ad949fa2b..0000000000 --- a/lib/yaml/stringio.rb +++ /dev/null @@ -1,83 +0,0 @@ -# -# Limited StringIO if no core lib is available -# -begin -require 'stringio' -rescue LoadError - # StringIO based on code by MoonWolf - class StringIO - def initialize(string="") - @string=string - @pos=0 - @eof=(string.size==0) - end - def pos - @pos - end - def eof - @eof - end - alias eof? eof - def readline(rs=$/) - if @eof - raise EOFError - else - if p = @string[@pos..-1]=~rs - line = @string[@pos,p+1] - else - line = @string[@pos..-1] - end - @pos+=line.size - @eof =true if @pos==@string.size - $_ = line - end - end - def rewind - seek(0,0) - end - def seek(offset,whence) - case whence - when 0 - @pos=offset - when 1 - @pos+=offset - when 2 - @pos=@string.size+offset - end - @eof=(@pos>=@string.size) - 0 - end - end - - # - # Class method for creating streams - # - def YAML.make_stream( io ) - if String === io - io = StringIO.new( io ) - elsif not IO === io - raise YAML::Error, "YAML stream must be an IO or String object." - end - if YAML::unicode - def io.readline - YAML.utf_to_internal( readline( @ln_sep ), @utf_encoding ) - end - def io.check_unicode - @utf_encoding = YAML.sniff_encoding( read( 4 ) ) - @ln_sep = YAML.enc_separator( @utf_encoding ) - seek( -4, IO::SEEK_CUR ) - end - def io.utf_encoding - @utf_encoding - end - io.check_unicode - else - def io.utf_encoding - :None - end - end - io - end - -end - diff --git a/lib/yaml/syck.rb b/lib/yaml/syck.rb deleted file mode 100644 index 267067feb5..0000000000 --- a/lib/yaml/syck.rb +++ /dev/null @@ -1,27 +0,0 @@ -# -# YAML::Syck module -# .. glues syck and yaml.rb together .. -# -require 'syck' -require 'yaml/basenode' -require 'yaml/baseemitter' - -module YAML - module Syck - - # - # Mixin BaseNode functionality - # - class Node - include YAML::BaseNode - end - - # - # Mixin BaseEmitter functionality - # - class Emitter - include YAML::BaseEmitter - end - - end -end diff --git a/lib/yaml/types.rb b/lib/yaml/types.rb deleted file mode 100644 index f7772cb3a0..0000000000 --- a/lib/yaml/types.rb +++ /dev/null @@ -1,196 +0,0 @@ -# -# Classes required by the full core typeset -# - -module YAML - - # - # Default private type - # - class PrivateType - attr_accessor :type_id, :value - def initialize( type, val ) - @type_id = type; @value = val - end - def to_yaml( opts = {} ) - YAML::quick_emit( self.object_id, opts ) { |out| - out << " !!#{@type_id}" - value.to_yaml( :Emitter => out ) - } - end - end - - # - # Default domain type - # - class DomainType - attr_accessor :domain, :type_id, :value - def initialize( domain, type, val ) - @domain = domain; @type_id = type; @value = val - end - def to_yaml_type - dom = @domain.dup - if dom =~ /\.yaml\.org,2002$/ - dom = $` - end - "#{dom}/#{@type_id}" - end - def to_yaml( opts = {} ) - YAML::quick_emit( self.object_id, opts ) { |out| - out << " !#{to_yaml_type} " - value.to_yaml( :Emitter => out ) - } - end - end - - # - # YAML Hash class to support comments and defaults - # - class SpecialHash < Object::Hash - attr_accessor :default - def inspect - self.default.to_s - end - def to_s - self.default.to_s - end - def update( h ) - if YAML::SpecialHash === h - @default = h.default if h.default - end - super( h ) - end - def to_yaml( opts = {} ) - opts[:DefaultKey] = self.default - super( opts ) - end - end - - # - # Builtin collection: !omap - # - class Omap < Array - def self.[]( *vals ) - o = Omap.new - 0.step( vals.length - 1, 2 ) { |i| - o[vals[i]] = vals[i+1] - } - o - end - def []( k ) - self.assoc( k ).to_a[1] - end - def []=( k, *rest ) - val, set = rest.reverse - if ( tmp = self.assoc( k ) ) and not set - tmp[1] = val - else - self << [ k, val ] - end - val - end - def has_key?( k ) - self.assoc( k ) ? true : false - end - def is_complex_yaml? - true - end - def to_yaml( opts = {} ) - YAML::quick_emit( self.object_id, opts ) { |out| - out.seq( "!omap" ) { |seq| - self.each { |v| - seq.add( Hash[ *v ] ) - } - } - } - end - end - - YAML.add_builtin_type( "omap" ) { |type, val| - if Array === val - p = Omap.new - val.each { |v| - if Hash === v - p.concat( v.to_a ) # Convert the map to a sequence - else - raise YAML::Error, "Invalid !omap entry: " + val.inspect - end - } - else - raise YAML::Error, "Invalid !omap: " + val.inspect - end - p - } - - # - # Builtin collection: !pairs - # - class Pairs < Array - def self.[]( *vals ) - p = Pairs.new - 0.step( vals.length - 1, 2 ) { |i| - p[vals[i]] = vals[i+1] - } - p - end - def []( k ) - self.assoc( k ).to_a - end - def []=( k, val ) - self << [ k, val ] - val - end - def has_key?( k ) - self.assoc( k ) ? true : false - end - def is_complex_yaml? - true - end - def to_yaml( opts = {} ) - YAML::quick_emit( self.object_id, opts ) { |out| - out.seq( "!pairs" ) { |seq| - self.each { |v| - seq.add( Hash[ *v ] ) - } - } - } - end - end - - YAML.add_builtin_type( "pairs" ) { |type, val| - if Array === val - p = Pairs.new - val.each { |v| - if Hash === v - p.concat( v.to_a ) # Convert the map to a sequence - else - raise YAML::Error, "Invalid !pairs entry: " + val.inspect - end - } - else - raise YAML::Error, "Invalid !pairs: " + val.inspect - end - p - } - - # - # Builtin collection: !set - # - class Set < Hash - def to_yaml_type - "!set" - end - end - - YAML.add_builtin_type( 'set' ) { |type, val| - if Array === val - val = Set[ *val ] - elsif Hash === val - Set[ val ] - else - raise YAML::Error, "Invalid map explicitly tagged !map: " + val.inspect - end - val - } - -end diff --git a/lib/yaml/yaml.gemspec b/lib/yaml/yaml.gemspec new file mode 100644 index 0000000000..17e1ce89e0 --- /dev/null +++ b/lib/yaml/yaml.gemspec @@ -0,0 +1,30 @@ +name = File.basename(__FILE__, ".gemspec") +version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir| + break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line| + /^\s*LOADER_VERSION\s*=\s*"(.*)"/ =~ line and break $1 + end rescue nil +end + +Gem::Specification.new do |spec| + spec.name = name + spec.version = version + spec.authors = ["Aaron Patterson", "SHIBATA Hiroshi"] + spec.email = ["aaron@tenderlovemaking.com", "hsbt@ruby-lang.org"] + + spec.summary = "YAML Ain't Markup Language" + spec.description = spec.summary + spec.homepage = "https://github.com/ruby/yaml" + spec.licenses = ["Ruby", "BSD-2-Clause"] + + spec.metadata["homepage_uri"] = spec.homepage + spec.metadata["source_code_uri"] = spec.homepage + + # Specify which files should be added to the gem when it is released. + # The `git ls-files -z` loads the files in the RubyGem that have been added into git. + spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do + `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } + end + spec.bindir = "exe" + spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + spec.require_paths = ["lib"] +end diff --git a/lib/yaml/yamlnode.rb b/lib/yaml/yamlnode.rb deleted file mode 100644 index e36a18e694..0000000000 --- a/lib/yaml/yamlnode.rb +++ /dev/null @@ -1,54 +0,0 @@ -# -# YAML::YamlNode class -# -require 'yaml/basenode' - -module YAML - - # - # YAML Generic Model container - # - class YamlNode - include BaseNode - attr_accessor :kind, :type_id, :value, :anchor - def initialize( t, v ) - @type_id = t - if Hash === v - @kind = 'map' - @value = {} - v.each { |k,v| - @value[ k.transform ] = [ k, v ] - } - elsif Array === v - @kind = 'seq' - @value = v - elsif String === v - @kind = 'scalar' - @value = v - end - end - - # - # Transform this node fully into a native type - # - def transform - t = nil - if @value.is_a? Hash - t = {} - @value.each { |k,v| - t[ k ] = v[1].transform - } - elsif @value.is_a? Array - t = [] - @value.each { |v| - t.push v.transform - } - else - t = @value - end - YAML.transfer_method( @type_id, t ) - end - - end - -end diff --git a/lib/yaml/ypath.rb b/lib/yaml/ypath.rb deleted file mode 100644 index 81348ca043..0000000000 --- a/lib/yaml/ypath.rb +++ /dev/null @@ -1,52 +0,0 @@ -# -# YAML::YPath -# - -module YAML - - class YPath - attr_accessor :segments, :predicates, :flags - def initialize( str ) - @segments = [] - @predicates = [] - @flags = nil - while str =~ /^\/?(\/|[^\/\[]+)(?:\[([^\]]+)\])?/ - @segments.push $1 - @predicates.push $2 - str = $' - end - unless str.to_s.empty? - @segments += str.split( "/" ) - end - if @segments.length == 0 - @segments.push "." - end - end - def YPath.each_path( str ) - # - # Find choices - # - paths = [] - str = "(#{ str })" - while str.sub!( /\(([^()]+)\)/, "\n#{ paths.length }\n" ) - paths.push $1.split( '|' ) - end - - # - # Construct all possible paths - # - all = [ str ] - ( paths.length - 1 ).downto( 0 ) do |i| - all = all.collect do |a| - paths[i].collect do |p| - a.gsub( /\n#{ i }\n/, p ) - end - end.flatten.uniq - end - all.collect do |path| - yield YPath.new( path ) - end - end - end - -end |
