psych 1.3.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|