psych 1.3.4 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.rdoc +138 -0
- data/Manifest.txt +27 -8
- data/README.rdoc +23 -2
- data/Rakefile +1 -1
- data/ext/psych/depend +3 -0
- data/ext/psych/extconf.rb +27 -11
- data/ext/psych/psych.h +4 -4
- data/ext/psych/{emitter.c → psych_emitter.c} +0 -0
- data/ext/psych/{emitter.h → psych_emitter.h} +0 -0
- data/ext/psych/{parser.c → psych_parser.c} +1 -1
- data/ext/psych/{parser.h → psych_parser.h} +0 -0
- data/ext/psych/{to_ruby.c → psych_to_ruby.c} +3 -1
- data/ext/psych/{to_ruby.h → psych_to_ruby.h} +0 -0
- data/ext/psych/{yaml_tree.c → psych_yaml_tree.c} +0 -0
- data/ext/psych/{yaml_tree.h → psych_yaml_tree.h} +0 -0
- data/ext/psych/yaml/LICENSE +19 -0
- data/ext/psych/yaml/api.c +1392 -0
- data/ext/psych/yaml/config.h +11 -0
- data/ext/psych/yaml/dumper.c +394 -0
- data/ext/psych/yaml/emitter.c +2329 -0
- data/ext/psych/yaml/loader.c +432 -0
- data/ext/psych/yaml/parser.c +1374 -0
- data/ext/psych/yaml/reader.c +465 -0
- data/ext/psych/yaml/scanner.c +3570 -0
- data/ext/psych/yaml/writer.c +141 -0
- data/ext/psych/yaml/yaml.h +1971 -0
- data/ext/psych/yaml/yaml_private.h +643 -0
- data/lib/psych.rb +217 -51
- data/lib/psych/class_loader.rb +101 -0
- data/lib/psych/core_ext.rb +1 -8
- data/lib/psych/deprecated.rb +3 -1
- data/lib/psych/exception.rb +13 -0
- data/lib/psych/handler.rb +13 -0
- data/lib/psych/handlers/recorder.rb +39 -0
- data/lib/psych/json/stream.rb +1 -0
- data/lib/psych/nodes/node.rb +3 -1
- data/lib/psych/scalar_scanner.rb +46 -25
- data/lib/psych/stream.rb +1 -0
- data/lib/psych/streaming.rb +10 -5
- data/lib/psych/syntax_error.rb +3 -1
- data/lib/psych/visitors/json_tree.rb +5 -2
- data/lib/psych/visitors/to_ruby.rb +123 -75
- data/lib/psych/visitors/yaml_tree.rb +59 -17
- data/lib/psych/y.rb +9 -0
- data/test/psych/handlers/test_recorder.rb +25 -0
- data/test/psych/helper.rb +30 -1
- data/test/psych/test_alias_and_anchor.rb +1 -1
- data/test/psych/test_array.rb +1 -1
- data/test/psych/test_boolean.rb +1 -1
- data/test/psych/test_class.rb +1 -1
- data/test/psych/test_coder.rb +3 -3
- data/test/psych/test_date_time.rb +1 -1
- data/test/psych/test_deprecated.rb +6 -2
- data/test/psych/test_document.rb +1 -1
- data/test/psych/test_emitter.rb +1 -1
- data/test/psych/test_encoding.rb +51 -65
- data/test/psych/test_engine_manager.rb +1 -11
- data/test/psych/test_exception.rb +40 -19
- data/test/psych/test_hash.rb +1 -1
- data/test/psych/test_json_tree.rb +1 -1
- data/test/psych/test_merge_keys.rb +52 -1
- data/test/psych/test_nil.rb +1 -1
- data/test/psych/test_null.rb +1 -1
- data/test/psych/test_numeric.rb +21 -1
- data/test/psych/test_object.rb +1 -1
- data/test/psych/test_object_references.rb +3 -3
- data/test/psych/test_omap.rb +1 -1
- data/test/psych/test_parser.rb +1 -1
- data/test/psych/test_psych.rb +15 -15
- data/test/psych/test_safe_load.rb +97 -0
- data/test/psych/test_scalar.rb +1 -1
- data/test/psych/test_scalar_scanner.rb +17 -2
- data/test/psych/test_serialize_subclasses.rb +1 -1
- data/test/psych/test_set.rb +1 -1
- data/test/psych/test_stream.rb +1 -1
- data/test/psych/test_string.rb +51 -3
- data/test/psych/test_struct.rb +1 -1
- data/test/psych/test_symbol.rb +1 -1
- data/test/psych/test_tainted.rb +8 -8
- data/test/psych/test_to_yaml_properties.rb +1 -1
- data/test/psych/test_tree_builder.rb +1 -1
- data/test/psych/test_yaml.rb +22 -2
- data/test/psych/test_yamldbm.rb +1 -1
- data/test/psych/test_yamlstore.rb +1 -1
- data/test/psych/visitors/test_to_ruby.rb +5 -4
- data/test/psych/visitors/test_yaml_tree.rb +19 -1
- metadata +45 -34
data/lib/psych/core_ext.rb
CHANGED
data/lib/psych/deprecated.rb
CHANGED
@@ -21,6 +21,7 @@ module Psych
|
|
21
21
|
target.psych_to_yaml unless opts[:nodump]
|
22
22
|
end
|
23
23
|
|
24
|
+
# This method is deprecated, use Psych.load_stream instead.
|
24
25
|
def self.load_documents yaml, &block
|
25
26
|
if $VERBOSE
|
26
27
|
warn "#{caller[0]}: load_documents is deprecated, use load_stream"
|
@@ -34,7 +35,8 @@ module Psych
|
|
34
35
|
warn "#{caller[0]}: detect_implicit is deprecated" if $VERBOSE
|
35
36
|
return '' unless String === thing
|
36
37
|
return 'null' if '' == thing
|
37
|
-
ScalarScanner.new.
|
38
|
+
ss = ScalarScanner.new(ClassLoader.new)
|
39
|
+
ss.tokenize(thing).class.name.downcase
|
38
40
|
end
|
39
41
|
|
40
42
|
def self.add_ruby_type type_tag, &block
|
data/lib/psych/handler.rb
CHANGED
@@ -25,6 +25,19 @@ module Psych
|
|
25
25
|
# Default dumping options
|
26
26
|
OPTIONS = DumperOptions.new
|
27
27
|
|
28
|
+
# Events that a Handler should respond to.
|
29
|
+
EVENTS = [ :alias,
|
30
|
+
:empty,
|
31
|
+
:end_document,
|
32
|
+
:end_mapping,
|
33
|
+
:end_sequence,
|
34
|
+
:end_stream,
|
35
|
+
:scalar,
|
36
|
+
:start_document,
|
37
|
+
:start_mapping,
|
38
|
+
:start_sequence,
|
39
|
+
:start_stream ]
|
40
|
+
|
28
41
|
###
|
29
42
|
# Called with +encoding+ when the YAML stream starts. This method is
|
30
43
|
# called once per stream. A stream may contain multiple documents.
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'psych/handler'
|
2
|
+
|
3
|
+
module Psych
|
4
|
+
module Handlers
|
5
|
+
###
|
6
|
+
# This handler will capture an event and record the event. Recorder events
|
7
|
+
# are available vial Psych::Handlers::Recorder#events.
|
8
|
+
#
|
9
|
+
# For example:
|
10
|
+
#
|
11
|
+
# recorder = Psych::Handlers::Recorder.new
|
12
|
+
# parser = Psych::Parser.new recorder
|
13
|
+
# parser.parse '--- foo'
|
14
|
+
#
|
15
|
+
# recorder.events # => [list of events]
|
16
|
+
#
|
17
|
+
# # Replay the events
|
18
|
+
#
|
19
|
+
# emitter = Psych::Emitter.new $stdout
|
20
|
+
# recorder.events.each do |m, args|
|
21
|
+
# emitter.send m, *args
|
22
|
+
# end
|
23
|
+
|
24
|
+
class Recorder < Psych::Handler
|
25
|
+
attr_reader :events
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@events = []
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
EVENTS.each do |event|
|
33
|
+
define_method event do |*args|
|
34
|
+
@events << [event, args]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/psych/json/stream.rb
CHANGED
data/lib/psych/nodes/node.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'stringio'
|
2
|
+
require 'psych/class_loader'
|
3
|
+
require 'psych/scalar_scanner'
|
2
4
|
|
3
5
|
module Psych
|
4
6
|
module Nodes
|
@@ -32,7 +34,7 @@ module Psych
|
|
32
34
|
#
|
33
35
|
# See also Psych::Visitors::ToRuby
|
34
36
|
def to_ruby
|
35
|
-
Visitors::ToRuby.
|
37
|
+
Visitors::ToRuby.create.accept(self)
|
36
38
|
end
|
37
39
|
alias :transform :to_ruby
|
38
40
|
|
data/lib/psych/scalar_scanner.rb
CHANGED
@@ -8,23 +8,36 @@ module Psych
|
|
8
8
|
TIME = /^\d{4}-\d{1,2}-\d{1,2}([Tt]|\s+)\d{1,2}:\d\d:\d\d(\.\d*)?(\s*Z|[-+]\d{1,2}(:\d\d)?)?/
|
9
9
|
|
10
10
|
# Taken from http://yaml.org/type/float.html
|
11
|
-
FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9
|
11
|
+
FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10)
|
12
12
|
|[-+]?[0-9][0-9_,]*(:[0-5]?[0-9])+\.[0-9_]*(?# base 60)
|
13
13
|
|[-+]?\.(inf|Inf|INF)(?# infinity)
|
14
14
|
|\.(nan|NaN|NAN)(?# not a number))$/x
|
15
15
|
|
16
|
+
# Taken from http://yaml.org/type/int.html
|
17
|
+
INTEGER = /^(?:[-+]?0b[0-1_]+ (?# base 2)
|
18
|
+
|[-+]?0[0-7_]+ (?# base 8)
|
19
|
+
|[-+]?(?:0|[1-9][0-9_]*) (?# base 10)
|
20
|
+
|[-+]?0x[0-9a-fA-F_]+ (?# base 16))$/x
|
21
|
+
|
22
|
+
attr_reader :class_loader
|
23
|
+
|
16
24
|
# Create a new scanner
|
17
|
-
def initialize
|
25
|
+
def initialize class_loader
|
18
26
|
@string_cache = {}
|
27
|
+
@symbol_cache = {}
|
28
|
+
@class_loader = class_loader
|
19
29
|
end
|
20
30
|
|
21
31
|
# Tokenize +string+ returning the ruby object
|
22
32
|
def tokenize string
|
23
33
|
return nil if string.empty?
|
24
34
|
return string if @string_cache.key?(string)
|
35
|
+
return @symbol_cache[string] if @symbol_cache.key?(string)
|
25
36
|
|
26
37
|
case string
|
27
|
-
|
38
|
+
# Check for a String type, being careful not to get caught by hash keys, hex values, and
|
39
|
+
# special floats (e.g., -.inf).
|
40
|
+
when /^[^\d\.:-]?[A-Za-z_\s!@#\$%\^&\*\(\)\{\}\<\>\|\/\\~;=]+/
|
28
41
|
if string.length > 5
|
29
42
|
@string_cache[string] = true
|
30
43
|
return string
|
@@ -45,25 +58,29 @@ module Psych
|
|
45
58
|
string
|
46
59
|
end
|
47
60
|
when TIME
|
48
|
-
|
61
|
+
begin
|
62
|
+
parse_time string
|
63
|
+
rescue ArgumentError
|
64
|
+
string
|
65
|
+
end
|
49
66
|
when /^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/
|
50
67
|
require 'date'
|
51
68
|
begin
|
52
|
-
|
69
|
+
class_loader.date.strptime(string, '%Y-%m-%d')
|
53
70
|
rescue ArgumentError
|
54
71
|
string
|
55
72
|
end
|
56
73
|
when /^\.inf$/i
|
57
|
-
|
74
|
+
Float::INFINITY
|
58
75
|
when /^-\.inf$/i
|
59
|
-
-
|
76
|
+
-Float::INFINITY
|
60
77
|
when /^\.nan$/i
|
61
|
-
|
78
|
+
Float::NAN
|
62
79
|
when /^:./
|
63
80
|
if string =~ /^:(["'])(.*)\1/
|
64
|
-
$2.sub(/^:/, '')
|
81
|
+
@symbol_cache[string] = class_loader.symbolize($2.sub(/^:/, ''))
|
65
82
|
else
|
66
|
-
string.sub(/^:/, '')
|
83
|
+
@symbol_cache[string] = class_loader.symbolize(string.sub(/^:/, ''))
|
67
84
|
end
|
68
85
|
when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+$/
|
69
86
|
i = 0
|
@@ -78,29 +95,33 @@ module Psych
|
|
78
95
|
end
|
79
96
|
i
|
80
97
|
when FLOAT
|
81
|
-
|
82
|
-
|
83
|
-
|
98
|
+
if string == '.'
|
99
|
+
@string_cache[string] = true
|
100
|
+
string
|
101
|
+
else
|
102
|
+
Float(string.gsub(/[,_]|\.$/, ''))
|
84
103
|
end
|
85
|
-
|
86
|
-
@string_cache[string] = true
|
87
|
-
string
|
88
104
|
else
|
89
|
-
|
90
|
-
|
91
|
-
return Integer(string.gsub(/[,_]/, ''))
|
92
|
-
rescue ArgumentError
|
93
|
-
end
|
94
|
-
end
|
105
|
+
int = parse_int string.gsub(/[,_]/, '')
|
106
|
+
return int if int
|
95
107
|
|
96
108
|
@string_cache[string] = true
|
97
109
|
string
|
98
110
|
end
|
99
111
|
end
|
100
112
|
|
113
|
+
###
|
114
|
+
# Parse and return an int from +string+
|
115
|
+
def parse_int string
|
116
|
+
return unless INTEGER === string
|
117
|
+
Integer(string)
|
118
|
+
end
|
119
|
+
|
101
120
|
###
|
102
121
|
# Parse and return a Time from +string+
|
103
122
|
def parse_time string
|
123
|
+
klass = class_loader.load 'Time'
|
124
|
+
|
104
125
|
date, time = *(string.split(/[ tT]/, 2))
|
105
126
|
(yy, m, dd) = date.split('-').map { |x| x.to_i }
|
106
127
|
md = time.match(/(\d+:\d+:\d+)(?:\.(\d*))?\s*(Z|[-+]\d+(:\d\d)?)?/)
|
@@ -108,10 +129,10 @@ module Psych
|
|
108
129
|
(hh, mm, ss) = md[1].split(':').map { |x| x.to_i }
|
109
130
|
us = (md[2] ? Rational("0.#{md[2]}") : 0) * 1000000
|
110
131
|
|
111
|
-
time =
|
132
|
+
time = klass.utc(yy, m, dd, hh, mm, ss, us)
|
112
133
|
|
113
134
|
return time if 'Z' == md[3]
|
114
|
-
return
|
135
|
+
return klass.at(time.to_i, us) unless md[3]
|
115
136
|
|
116
137
|
tz = md[3].match(/^([+\-]?\d{1,2})\:?(\d{1,2})?$/)[1..-1].compact.map { |digit| Integer(digit, 10) }
|
117
138
|
offset = tz.first * 3600
|
@@ -122,7 +143,7 @@ module Psych
|
|
122
143
|
offset += ((tz[1] || 0) * 60)
|
123
144
|
end
|
124
145
|
|
125
|
-
|
146
|
+
klass.at((time - offset).to_i, us)
|
126
147
|
end
|
127
148
|
end
|
128
149
|
end
|
data/lib/psych/stream.rb
CHANGED
data/lib/psych/streaming.rb
CHANGED
@@ -1,10 +1,15 @@
|
|
1
1
|
module Psych
|
2
2
|
module Streaming
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module ClassMethods
|
4
|
+
###
|
5
|
+
# Create a new streaming emitter. Emitter will print to +io+. See
|
6
|
+
# Psych::Stream for an example.
|
7
|
+
def new io
|
8
|
+
emitter = const_get(:Emitter).new(io)
|
9
|
+
class_loader = ClassLoader.new
|
10
|
+
ss = ScalarScanner.new class_loader
|
11
|
+
super(emitter, ss, {})
|
12
|
+
end
|
8
13
|
end
|
9
14
|
|
10
15
|
###
|
data/lib/psych/syntax_error.rb
CHANGED
@@ -5,8 +5,11 @@ module Psych
|
|
5
5
|
class JSONTree < YAMLTree
|
6
6
|
include Psych::JSON::RubyEvents
|
7
7
|
|
8
|
-
def
|
9
|
-
|
8
|
+
def self.create options = {}
|
9
|
+
emitter = Psych::JSON::TreeBuilder.new
|
10
|
+
class_loader = ClassLoader.new
|
11
|
+
ss = ScalarScanner.new class_loader
|
12
|
+
new(emitter, ss, options)
|
10
13
|
end
|
11
14
|
|
12
15
|
def accept target
|
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'psych/scalar_scanner'
|
2
|
+
require 'psych/class_loader'
|
3
|
+
require 'psych/exception'
|
2
4
|
|
3
5
|
unless defined?(Regexp::NOENCODING)
|
4
6
|
Regexp::NOENCODING = 32
|
@@ -9,11 +11,20 @@ module Psych
|
|
9
11
|
###
|
10
12
|
# This class walks a YAML AST, converting each node to ruby
|
11
13
|
class ToRuby < Psych::Visitors::Visitor
|
12
|
-
def
|
14
|
+
def self.create
|
15
|
+
class_loader = ClassLoader.new
|
16
|
+
scanner = ScalarScanner.new class_loader
|
17
|
+
new(scanner, class_loader)
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :class_loader
|
21
|
+
|
22
|
+
def initialize ss, class_loader
|
13
23
|
super()
|
14
24
|
@st = {}
|
15
25
|
@ss = ss
|
16
26
|
@domain_types = Psych.domain_types
|
27
|
+
@class_loader = class_loader
|
17
28
|
end
|
18
29
|
|
19
30
|
def accept target
|
@@ -32,7 +43,7 @@ module Psych
|
|
32
43
|
end
|
33
44
|
|
34
45
|
def deserialize o
|
35
|
-
if klass = Psych.load_tags[o.tag]
|
46
|
+
if klass = resolve_class(Psych.load_tags[o.tag])
|
36
47
|
instance = klass.allocate
|
37
48
|
|
38
49
|
if instance.respond_to?(:init_with)
|
@@ -59,19 +70,23 @@ module Psych
|
|
59
70
|
end
|
60
71
|
when '!ruby/object:BigDecimal'
|
61
72
|
require 'bigdecimal'
|
62
|
-
|
73
|
+
class_loader.big_decimal._load o.value
|
63
74
|
when "!ruby/object:DateTime"
|
75
|
+
class_loader.date_time
|
64
76
|
require 'date'
|
65
77
|
@ss.parse_time(o.value).to_datetime
|
66
78
|
when "!ruby/object:Complex"
|
79
|
+
class_loader.complex
|
67
80
|
Complex(o.value)
|
68
81
|
when "!ruby/object:Rational"
|
82
|
+
class_loader.rational
|
69
83
|
Rational(o.value)
|
70
84
|
when "!ruby/class", "!ruby/module"
|
71
85
|
resolve_class o.value
|
72
86
|
when "tag:yaml.org,2002:float", "!float"
|
73
87
|
Float(@ss.tokenize(o.value))
|
74
88
|
when "!ruby/regexp"
|
89
|
+
klass = class_loader.regexp
|
75
90
|
o.value =~ /^\/(.*)\/([mixn]*)$/
|
76
91
|
source = $1
|
77
92
|
options = 0
|
@@ -85,15 +100,16 @@ module Psych
|
|
85
100
|
else lang = option
|
86
101
|
end
|
87
102
|
end
|
88
|
-
|
103
|
+
klass.new(*[source, options, lang].compact)
|
89
104
|
when "!ruby/range"
|
105
|
+
klass = class_loader.range
|
90
106
|
args = o.value.split(/([.]{2,3})/, 2).map { |s|
|
91
107
|
accept Nodes::Scalar.new(s)
|
92
108
|
}
|
93
109
|
args.push(args.delete_at(1) == '...')
|
94
|
-
|
110
|
+
klass.new(*args)
|
95
111
|
when /^!ruby\/sym(bol)?:?(.*)?$/
|
96
|
-
o.value
|
112
|
+
class_loader.symbolize o.value
|
97
113
|
else
|
98
114
|
@ss.tokenize o.value
|
99
115
|
end
|
@@ -105,7 +121,7 @@ module Psych
|
|
105
121
|
end
|
106
122
|
|
107
123
|
def visit_Psych_Nodes_Sequence o
|
108
|
-
if klass = Psych.load_tags[o.tag]
|
124
|
+
if klass = resolve_class(Psych.load_tags[o.tag])
|
109
125
|
instance = klass.allocate
|
110
126
|
|
111
127
|
if instance.respond_to?(:init_with)
|
@@ -118,6 +134,8 @@ module Psych
|
|
118
134
|
end
|
119
135
|
|
120
136
|
case o.tag
|
137
|
+
when nil
|
138
|
+
register_empty(o)
|
121
139
|
when '!omap', 'tag:yaml.org,2002:omap'
|
122
140
|
map = register(o, Psych::Omap.new)
|
123
141
|
o.children.each { |a|
|
@@ -130,51 +148,29 @@ module Psych
|
|
130
148
|
o.children.each { |c| list.push accept c }
|
131
149
|
list
|
132
150
|
else
|
133
|
-
|
134
|
-
o.children.each { |c| list.push accept c }
|
135
|
-
list
|
151
|
+
register_empty(o)
|
136
152
|
end
|
137
153
|
end
|
138
154
|
|
139
155
|
def visit_Psych_Nodes_Mapping o
|
140
|
-
|
156
|
+
if Psych.load_tags[o.tag]
|
157
|
+
return revive(resolve_class(Psych.load_tags[o.tag]), o)
|
158
|
+
end
|
141
159
|
return revive_hash({}, o) unless o.tag
|
142
160
|
|
143
161
|
case o.tag
|
144
|
-
when /^!(?:str|ruby\/string)(?::(.*))?/, 'tag:yaml.org,2002:str'
|
145
|
-
klass = resolve_class($1)
|
146
|
-
members = Hash[*o.children.map { |c| accept c }]
|
147
|
-
string = members.delete 'str'
|
148
|
-
|
149
|
-
if klass
|
150
|
-
string = klass.allocate.replace string
|
151
|
-
register(o, string)
|
152
|
-
end
|
153
|
-
|
154
|
-
init_with(string, members.map { |k,v| [k.to_s.sub(/^@/, ''),v] }, o)
|
155
|
-
when /^!ruby\/array:(.*)$/
|
156
|
-
klass = resolve_class($1)
|
157
|
-
list = register(o, klass.allocate)
|
158
|
-
|
159
|
-
members = Hash[o.children.map { |c| accept c }.each_slice(2).to_a]
|
160
|
-
list.replace members['internal']
|
161
|
-
|
162
|
-
members['ivars'].each do |ivar, v|
|
163
|
-
list.instance_variable_set ivar, v
|
164
|
-
end
|
165
|
-
list
|
166
162
|
when /^!ruby\/struct:?(.*)?$/
|
167
|
-
klass = resolve_class($1)
|
163
|
+
klass = resolve_class($1) if $1
|
168
164
|
|
169
165
|
if klass
|
170
166
|
s = register(o, klass.allocate)
|
171
167
|
|
172
168
|
members = {}
|
173
|
-
struct_members = s.members.map { |x|
|
169
|
+
struct_members = s.members.map { |x| class_loader.symbolize x }
|
174
170
|
o.children.each_slice(2) do |k,v|
|
175
171
|
member = accept(k)
|
176
172
|
value = accept(v)
|
177
|
-
if struct_members.include?(member
|
173
|
+
if struct_members.include?(class_loader.symbolize(member))
|
178
174
|
s.send("#{member}=", value)
|
179
175
|
else
|
180
176
|
members[member.to_s.sub(/^@/, '')] = value
|
@@ -182,48 +178,88 @@ module Psych
|
|
182
178
|
end
|
183
179
|
init_with(s, members, o)
|
184
180
|
else
|
181
|
+
klass = class_loader.struct
|
185
182
|
members = o.children.map { |c| accept c }
|
186
183
|
h = Hash[*members]
|
187
|
-
|
184
|
+
klass.new(*h.map { |k,v|
|
185
|
+
class_loader.symbolize k
|
186
|
+
}).new(*h.map { |k,v| v })
|
187
|
+
end
|
188
|
+
|
189
|
+
when /^!ruby\/object:?(.*)?$/
|
190
|
+
name = $1 || 'Object'
|
191
|
+
|
192
|
+
if name == 'Complex'
|
193
|
+
class_loader.complex
|
194
|
+
h = Hash[*o.children.map { |c| accept c }]
|
195
|
+
register o, Complex(h['real'], h['image'])
|
196
|
+
elsif name == 'Rational'
|
197
|
+
class_loader.rational
|
198
|
+
h = Hash[*o.children.map { |c| accept c }]
|
199
|
+
register o, Rational(h['numerator'], h['denominator'])
|
200
|
+
else
|
201
|
+
obj = revive((resolve_class(name) || class_loader.object), o)
|
202
|
+
obj
|
203
|
+
end
|
204
|
+
|
205
|
+
when /^!(?:str|ruby\/string)(?::(.*))?/, 'tag:yaml.org,2002:str'
|
206
|
+
klass = resolve_class($1)
|
207
|
+
members = {}
|
208
|
+
string = nil
|
209
|
+
|
210
|
+
o.children.each_slice(2) do |k,v|
|
211
|
+
key = accept k
|
212
|
+
value = accept v
|
213
|
+
|
214
|
+
if key == 'str'
|
215
|
+
if klass
|
216
|
+
string = klass.allocate.replace value
|
217
|
+
else
|
218
|
+
string = value
|
219
|
+
end
|
220
|
+
register(o, string)
|
221
|
+
else
|
222
|
+
members[key] = value
|
223
|
+
end
|
224
|
+
end
|
225
|
+
init_with(string, members.map { |k,v| [k.to_s.sub(/^@/, ''),v] }, o)
|
226
|
+
when /^!ruby\/array:(.*)$/
|
227
|
+
klass = resolve_class($1)
|
228
|
+
list = register(o, klass.allocate)
|
229
|
+
|
230
|
+
members = Hash[o.children.map { |c| accept c }.each_slice(2).to_a]
|
231
|
+
list.replace members['internal']
|
232
|
+
|
233
|
+
members['ivars'].each do |ivar, v|
|
234
|
+
list.instance_variable_set ivar, v
|
188
235
|
end
|
236
|
+
list
|
189
237
|
|
190
238
|
when '!ruby/range'
|
239
|
+
klass = class_loader.range
|
191
240
|
h = Hash[*o.children.map { |c| accept c }]
|
192
|
-
register o,
|
241
|
+
register o, klass.new(h['begin'], h['end'], h['excl'])
|
193
242
|
|
194
243
|
when /^!ruby\/exception:?(.*)?$/
|
195
244
|
h = Hash[*o.children.map { |c| accept c }]
|
196
245
|
|
197
|
-
e = build_exception((resolve_class($1) ||
|
246
|
+
e = build_exception((resolve_class($1) || class_loader.exception),
|
198
247
|
h.delete('message'))
|
199
248
|
init_with(e, h, o)
|
200
249
|
|
201
250
|
when '!set', 'tag:yaml.org,2002:set'
|
202
|
-
set =
|
251
|
+
set = class_loader.psych_set.new
|
203
252
|
@st[o.anchor] = set if o.anchor
|
204
253
|
o.children.each_slice(2) do |k,v|
|
205
254
|
set[accept(k)] = accept(v)
|
206
255
|
end
|
207
256
|
set
|
208
257
|
|
209
|
-
when '!ruby/object:Complex'
|
210
|
-
h = Hash[*o.children.map { |c| accept c }]
|
211
|
-
register o, Complex(h['real'], h['image'])
|
212
|
-
|
213
|
-
when '!ruby/object:Rational'
|
214
|
-
h = Hash[*o.children.map { |c| accept c }]
|
215
|
-
register o, Rational(h['numerator'], h['denominator'])
|
216
|
-
|
217
|
-
when /^!ruby\/object:?(.*)?$/
|
218
|
-
name = $1 || 'Object'
|
219
|
-
obj = revive((resolve_class(name) || Object), o)
|
220
|
-
obj
|
221
|
-
|
222
258
|
when /^!map:(.*)$/, /^!ruby\/hash:(.*)$/
|
223
259
|
revive_hash resolve_class($1).new, o
|
224
260
|
|
225
261
|
when '!omap', 'tag:yaml.org,2002:omap'
|
226
|
-
map = register(o,
|
262
|
+
map = register(o, class_loader.psych_omap.new)
|
227
263
|
o.children.each_slice(2) do |l,r|
|
228
264
|
map[accept(l)] = accept r
|
229
265
|
end
|
@@ -252,31 +288,51 @@ module Psych
|
|
252
288
|
object
|
253
289
|
end
|
254
290
|
|
291
|
+
def register_empty object
|
292
|
+
list = register(object, [])
|
293
|
+
object.children.each { |c| list.push accept c }
|
294
|
+
list
|
295
|
+
end
|
296
|
+
|
255
297
|
def revive_hash hash, o
|
256
298
|
@st[o.anchor] = hash if o.anchor
|
257
299
|
|
258
|
-
|
300
|
+
o.children.each_slice(2) { |k,v|
|
259
301
|
key = accept(k)
|
302
|
+
val = accept(v)
|
260
303
|
|
261
304
|
if key == '<<'
|
262
305
|
case v
|
263
306
|
when Nodes::Alias
|
264
|
-
|
307
|
+
begin
|
308
|
+
hash.merge! val
|
309
|
+
rescue TypeError
|
310
|
+
hash[key] = val
|
311
|
+
end
|
265
312
|
when Nodes::Sequence
|
266
|
-
|
267
|
-
|
313
|
+
begin
|
314
|
+
h = {}
|
315
|
+
val.reverse_each do |value|
|
316
|
+
h.merge! value
|
317
|
+
end
|
318
|
+
hash.merge! h
|
319
|
+
rescue TypeError
|
320
|
+
hash[key] = val
|
268
321
|
end
|
269
322
|
else
|
270
|
-
hash[key] =
|
323
|
+
hash[key] = val
|
271
324
|
end
|
272
325
|
else
|
273
|
-
hash[key] =
|
326
|
+
hash[key] = val
|
274
327
|
end
|
275
328
|
|
276
329
|
}
|
277
330
|
hash
|
278
331
|
end
|
279
332
|
|
333
|
+
def merge_key hash, key, val
|
334
|
+
end
|
335
|
+
|
280
336
|
def revive klass, node
|
281
337
|
s = klass.allocate
|
282
338
|
@st[node.anchor] = s if node.anchor
|
@@ -303,21 +359,13 @@ module Psych
|
|
303
359
|
|
304
360
|
# Convert +klassname+ to a Class
|
305
361
|
def resolve_class klassname
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
rescue ArgumentError, NameError => ex
|
314
|
-
unless retried
|
315
|
-
name = "Struct::#{name}"
|
316
|
-
retried = ex
|
317
|
-
retry
|
318
|
-
end
|
319
|
-
raise retried
|
320
|
-
end
|
362
|
+
class_loader.load klassname
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
class NoAliasRuby < ToRuby
|
367
|
+
def visit_Psych_Nodes_Alias o
|
368
|
+
raise BadAlias, "Unknown alias: #{o.anchor}"
|
321
369
|
end
|
322
370
|
end
|
323
371
|
end
|