This project is closed and read-only.
Backport #6212 » psych_backport.patch
| ChangeLog | ||
|---|---|---|
|
Mon Jul 18 13:36:47 2011 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych.rb: define a new BadAlias error class.
|
||
|
* ext/psych/lib/psych/visitors/to_ruby.rb: raise an exception when
|
||
|
deserializing an alias that does not exist.
|
||
|
* test/psych/test_merge_keys.rb: corresponding test.
|
||
|
Fri Mar 9 06:29:22 2012 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych.rb (load, parse): stop parsing or loading after
|
||
|
the first document has been parsed.
|
||
|
* test/psych/test_stream.rb: pertinent tests.
|
||
|
Fri Mar 9 06:17:05 2012 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych.rb (parse_stream, load_stream): if a block is
|
||
|
given, documents will be yielded to the block as they are parsed.
|
||
|
[ruby-core:42404] [Bug #5978]
|
||
|
* ext/psych/lib/psych/handlers/document_stream.rb: add a handler that
|
||
|
yields documents as they are parsed
|
||
|
* test/psych/test_stream.rb: corresponding tests.
|
||
|
Tue Mar 6 02:31:20 2012 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych/core_ext.rb: only extend Kernel if IRB is loaded
|
||
|
in order to stop method pollution.
|
||
|
Tue Feb 28 10:28:51 2012 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych.rb: default open YAML files with utf8 external
|
||
|
encoding. [ruby-core:42967]
|
||
|
* test/psych/test_tainted.rb: ditto
|
||
|
Fri Feb 24 13:54:33 2012 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/parser.c: prevent a memory leak by protecting calls to
|
||
|
handler callbacks.
|
||
|
* test/psych/test_parser.rb: test to demonstrate leak.
|
||
|
Fri Feb 24 08:08:38 2012 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/parser.c: set parser encoding based on the YAML input
|
||
|
rather than user configuration.
|
||
|
* test/psych/test_encoding.rb: corresponding tests.
|
||
|
* test/psych/test_parser.rb: ditto
|
||
|
* test/psych/test_tainted.rb: ditto
|
||
|
Fri Feb 10 03:41:31 2012 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/parser.c: removed external encoding setter, allow parser
|
||
|
to be reused.
|
||
|
* ext/psych/lib/psych/parser.rb: added external encoding setter.
|
||
|
* test/psych/test_parser.rb: test parser reuse
|
||
|
Wed Jan 18 12:49:15 2012 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych/visitors/to_ruby.rb: Added support for loading
|
||
|
subclasses of String with ivars
|
||
|
* ext/psych/lib/psych/visitors/yaml_tree.rb: Added support for dumping
|
||
|
subclasses of String with ivars
|
||
|
* test/psych/test_string.rb: corresponding tests
|
||
|
Wed Jan 18 10:39:47 2012 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych/visitors/to_ruby.rb: Added ability to load array
|
||
|
subclasses with ivars.
|
||
|
* ext/psych/lib/psych/visitors/yaml_tree.rb: Added ability to dump
|
||
|
array subclasses with ivars.
|
||
|
* test/psych/test_array.rb: corresponding tests
|
||
|
Wed Dec 21 02:25:36 2011 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/emitter.c: fixing clang warnings. Thanks Joey!
|
||
|
Sun Dec 18 12:42:48 2011 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych/visitors/to_ruby.rb: BigDecimals can be restored
|
||
|
from YAML.
|
||
|
* ext/psych/lib/psych/visitors/yaml_tree.rb: BigDecimals can be dumped
|
||
|
to YAML.
|
||
|
* test/psych/test_numeric.rb: tests for BigDecimal serialization
|
||
|
Sun Dec 18 12:03:13 2011 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych/scalar_scanner.rb: Strings that look like dates
|
||
|
should be treated as strings and not dates.
|
||
|
* test/psych/test_scalar_scanner.rb: corresponding tests.
|
||
|
Wed Dec 7 08:04:31 2011 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych.rb (module Psych): parse and load methods take
|
||
|
an optional file name that is used when raising Psych::SyntaxError
|
||
|
exceptions
|
||
|
* ext/psych/lib/psych/syntax_error.rb (module Psych): allow nil file
|
||
|
names and handle nil file names in the exception message
|
||
|
* test/psych/test_exception.rb (module Psych): Tests for changes.
|
||
|
Wed Nov 30 09:09:37 2011 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/parser.c (parse): parse method can take an option file
|
||
|
name for use in exception messages.
|
||
|
* test/psych/test_parser.rb: corresponding tests.
|
||
|
Tue Nov 22 04:46:22 2011 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych.rb: remove autoload from psych
|
||
|
* ext/psych/lib/psych/json.rb: ditto
|
||
|
Wed Nov 9 04:52:16 2011 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych/tree_builder.rb: dump complex numbers,
|
||
|
rationals, etc with reference ids.
|
||
|
* ext/psych/lib/psych/visitors/yaml_tree.rb: ditto
|
||
|
* ext/psych/lib/psych/visitors/to_ruby.rb: loading complex numbers,
|
||
|
rationals, etc with reference ids.
|
||
|
* test/psych/test_object_references.rb: corresponding tests
|
||
|
Mon Nov 7 20:31:52 2011 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych/scalar_scanner.rb: make sure strings that look
|
||
|
like base 60 numbers are serialized as quoted strings.
|
||
|
* test/psych/test_string.rb: test for change.
|
||
|
Thu Oct 27 08:47:38 2011 Martin Bosslet <Martin.Bosslet@googlemail.com>
|
||
|
* ext/psych/parser.c: remove unused variable.
|
||
|
Wed Oct 5 02:50:27 2011 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych/syntax_error.rb: Add file, line, offset, and
|
||
|
message attributes during parse failure.
|
||
|
* ext/psych/parser.c: Update parser to raise exception with correct
|
||
|
values.
|
||
|
* test/psych/test_exception.rb: corresponding tests.
|
||
|
Wed Oct 5 01:52:16 2011 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/parser.c (parse): Use context_mark for indicating error
|
||
|
line and column.
|
||
|
Wed Oct 5 01:22:08 2011 Aaron Patterson <aaron@tenderlovemaking.com>
|
||
|
* ext/psych/lib/psych/scalar_scanner.rb: use normal begin / rescue
|
||
|
since postfix rescue cannot receive the exception class. Thanks
|
||
|
nagachika!
|
||
|
Tue Mar 27 22:22:50 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||
|
* configure.in (RUBY_STACK_GROW_DIRECTION): substitute CPU name as
|
||
| ext/psych/emitter.c | ||
|---|---|---|
|
(yaml_char_t *)(NIL_P(anchor) ? NULL : StringValuePtr(anchor)),
|
||
|
(yaml_char_t *)(NIL_P(tag) ? NULL : StringValuePtr(tag)),
|
||
|
implicit ? 1 : 0,
|
||
|
(yaml_sequence_style_t)NUM2INT(style)
|
||
|
(yaml_mapping_style_t)NUM2INT(style)
|
||
|
);
|
||
|
emit(emitter, &event);
|
||
| ext/psych/lib/psych.rb | ||
|---|---|---|
|
require 'psych/coder'
|
||
|
require 'psych/core_ext'
|
||
|
require 'psych/deprecated'
|
||
|
require 'psych/json'
|
||
|
require 'psych/stream'
|
||
|
require 'psych/json/tree_builder'
|
||
|
require 'psych/json/stream'
|
||
|
require 'psych/handlers/document_stream'
|
||
|
###
|
||
|
# = Overview
|
||
| ... | ... | |
|
class Exception < RuntimeError
|
||
|
end
|
||
|
autoload :Stream, 'psych/stream'
|
||
|
class BadAlias < Exception
|
||
|
end
|
||
|
###
|
||
|
# Load +yaml+ in to a Ruby data structure. If multiple documents are
|
||
|
# provided, the object contained in the first document will be returned.
|
||
|
# +filename+ will be used in the exception message if any exception is raised
|
||
|
# while parsing.
|
||
|
#
|
||
|
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
|
||
|
#
|
||
|
# Example:
|
||
|
#
|
||
|
# Psych.load("--- a") # => 'a'
|
||
|
# Psych.load("---\n - a\n - b") # => ['a', 'b']
|
||
|
def self.load yaml
|
||
|
result = parse(yaml)
|
||
|
# Psych.load("--- a") # => 'a'
|
||
|
# Psych.load("---\n - a\n - b") # => ['a', 'b']
|
||
|
#
|
||
|
# begin
|
||
|
# Psych.load("--- `", "file.txt")
|
||
|
# rescue Psych::SyntaxError => ex
|
||
|
# ex.file # => 'file.txt'
|
||
|
# ex.message # => "(foo.txt): found character that cannot start any token"
|
||
|
# end
|
||
|
def self.load yaml, filename = nil
|
||
|
result = parse(yaml, filename)
|
||
|
result ? result.to_ruby : result
|
||
|
end
|
||
|
###
|
||
|
# Parse a YAML string in +yaml+. Returns the first object of a YAML AST.
|
||
|
# +filename+ is used in the exception message if a Psych::SyntaxError is
|
||
|
# raised.
|
||
|
#
|
||
|
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
|
||
|
#
|
||
|
# Example:
|
||
|
#
|
||
|
# Psych.parse("---\n - a\n - b") # => #<Psych::Nodes::Sequence:0x00>
|
||
|
#
|
||
|
# begin
|
||
|
# Psych.parse("--- `", "file.txt")
|
||
|
# rescue Psych::SyntaxError => ex
|
||
|
# ex.file # => 'file.txt'
|
||
|
# ex.message # => "(foo.txt): found character that cannot start any token"
|
||
|
# end
|
||
|
#
|
||
|
# See Psych::Nodes for more information about YAML AST.
|
||
|
def self.parse yaml
|
||
|
children = parse_stream(yaml).children
|
||
|
children.empty? ? false : children.first.children.first
|
||
|
def self.parse yaml, filename = nil
|
||
|
parse_stream(yaml, filename) do |node|
|
||
|
return node
|
||
|
end
|
||
|
false
|
||
|
end
|
||
|
###
|
||
|
# Parse a file at +filename+. Returns the YAML AST.
|
||
|
#
|
||
|
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
|
||
|
def self.parse_file filename
|
||
|
File.open filename do |f|
|
||
|
parse f
|
||
|
File.open filename, 'r:bom|utf-8' do |f|
|
||
|
parse f, filename
|
||
|
end
|
||
|
end
|
||
| ... | ... | |
|
###
|
||
|
# Parse a YAML string in +yaml+. Returns the full AST for the YAML document.
|
||
|
# This method can handle multiple YAML documents contained in +yaml+.
|
||
|
# +filename+ is used in the exception message if a Psych::SyntaxError is
|
||
|
# raised.
|
||
|
#
|
||
|
# If a block is given, a Psych::Nodes::Document node will be yielded to the
|
||
|
# block as it's being parsed.
|
||
|
#
|
||
|
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
|
||
|
#
|
||
|
# Example:
|
||
|
#
|
||
|
# Psych.parse_stream("---\n - a\n - b") # => #<Psych::Nodes::Stream:0x00>
|
||
|
#
|
||
|
# Psych.parse_stream("--- a\n--- b") do |node|
|
||
|
# node # => #<Psych::Nodes::Document:0x00>
|
||
|
# end
|
||
|
#
|
||
|
# begin
|
||
|
# Psych.parse_stream("--- `", "file.txt")
|
||
|
# rescue Psych::SyntaxError => ex
|
||
|
# ex.file # => 'file.txt'
|
||
|
# ex.message # => "(foo.txt): found character that cannot start any token"
|
||
|
# end
|
||
|
#
|
||
|
# See Psych::Nodes for more information about YAML AST.
|
||
|
def self.parse_stream yaml
|
||
|
parser = self.parser
|
||
|
parser.parse yaml
|
||
|
parser.handler.root
|
||
|
def self.parse_stream yaml, filename = nil, &block
|
||
|
if block_given?
|
||
|
parser = Psych::Parser.new(Handlers::DocumentStream.new(&block))
|
||
|
parser.parse yaml, filename
|
||
|
else
|
||
|
parser = self.parser
|
||
|
parser.parse yaml, filename
|
||
|
parser.handler.root
|
||
|
end
|
||
|
end
|
||
|
###
|
||
| ... | ... | |
|
###
|
||
|
# Load multiple documents given in +yaml+. Returns the parsed documents
|
||
|
# as a list. For example:
|
||
|
# as a list. If a block is given, each document will be converted to ruby
|
||
|
# and passed to the block during parsing
|
||
|
#
|
||
|
# Example:
|
||
|
#
|
||
|
# Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
|
||
|
#
|
||
|
def self.load_stream yaml
|
||
|
parse_stream(yaml).children.map { |child| child.to_ruby }
|
||
|
# list = []
|
||
|
# Psych.load_stream("--- foo\n...\n--- bar\n...") do |ruby|
|
||
|
# list << ruby
|
||
|
# end
|
||
|
# list # => ['foo', 'bar']
|
||
|
#
|
||
|
def self.load_stream yaml, filename = nil
|
||
|
if block_given?
|
||
|
parse_stream(yaml, filename) do |node|
|
||
|
yield node.to_ruby
|
||
|
end
|
||
|
else
|
||
|
parse_stream(yaml, filename).children.map { |child| child.to_ruby }
|
||
|
end
|
||
|
end
|
||
|
###
|
||
|
# Load the document contained in +filename+. Returns the yaml contained in
|
||
|
# +filename+ as a ruby object
|
||
|
def self.load_file filename
|
||
|
File.open(filename) { |f| self.load f }
|
||
|
File.open(filename, 'r:bom|utf-8') { |f| self.load f, filename }
|
||
|
end
|
||
|
# :stopdoc:
|
||
| ext/psych/lib/psych/core_ext.rb | ||
|---|---|---|
|
alias :yaml_as :psych_yaml_as
|
||
|
end
|
||
|
if defined?(::IRB)
|
||
|
module Kernel
|
||
|
def psych_y *objects
|
||
|
puts Psych.dump_stream(*objects)
|
||
| ... | ... | |
|
alias y psych_y
|
||
|
private :y
|
||
|
end
|
||
|
end
|
||
| ext/psych/lib/psych/handlers/document_stream.rb | ||
|---|---|---|
|
require 'psych/tree_builder'
|
||
|
module Psych
|
||
|
module Handlers
|
||
|
class DocumentStream < Psych::TreeBuilder # :nodoc:
|
||
|
def initialize &block
|
||
|
super
|
||
|
@block = block
|
||
|
end
|
||
|
def start_document version, tag_directives, implicit
|
||
|
n = Nodes::Document.new version, tag_directives, implicit
|
||
|
push n
|
||
|
end
|
||
|
def end_document implicit_end = !streaming?
|
||
|
@last.implicit_end = implicit_end
|
||
|
@block.call pop
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
| ext/psych/lib/psych/json.rb | ||
|---|---|---|
|
module Psych
|
||
|
module JSON
|
||
|
autoload :TreeBuilder, 'psych/json/tree_builder'
|
||
|
autoload :Stream, 'psych/json/stream'
|
||
|
end
|
||
|
end
|
||
| ext/psych/lib/psych/parser.rb | ||
|---|---|---|
|
# The handler on which events will be called
|
||
|
attr_accessor :handler
|
||
|
# Set the encoding for this parser to +encoding+
|
||
|
attr_writer :external_encoding
|
||
|
###
|
||
|
# Creates a new Psych::Parser instance with +handler+. YAML events will
|
||
|
# be called on +handler+. See Psych::Parser for more details.
|
||
|
def initialize handler = Handler.new
|
||
|
@handler = handler
|
||
|
@external_encoding = ANY
|
||
|
end
|
||
|
end
|
||
|
end
|
||
| ext/psych/lib/psych/scalar_scanner.rb | ||
|---|---|---|
|
end
|
||
|
when TIME
|
||
|
parse_time string
|
||
|
when /^\d{4}-\d{1,2}-\d{1,2}$/
|
||
|
when /^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/
|
||
|
require 'date'
|
||
|
Date.strptime(string, '%Y-%m-%d')
|
||
|
begin
|
||
|
Date.strptime(string, '%Y-%m-%d')
|
||
|
rescue ArgumentError
|
||
|
string
|
||
|
end
|
||
|
when /^\.inf$/i
|
||
|
1 / 0.0
|
||
|
when /^-\.inf$/i
|
||
| ... | ... | |
|
else
|
||
|
string.sub(/^:/, '').to_sym
|
||
|
end
|
||
|
when /^[-+]?[1-9][0-9_]*(:[0-5]?[0-9])+$/
|
||
|
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 FLOAT
|
||
|
return Float(string.gsub(/[,_]/, '')) rescue ArgumentError
|
||
|
begin
|
||
|
return Float(string.gsub(/[,_]/, ''))
|
||
|
rescue ArgumentError
|
||
|
end
|
||
|
@string_cache[string] = true
|
||
|
string
|
||
|
else
|
||
|
if string.count('.') < 2
|
||
|
return Integer(string.gsub(/[,_]/, '')) rescue ArgumentError
|
||
|
begin
|
||
|
return Integer(string.gsub(/[,_]/, ''))
|
||
|
rescue ArgumentError
|
||
|
end
|
||
|
end
|
||
|
@string_cache[string] = true
|
||
| ext/psych/lib/psych/syntax_error.rb | ||
|---|---|---|
|
module Psych
|
||
|
class SyntaxError < ::SyntaxError
|
||
|
attr_reader :file, :line, :column, :offset, :problem, :context
|
||
|
def initialize file, line, col, offset, problem, context
|
||
|
err = [problem, context].compact.join ' '
|
||
|
filename = file || '<unknown>'
|
||
|
message = "(%s): %s at line %d column %d" % [filename, err, line, col]
|
||
|
@file = file
|
||
|
@line = line
|
||
|
@column = col
|
||
|
@offset = offset
|
||
|
@problem = problem
|
||
|
@context = context
|
||
|
super(message)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
| ext/psych/lib/psych/tree_builder.rb | ||
|---|---|---|
|
end
|
||
|
def scalar value, anchor, tag, plain, quoted, style
|
||
|
@last.children << Nodes::Scalar.new(value,anchor,tag,plain,quoted,style)
|
||
|
s = Nodes::Scalar.new(value,anchor,tag,plain,quoted,style)
|
||
|
@last.children << s
|
||
|
s
|
||
|
end
|
||
|
def alias anchor
|
||
| ext/psych/lib/psych/visitors/to_ruby.rb | ||
|---|---|---|
|
result
|
||
|
end
|
||
|
def visit_Psych_Nodes_Scalar o
|
||
|
@st[o.anchor] = o.value if o.anchor
|
||
|
def deserialize o
|
||
|
if klass = Psych.load_tags[o.tag]
|
||
|
instance = klass.allocate
|
||
| ... | ... | |
|
case o.tag
|
||
|
when '!binary', 'tag:yaml.org,2002:binary'
|
||
|
o.value.unpack('m').first
|
||
|
when '!str', 'tag:yaml.org,2002:str'
|
||
|
o.value
|
||
|
when /^!(?:str|ruby\/string)(?::(.*))?/, 'tag:yaml.org,2002:str'
|
||
|
klass = resolve_class($1)
|
||
|
if klass
|
||
|
klass.allocate.replace o.value
|
||
|
else
|
||
|
o.value
|
||
|
end
|
||
|
when '!ruby/object:BigDecimal'
|
||
|
require 'bigdecimal'
|
||
|
BigDecimal._load o.value
|
||
|
when "!ruby/object:DateTime"
|
||
|
require 'date'
|
||
|
@ss.parse_time(o.value).to_datetime
|
||
| ... | ... | |
|
@ss.tokenize o.value
|
||
|
end
|
||
|
end
|
||
|
private :deserialize
|
||
|
def visit_Psych_Nodes_Scalar o
|
||
|
register o, deserialize(o)
|
||
|
end
|
||
|
def visit_Psych_Nodes_Sequence o
|
||
|
if klass = Psych.load_tags[o.tag]
|
||
| ... | ... | |
|
case o.tag
|
||
|
when '!omap', 'tag:yaml.org,2002:omap'
|
||
|
map = Psych::Omap.new
|
||
|
@st[o.anchor] = map if o.anchor
|
||
|
map = register(o, Psych::Omap.new)
|
||
|
o.children.each { |a|
|
||
|
map[accept(a.children.first)] = accept a.children.last
|
||
|
}
|
||
|
map
|
||
|
when /^!(?:seq|ruby\/array):(.*)$/
|
||
|
klass = resolve_class($1)
|
||
|
list = register(o, klass.allocate)
|
||
|
o.children.each { |c| list.push accept c }
|
||
|
list
|
||
|
else
|
||
|
list = []
|
||
|
@st[o.anchor] = list if o.anchor
|
||
|
list = register(o, [])
|
||
|
o.children.each { |c| list.push accept c }
|
||
|
list
|
||
|
end
|
||
| ... | ... | |
|
return revive_hash({}, o) unless o.tag
|
||
|
case o.tag
|
||
|
when '!str', 'tag:yaml.org,2002:str'
|
||
|
when /^!(?:str|ruby\/string)(?::(.*))?/, 'tag:yaml.org,2002:str'
|
||
|
klass = resolve_class($1)
|
||
|
members = Hash[*o.children.map { |c| accept c }]
|
||
|
string = members.delete 'str'
|
||
|
if klass
|
||
|
string = klass.allocate
|
||
|
string.replace string
|
||
|
end
|
||
|
init_with(string, members.map { |k,v| [k.to_s.sub(/^@/, ''),v] }, o)
|
||
|
when /^!ruby\/array:(.*)$/
|
||
|
klass = resolve_class($1)
|
||
|
list = register(o, klass.allocate)
|
||
|
members = Hash[o.children.map { |c| accept c }.each_slice(2).to_a]
|
||
|
list.replace members['internal']
|
||
|
members['ivars'].each do |ivar, v|
|
||
|
list.instance_variable_set ivar, v
|
||
|
end
|
||
|
list
|
||
|
when /^!ruby\/struct:?(.*)?$/
|
||
|
klass = resolve_class($1)
|
||
|
if klass
|
||
|
s = klass.allocate
|
||
|
@st[o.anchor] = s if o.anchor
|
||
|
s = register(o, klass.allocate)
|
||
|
members = {}
|
||
|
struct_members = s.members.map { |x| x.to_sym }
|
||
| ... | ... | |
|
when '!ruby/range'
|
||
|
h = Hash[*o.children.map { |c| accept c }]
|
||
|
Range.new(h['begin'], h['end'], h['excl'])
|
||
|
register o, Range.new(h['begin'], h['end'], h['excl'])
|
||
|
when /^!ruby\/exception:?(.*)?$/
|
||
|
h = Hash[*o.children.map { |c| accept c }]
|
||
| ... | ... | |
|
when '!ruby/object:Complex'
|
||
|
h = Hash[*o.children.map { |c| accept c }]
|
||
|
Complex(h['real'], h['image'])
|
||
|
register o, Complex(h['real'], h['image'])
|
||
|
when '!ruby/object:Rational'
|
||
|
h = Hash[*o.children.map { |c| accept c }]
|
||
|
Rational(h['numerator'], h['denominator'])
|
||
|
register o, Rational(h['numerator'], h['denominator'])
|
||
|
when /^!ruby\/object:?(.*)?$/
|
||
|
name = $1 || 'Object'
|
||
| ... | ... | |
|
end
|
||
|
def visit_Psych_Nodes_Alias o
|
||
|
@st[o.anchor]
|
||
|
@st.fetch(o.anchor) { raise BadAlias, "Unknown alias: #{o.anchor}" }
|
||
|
end
|
||
|
private
|
||
|
def register node, object
|
||
|
@st[node.anchor] = object if node.anchor
|
||
|
object
|
||
|
end
|
||
|
def revive_hash hash, o
|
||
|
@st[o.anchor] = hash if o.anchor
|
||
| ext/psych/lib/psych/visitors/yaml_tree.rb | ||
|---|---|---|
|
end
|
||
|
def visit_Regexp o
|
||
|
@emitter.scalar o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY
|
||
|
register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY)
|
||
|
end
|
||
|
def visit_DateTime o
|
||
|
formatted = format_time o.to_time
|
||
|
tag = '!ruby/object:DateTime'
|
||
|
@emitter.scalar formatted, nil, tag, false, false, Nodes::Scalar::ANY
|
||
|
register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY)
|
||
|
end
|
||
|
def visit_Time o
|
||
| ... | ... | |
|
end
|
||
|
def visit_Rational o
|
||
|
@emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK)
|
||
|
register o, @emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK)
|
||
|
[
|
||
|
'denominator', o.denominator.to_s,
|
||
| ... | ... | |
|
end
|
||
|
def visit_Complex o
|
||
|
@emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK)
|
||
|
register o, @emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK)
|
||
|
['real', o.real.to_s, 'image', o.imag.to_s].each do |m|
|
||
|
@emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
|
||
| ... | ... | |
|
end
|
||
|
end
|
||
|
def visit_BigDecimal o
|
||
|
@emitter.scalar o._dump, nil, '!ruby/object:BigDecimal', false, false, Nodes::Scalar::ANY
|
||
|
end
|
||
|
def binary? string
|
||
|
string.encoding == Encoding::ASCII_8BIT ||
|
||
|
string.index("\x00") ||
|
||
| ... | ... | |
|
ivars = find_ivars o
|
||
|
if ivars.empty?
|
||
|
unless o.class == ::String
|
||
|
tag = "!ruby/string:#{o.class}"
|
||
|
end
|
||
|
@emitter.scalar str, nil, tag, plain, quote, style
|
||
|
else
|
||
|
@emitter.start_mapping nil, '!str', false, Nodes::Mapping::BLOCK
|
||
|
maptag = '!ruby/string'
|
||
|
maptag << ":#{o.class}" unless o.class == ::String
|
||
|
@emitter.start_mapping nil, maptag, false, Nodes::Mapping::BLOCK
|
||
|
@emitter.scalar 'str', nil, nil, true, false, Nodes::Scalar::ANY
|
||
|
@emitter.scalar str, nil, tag, plain, quote, style
|
||
| ... | ... | |
|
def visit_Module o
|
||
|
raise TypeError, "can't dump anonymous module: #{o}" unless o.name
|
||
|
@emitter.scalar o.name, nil, '!ruby/module', false, false, Nodes::Scalar::SINGLE_QUOTED
|
||
|
register o, @emitter.scalar(o.name, nil, '!ruby/module', false, false, Nodes::Scalar::SINGLE_QUOTED)
|
||
|
end
|
||
|
def visit_Class o
|
||
|
raise TypeError, "can't dump anonymous class: #{o}" unless o.name
|
||
|
@emitter.scalar o.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED
|
||
|
register o, @emitter.scalar(o.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED)
|
||
|
end
|
||
|
def visit_Range o
|
||
|
@emitter.start_mapping nil, '!ruby/range', false, Nodes::Mapping::BLOCK
|
||
|
register o, @emitter.start_mapping(nil, '!ruby/range', false, Nodes::Mapping::BLOCK)
|
||
|
['begin', o.begin, 'end', o.end, 'excl', o.exclude_end?].each do |m|
|
||
|
accept m
|
||
|
end
|
||
| ... | ... | |
|
end
|
||
|
def visit_Array o
|
||
|
register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
|
||
|
o.each { |c| accept c }
|
||
|
@emitter.end_sequence
|
||
|
if o.class == ::Array
|
||
|
register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
|
||
|
o.each { |c| accept c }
|
||
|
@emitter.end_sequence
|
||
|
else
|
||
|
visit_array_subclass o
|
||
|
end
|
||
|
end
|
||
|
def visit_NilClass o
|
||
| ... | ... | |
|
end
|
||
|
private
|
||
|
def visit_array_subclass o
|
||
|
tag = "!ruby/array:#{o.class}"
|
||
|
if o.instance_variables.empty?
|
||
|
node = @emitter.start_sequence(nil, tag, false, Nodes::Sequence::BLOCK)
|
||
|
register o, node
|
||
|
o.each { |c| accept c }
|
||
|
@emitter.end_sequence
|
||
|
else
|
||
|
node = @emitter.start_mapping(nil, tag, false, Nodes::Sequence::BLOCK)
|
||
|
register o, node
|
||
|
# Dump the internal list
|
||
|
accept 'internal'
|
||
|
@emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
|
||
|
o.each { |c| accept c }
|
||
|
@emitter.end_sequence
|
||
|
# Dump the ivars
|
||
|
accept 'ivars'
|
||
|
@emitter.start_mapping(nil, nil, true, Nodes::Sequence::BLOCK)
|
||
|
o.instance_variables.each do |ivar|
|
||
|
accept ivar
|
||
|
accept o.instance_variable_get ivar
|
||
|
end
|
||
|
@emitter.end_mapping
|
||
|
@emitter.end_mapping
|
||
|
end
|
||
|
end
|
||
|
def dump_list o
|
||
|
end
|
||
|
# '%:z' was no defined until 1.9.3
|
||
|
if RUBY_VERSION < '1.9.3'
|
||
|
def format_time time
|
||
| ext/psych/parser.c | ||
|---|---|---|
|
return Data_Wrap_Struct(klass, 0, dealloc, parser);
|
||
|
}
|
||
|
static VALUE make_exception(yaml_parser_t * parser, VALUE path)
|
||
|
{
|
||
|
size_t line, column;
|
||
|
line = parser->context_mark.line + 1;
|
||
|
column = parser->context_mark.column + 1;
|
||
|
return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6,
|
||
|
path,
|
||
|
INT2NUM(line),
|
||
|
INT2NUM(column),
|
||
|
INT2NUM(parser->problem_offset),
|
||
|
parser->problem ? rb_usascii_str_new2(parser->problem) : Qnil,
|
||
|
parser->context ? rb_usascii_str_new2(parser->context) : Qnil);
|
||
|
}
|
||
|
#ifdef HAVE_RUBY_ENCODING_H
|
||
|
static VALUE transcode_string(VALUE src, int * parser_encoding)
|
||
|
{
|
||
|
int utf8 = rb_utf8_encindex();
|
||
|
int utf16le = rb_enc_find_index("UTF16_LE");
|
||
|
int utf16be = rb_enc_find_index("UTF16_BE");
|
||
|
int source_encoding = rb_enc_get_index(src);
|
||
|
if (source_encoding == utf8) {
|
||
|
*parser_encoding = YAML_UTF8_ENCODING;
|
||
|
return src;
|
||
|
}
|
||
|
if (source_encoding == utf16le) {
|
||
|
*parser_encoding = YAML_UTF16LE_ENCODING;
|
||
|
return src;
|
||
|
}
|
||
|
if (source_encoding == utf16be) {
|
||
|
*parser_encoding = YAML_UTF16BE_ENCODING;
|
||
|
return src;
|
||
|
}
|
||
|
src = rb_str_export_to_enc(src, rb_utf8_encoding());
|
||
|
RB_GC_GUARD(src);
|
||
|
*parser_encoding = YAML_UTF8_ENCODING;
|
||
|
return src;
|
||
|
}
|
||
|
static VALUE transcode_io(VALUE src, int * parser_encoding)
|
||
|
{
|
||
|
VALUE io_external_encoding;
|
||
|
int io_external_enc_index;
|
||
|
io_external_encoding = rb_funcall(src, rb_intern("external_encoding"), 0);
|
||
|
/* if no encoding is returned, assume ascii8bit. */
|
||
|
if (NIL_P(io_external_encoding)) {
|
||
|
io_external_enc_index = rb_ascii8bit_encindex();
|
||
|
} else {
|
||
|
io_external_enc_index = rb_to_encoding_index(io_external_encoding);
|
||
|
}
|
||
|
/* Treat US-ASCII as utf_8 */
|
||
|
if (io_external_enc_index == rb_usascii_encindex()) {
|
||
|
*parser_encoding = YAML_UTF8_ENCODING;
|
||
|
return src;
|
||
|
}
|
||
|
if (io_external_enc_index == rb_utf8_encindex()) {
|
||
|
*parser_encoding = YAML_UTF8_ENCODING;
|
||
|
return src;
|
||
|
}
|
||
|
if (io_external_enc_index == rb_enc_find_index("UTF-16LE")) {
|
||
|
*parser_encoding = YAML_UTF16LE_ENCODING;
|
||
|
return src;
|
||
|
}
|
||
|
if (io_external_enc_index == rb_enc_find_index("UTF-16BE")) {
|
||
|
*parser_encoding = YAML_UTF16BE_ENCODING;
|
||
|
return src;
|
||
|
}
|
||
|
/* Just guess on ASCII-8BIT */
|
||
|
if (io_external_enc_index == rb_ascii8bit_encindex()) {
|
||
|
*parser_encoding = YAML_ANY_ENCODING;
|
||
|
return src;
|
||
|
}
|
||
|
rb_raise(rb_eArgError, "YAML file must be UTF-8, UTF-16LE, or UTF-16BE, not %s",
|
||
|
rb_enc_name(rb_enc_from_index(io_external_enc_index)));
|
||
|
return Qnil;
|
||
|
}
|
||
|
#endif
|
||
|
static VALUE protected_start_stream(VALUE pointer)
|
||
|
{
|
||
|
VALUE *args = (VALUE *)pointer;
|
||
|
return rb_funcall(args[0], id_start_stream, 1, args[1]);
|
||
|
}
|
||
|
static VALUE protected_start_document(VALUE pointer)
|
||
|
{
|
||
|
VALUE *args = (VALUE *)pointer;
|
||
|
return rb_funcall3(args[0], id_start_document, 3, args + 1);
|
||
|
}
|
||
|
static VALUE protected_end_document(VALUE pointer)
|
||
|
{
|
||
|
VALUE *args = (VALUE *)pointer;
|
||
|
return rb_funcall(args[0], id_end_document, 1, args[1]);
|
||
|
}
|
||
|
static VALUE protected_alias(VALUE pointer)
|
||
|
{
|
||
|
VALUE *args = (VALUE *)pointer;
|
||
|
return rb_funcall(args[0], id_alias, 1, args[1]);
|
||
|
}
|
||
|
static VALUE protected_scalar(VALUE pointer)
|
||
|
{
|
||
|
VALUE *args = (VALUE *)pointer;
|
||
|
return rb_funcall3(args[0], id_scalar, 6, args + 1);
|
||
|
}
|
||
|
static VALUE protected_start_sequence(VALUE pointer)
|
||
|
{
|
||
|
VALUE *args = (VALUE *)pointer;
|
||
|
return rb_funcall3(args[0], id_start_sequence, 4, args + 1);
|
||
|
}
|
||
|
static VALUE protected_end_sequence(VALUE handler)
|
||
|
{
|
||
|
return rb_funcall(handler, id_end_sequence, 0);
|
||
|
}
|
||
|
static VALUE protected_start_mapping(VALUE pointer)
|
||
|
{
|
||
|
VALUE *args = (VALUE *)pointer;
|
||
|
return rb_funcall3(args[0], id_start_mapping, 4, args + 1);
|
||
|
}
|
||
|
static VALUE protected_end_mapping(VALUE handler)
|
||
|
{
|
||
|
return rb_funcall(handler, id_end_mapping, 0);
|
||
|
}
|
||
|
static VALUE protected_empty(VALUE handler)
|
||
|
{
|
||
|
return rb_funcall(handler, id_empty, 0);
|
||
|
}
|
||
|
static VALUE protected_end_stream(VALUE handler)
|
||
|
{
|
||
|
return rb_funcall(handler, id_end_stream, 0);
|
||
|
}
|
||
|
/*
|
||
|
* call-seq:
|
||
|
* parser.parse(yaml)
|
||
| ... | ... | |
|
*
|
||
|
* See Psych::Parser and Psych::Parser#handler
|
||
|
*/
|
||
|
static VALUE parse(VALUE self, VALUE yaml)
|
||
|
static VALUE parse(int argc, VALUE *argv, VALUE self)
|
||
|
{
|
||
|
VALUE yaml, path;
|
||
|
yaml_parser_t * parser;
|
||
|
yaml_event_t event;
|
||
|
int done = 0;
|
||
|
int tainted = 0;
|
||
|
int state = 0;
|
||
|
int parser_encoding = YAML_ANY_ENCODING;
|
||
|
#ifdef HAVE_RUBY_ENCODING_H
|
||
|
int encoding = rb_utf8_encindex();
|
||
|
rb_encoding * internal_enc = rb_default_internal_encoding();
|
||
|
#endif
|
||
|
VALUE handler = rb_iv_get(self, "@handler");
|
||
|
if (rb_scan_args(argc, argv, "11", &yaml, &path) == 1) {
|
||
|
if(rb_respond_to(yaml, id_path))
|
||
|
path = rb_funcall(yaml, id_path, 0);
|
||
|
else
|
||
|
path = rb_str_new2("<unknown>");
|
||
|
}
|
||
|
Data_Get_Struct(self, yaml_parser_t, parser);
|
||
|
yaml_parser_delete(parser);
|
||
|
yaml_parser_initialize(parser);
|
||
|
if (OBJ_TAINTED(yaml)) tainted = 1;
|
||
|
if(rb_respond_to(yaml, id_read)) {
|
||
|
if (rb_respond_to(yaml, id_read)) {
|
||
|
#ifdef HAVE_RUBY_ENCODING_H
|
||
|
yaml = transcode_io(yaml, &parser_encoding);
|
||
|
yaml_parser_set_encoding(parser, parser_encoding);
|
||
|
#endif
|
||
|
yaml_parser_set_input(parser, io_reader, (void *)yaml);
|
||
|
if (RTEST(rb_obj_is_kind_of(yaml, rb_cIO))) tainted = 1;
|
||
|
} else {
|
||
|
StringValue(yaml);
|
||
|
#ifdef HAVE_RUBY_ENCODING_H
|
||
|
yaml = transcode_string(yaml, &parser_encoding);
|
||
|
yaml_parser_set_encoding(parser, parser_encoding);
|
||
|
#endif
|
||
|
yaml_parser_set_input_string(
|
||
|
parser,
|
||
|
(const unsigned char *)RSTRING_PTR(yaml),
|
||
| ... | ... | |
|
while(!done) {
|
||
|
if(!yaml_parser_parse(parser, &event)) {
|
||
|
VALUE path;
|
||
|
size_t line = parser->mark.line;
|
||
|
size_t column = parser->mark.column;
|
||
|
if(rb_respond_to(yaml, id_path))
|
||
|
path = rb_funcall(yaml, id_path, 0);
|
||
|
else
|
||
|
path = rb_str_new2("<unknown>");
|
||
|
VALUE exception;
|
||
|
exception = make_exception(parser, path);
|
||
|
yaml_parser_delete(parser);
|
||
|
yaml_parser_initialize(parser);
|
||
|
rb_raise(ePsychSyntaxError, "(%s): couldn't parse YAML at line %d column %d",
|
||
|
StringValuePtr(path),
|
||
|
(int)line, (int)column);
|
||
|
rb_exc_raise(exception);
|
||
|
}
|
||
|
switch(event.type) {
|
||
|
case YAML_STREAM_START_EVENT:
|
||
|
rb_funcall(handler, id_start_stream, 1,
|
||
|
INT2NUM((long)event.data.stream_start.encoding)
|
||
|
);
|
||
|
break;
|
||
|
case YAML_STREAM_START_EVENT:
|
||
|
{
|
||
|
VALUE args[2];
|
||
|
args[0] = handler;
|
||
|
args[1] = INT2NUM((long)event.data.stream_start.encoding);
|
||
|
rb_protect(protected_start_stream, (VALUE)args, &state);
|
||
|
}
|
||
|
break;
|
||
|
case YAML_DOCUMENT_START_EVENT:
|
||
|
{
|
||
|
VALUE args[4];
|
||
|
/* Get a list of tag directives (if any) */
|
||
|
VALUE tag_directives = rb_ary_new();
|
||
|
/* Grab the document version */
|
||
| ... | ... | |
|
rb_ary_push(tag_directives, rb_ary_new3((long)2, handle, prefix));
|
||
|
}
|
||
|
}
|
||
|
rb_funcall(handler, id_start_document, 3,
|
||
|
version, tag_directives,
|
||
|
event.data.document_start.implicit == 1 ? Qtrue : Qfalse
|
||
|
);
|
||
|
args[0] = handler;
|
||
|
args[1] = version;
|
||
|
args[2] = tag_directives;
|
||
|
args[3] = event.data.document_start.implicit == 1 ? Qtrue : Qfalse;
|
||
|
rb_protect(protected_start_document, (VALUE)args, &state);
|
||
|
}
|
||
|
break;
|
||
|
case YAML_DOCUMENT_END_EVENT:
|
||
|
rb_funcall(handler, id_end_document, 1,
|
||
|
event.data.document_end.implicit == 1 ? Qtrue : Qfalse
|
||
|
);
|
||
|
{
|
||
|
VALUE args[2];
|
||
|
args[0] = handler;
|
||
|
args[1] = event.data.document_end.implicit == 1 ? Qtrue : Qfalse;
|
||
|
rb_protect(protected_end_document, (VALUE)args, &state);
|
||
|
}
|
||
|
break;
|
||
|
case YAML_ALIAS_EVENT:
|
||
|
{
|
||
|
VALUE args[2];
|
||
|
VALUE alias = Qnil;
|
||
|
if(event.data.alias.anchor) {
|
||
|
alias = rb_str_new2((const char *)event.data.alias.anchor);
|
||
| ... | ... | |
|
#endif
|
||
|
}
|
||
|
rb_funcall(handler, id_alias, 1, alias);
|
||
|
args[0] = handler;
|
||
|
args[1] = alias;
|
||
|
rb_protect(protected_alias, (VALUE)args, &state);
|
||
|
}
|
||
|
break;
|
||
|
case YAML_SCALAR_EVENT:
|
||
|
{
|
||
|
VALUE args[7];
|
||
|
VALUE anchor = Qnil;
|
||
|
VALUE tag = Qnil;
|
||
|
VALUE plain_implicit, quoted_implicit, style;
|
||
| ... | ... | |
|
style = INT2NUM((long)event.data.scalar.style);
|
||
|
rb_funcall(handler, id_scalar, 6,
|
||
|
val, anchor, tag, plain_implicit, quoted_implicit, style);
|
||
|
args[0] = handler;
|
||
|
args[1] = val;
|
||
|
args[2] = anchor;
|
||
|
args[3] = tag;
|
||
|
args[4] = plain_implicit;
|
||
|
args[5] = quoted_implicit;
|
||
|
args[6] = style;
|
||
|
rb_protect(protected_scalar, (VALUE)args, &state);
|
||
|
}
|
||
|
break;
|
||
|
case YAML_SEQUENCE_START_EVENT:
|
||
|
{
|
||
|
VALUE args[5];
|
||
|
VALUE anchor = Qnil;
|
||
|
VALUE tag = Qnil;
|
||
|
VALUE implicit, style;
|
||
| ... | ... | |
|
style = INT2NUM((long)event.data.sequence_start.style);
|
||
|
rb_funcall(handler, id_start_sequence, 4,
|
||
|
anchor, tag, implicit, style);
|
||
|
args[0] = handler;
|
||
|
args[1] = anchor;
|
||
|
args[2] = tag;
|
||
|
args[3] = implicit;
|
||
|
args[4] = style;
|
||
|
rb_protect(protected_start_sequence, (VALUE)args, &state);
|
||
|
}
|
||
|
break;
|
||
|
case YAML_SEQUENCE_END_EVENT:
|
||
|
rb_funcall(handler, id_end_sequence, 0);
|
||
|
rb_protect(protected_end_sequence, handler, &state);
|
||
|
break;
|
||
|
case YAML_MAPPING_START_EVENT:
|
||
|
{
|
||
|
VALUE args[5];
|
||
|
VALUE anchor = Qnil;
|
||
|
VALUE tag = Qnil;
|
||
|
VALUE implicit, style;
|
||
| ... | ... | |
|
style = INT2NUM((long)event.data.mapping_start.style);
|
||
|
rb_funcall(handler, id_start_mapping, 4,
|
||
|
anchor, tag, implicit, style);
|
||
|
args[0] = handler;
|
||
|
args[1] = anchor;
|
||
|
args[2] = tag;
|
||
|
args[3] = implicit;
|
||
|
args[4] = style;
|
||
|
rb_protect(protected_start_mapping, (VALUE)args, &state);
|
||
|
}
|
||
|
break;
|
||
|
case YAML_MAPPING_END_EVENT:
|
||
|
rb_funcall(handler, id_end_mapping, 0);
|
||
|
rb_protect(protected_end_mapping, handler, &state);
|
||
|
break;
|
||
|
case YAML_NO_EVENT:
|
||
|
rb_funcall(handler, id_empty, 0);
|
||
|
rb_protect(protected_empty, handler, &state);
|
||
|
break;
|
||
|
case YAML_STREAM_END_EVENT:
|
||
|
rb_funcall(handler, id_end_stream, 0);
|
||
|
rb_protect(protected_end_stream, handler, &state);
|
||
|
done = 1;
|
||
|
break;
|
||
|
}
|
||
|
yaml_event_delete(&event);
|
||
|
if (state) rb_jump_tag(state);
|
||
|
}
|
||
|
return self;
|
||
| ... | ... | |
|
/*
|
||
|
* call-seq:
|
||
|
* parser.external_encoding=(encoding)
|
||
|
*
|
||
|
* Set the encoding for this parser to +encoding+
|
||
|
*/
|
||
|
static VALUE set_external_encoding(VALUE self, VALUE encoding)
|
||
|
{
|
||
|
yaml_parser_t * parser;
|
||
|
VALUE exception;
|
||
|
Data_Get_Struct(self, yaml_parser_t, parser);
|
||
|
if(parser->encoding) {
|
||
|
exception = rb_const_get_at(mPsych, rb_intern("Exception"));
|
||
|
rb_raise(exception, "don't set the encoding twice!");
|
||
|
}
|
||
|
yaml_parser_set_encoding(parser, NUM2INT(encoding));
|
||
|
return encoding;
|
||
|
}
|
||
|
/*
|
||
|
* call-seq:
|
||
|
* parser.mark # => #<Psych::Parser::Mark>
|
||
|
*
|
||
|
* Returns a Psych::Parser::Mark object that contains line, column, and index
|
||
| ... | ... | |
|
/* UTF-16-BE Encoding with BOM */
|
||
|
rb_define_const(cPsychParser, "UTF16BE", INT2NUM(YAML_UTF16BE_ENCODING));
|
||
|
rb_require("psych/syntax_error");
|
||
|
ePsychSyntaxError = rb_define_class_under(mPsych, "SyntaxError", rb_eSyntaxError);
|
||
|
rb_define_method(cPsychParser, "parse", parse, 1);
|
||
|
rb_define_method(cPsychParser, "parse", parse, -1);
|
||
|
rb_define_method(cPsychParser, "mark", mark, 0);
|
||
|
rb_define_method(cPsychParser, "external_encoding=", set_external_encoding, 1);
|
||
|
id_read = rb_intern("read");
|
||
|
id_path = rb_intern("path");
|
||
| test/psych/test_array.rb | ||
|---|---|---|
|
module Psych
|
||
|
class TestArray < TestCase
|
||
|
class X < Array
|
||
|
end
|
||
|
class Y < Array
|
||
|
attr_accessor :val
|
||
|
end
|
||
|
def setup
|
||
|
super
|
||
|
@list = [{ :a => 'b' }, 'foo']
|
||
|
end
|
||
|
def test_subclass
|
||
|
yaml = Psych.dump X.new
|
||
|
assert_match X.name, yaml
|
||
|
list = X.new
|
||
|
list << 1
|
||
|
assert_equal X, list.class
|
||
|
assert_equal 1, list.first
|
||
|
end
|
||
|
def test_subclass_with_attributes
|
||
|
y = Psych.load Psych.dump Y.new.tap {|y| y.val = 1}
|
||
|
assert_equal Y, y.class
|
||
|
assert_equal 1, y.val
|
||
|
end
|
||
|
def test_backwards_with_syck
|
||
|
x = Psych.load "--- !seq:#{X.name} []\n\n"
|
||
|
assert_equal X, x.class
|
||
|
end
|
||
|
def test_self_referential
|
||
|
@list << @list
|
||
|
assert_cycle(@list)
|
||
| test/psych/test_encoding.rb | ||
|---|---|---|
|
@emitter = Psych::Emitter.new @buffer
|
||
|
end
|
||
|
def test_transcode_shiftjis
|
||
|
str = "こんにちは!"
|
||
|
loaded = Psych.load("--- こんにちは!".encode('SHIFT_JIS'))
|
||
|
assert_equal str, loaded
|
||
|
end
|
||
|
def test_transcode_utf16le
|
||
|
str = "こんにちは!"
|
||
|
loaded = Psych.load("--- こんにちは!".encode('UTF-16LE'))
|
||
|
assert_equal str, loaded
|
||
|
end
|
||
|
def test_transcode_utf16be
|
||
|
str = "こんにちは!"
|
||
|
loaded = Psych.load("--- こんにちは!".encode('UTF-16BE'))
|
||
|
assert_equal str, loaded
|
||
|
end
|
||
|
def test_io_shiftjis
|
||
|
t = Tempfile.new(['shiftjis', 'yml'], :encoding => 'SHIFT_JIS')
|
||
|
t.write '--- こんにちは!'
|
||
|
t.close
|
||
|
# If the external encoding isn't utf8, utf16le, or utf16be, we cannot
|
||
|
# process the file.
|
||
|
File.open(t.path, 'r', :encoding => 'SHIFT_JIS') do |f|
|
||
|
assert_raises ArgumentError do
|
||
|
Psych.load(f)
|
||
|
end
|
||
|
end
|
||
|
t.close(true)
|
||
|
end
|
||
|
def test_io_utf16le
|
||
|
t = Tempfile.new(['utf16le', 'yml'])
|
||
|
t.binmode
|
||
|
t.write '--- こんにちは!'.encode('UTF-16LE')
|
||
|
t.close
|
||
|
File.open(t.path, 'rb', :encoding => 'UTF-16LE') do |f|
|
||
|
assert_equal "こんにちは!", Psych.load(f)
|
||
|
end
|
||
|
t.close(true)
|
||
|
end
|
||
|
def test_io_utf16be
|
||
|
t = Tempfile.new(['utf16be', 'yml'])
|
||
|
t.binmode
|
||
|
t.write '--- こんにちは!'.encode('UTF-16BE')
|
||
|
t.close
|
||
|
File.open(t.path, 'rb', :encoding => 'UTF-16BE') do |f|
|
||
|
assert_equal "こんにちは!", Psych.load(f)
|
||
|
end
|
||
|
t.close(true)
|
||
|
end
|
||
|
def test_io_utf8
|
||
|
t = Tempfile.new(['utf8', 'yml'])
|
||
|
t.binmode
|
||
|
t.write '--- こんにちは!'.encode('UTF-8')
|
||
|
t.close
|
||
|
File.open(t.path, 'rb', :encoding => 'UTF-8') do |f|
|
||
|
assert_equal "こんにちは!", Psych.load(f)
|
||
|
end
|
||
|
t.close(true)
|
||
|
end
|
||
|
def test_emit_alias
|
||
|
@emitter.start_stream Psych::Parser::UTF8
|
||
|
@emitter.start_document [], [], true
|
||
| test/psych/test_exception.rb | ||
|---|---|---|
|
@wups = Wups.new
|
||
|
end
|
||
|
def test_load_takes_file
|
||
|
ex = assert_raises(Psych::SyntaxError) do
|
||
|
Psych.load '--- `'
|
||
|
end
|
||
|
assert_nil ex.file
|
||
|
ex = assert_raises(Psych::SyntaxError) do
|
||
|
Psych.load '--- `', 'meow'
|
||
|
end
|
||
|
assert_equal 'meow', ex.file
|
||
|
end
|
||
|
def test_psych_parse_stream_takes_file
|
||
|
ex = assert_raises(Psych::SyntaxError) do
|
||
|
Psych.parse_stream '--- `'
|
||
|
end
|
||
|
assert_nil ex.file
|
||
|
assert_match '(<unknown>)', ex.message
|
||
|
ex = assert_raises(Psych::SyntaxError) do
|
||
|
Psych.parse_stream '--- `', 'omg!'
|
||
|
end
|
||
|
assert_equal 'omg!', ex.file
|
||
|
assert_match 'omg!', ex.message
|
||
|
end
|
||
|
def test_load_stream_takes_file
|
||
|
ex = assert_raises(Psych::SyntaxError) do
|
||
|
Psych.load_stream '--- `'
|
||
|
end
|
||
|
assert_nil ex.file
|
||
|
assert_match '(<unknown>)', ex.message
|
||
|
ex = assert_raises(Psych::SyntaxError) do
|
||
|
Psych.load_stream '--- `', 'omg!'
|
||
|
end
|
||
|
assert_equal 'omg!', ex.file
|
||
|
end
|
||
|
def test_parse_file_exception
|
||
|
t = Tempfile.new(['parsefile', 'yml'])
|
||
|
t.binmode
|
||
|
t.write '--- `'
|
||
|
t.close
|
||
|
ex = assert_raises(Psych::SyntaxError) do
|
||
|
Psych.parse_file t.path
|
||
|
end
|
||
|
assert_equal t.path, ex.file
|
||
|
t.close(true)
|
||
|
end
|
||
|
def test_load_file_exception
|
||
|
t = Tempfile.new(['loadfile', 'yml'])
|
||
|
t.binmode
|
||
|
t.write '--- `'
|
||
|
t.close
|
||
|
ex = assert_raises(Psych::SyntaxError) do
|
||
|
Psych.load_file t.path
|
||
|
end
|
||
|
assert_equal t.path, ex.file
|
||
|
t.close(true)
|
||
|
end
|
||
|
def test_psych_parse_takes_file
|
||
|
ex = assert_raises(Psych::SyntaxError) do
|
||
|
Psych.parse '--- `'
|
||
|
end
|
||
|
assert_match '(<unknown>)', ex.message
|
||
|
assert_nil ex.file
|
||
|
ex = assert_raises(Psych::SyntaxError) do
|
||
|
Psych.parse '--- `', 'omg!'
|
||
|
end
|
||
|
assert_match 'omg!', ex.message
|
||
|
end
|
||
|
def test_attributes
|
||
|
e = assert_raises(Psych::SyntaxError) {
|
||
|
Psych.load '--- `foo'
|
||
|
}
|
||
|
assert_nil e.file
|
||
|
assert_equal 1, e.line
|
||
|
assert_equal 5, e.column
|
||
|
# FIXME: offset isn't being set correctly by libyaml
|
||
|
# assert_equal 5, e.offset
|
||
|
assert e.problem
|
||
|
assert e.context
|
||
|
end
|
||
|
def test_convert
|
||
|
w = Psych.load(Psych.dump(@wups))
|
||
|
assert_equal @wups, w
|
||
| test/psych/test_merge_keys.rb | ||
|---|---|---|
|
module Psych
|
||
|
class TestMergeKeys < TestCase
|
||
|
def test_missing_merge_key
|
||
|
yaml = <<-eoyml
|
||
|
bar:
|
||
|
<< : *foo
|
||
|
eoyml
|
||
|
exp = assert_raises(Psych::BadAlias) { Psych.load yaml }
|
||
|
assert_match 'foo', exp.message
|
||
|
end
|
||
|
# [ruby-core:34679]
|
||
|
def test_merge_key
|
||
|
yaml = <<-eoyml
|
||