psych 2.0.14-java

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.
Files changed (118) hide show
  1. checksums.yaml +7 -0
  2. data/.autotest +18 -0
  3. data/.gemtest +0 -0
  4. data/.travis.yml +16 -0
  5. data/CHANGELOG.rdoc +576 -0
  6. data/Manifest.txt +114 -0
  7. data/README.rdoc +71 -0
  8. data/Rakefile +123 -0
  9. data/ext/psych/depend +3 -0
  10. data/ext/psych/extconf.rb +38 -0
  11. data/ext/psych/psych.c +34 -0
  12. data/ext/psych/psych.h +20 -0
  13. data/ext/psych/psych_emitter.c +555 -0
  14. data/ext/psych/psych_emitter.h +8 -0
  15. data/ext/psych/psych_parser.c +597 -0
  16. data/ext/psych/psych_parser.h +6 -0
  17. data/ext/psych/psych_to_ruby.c +43 -0
  18. data/ext/psych/psych_to_ruby.h +8 -0
  19. data/ext/psych/psych_yaml_tree.c +24 -0
  20. data/ext/psych/psych_yaml_tree.h +8 -0
  21. data/ext/psych/yaml/LICENSE +19 -0
  22. data/ext/psych/yaml/api.c +1415 -0
  23. data/ext/psych/yaml/config.h +10 -0
  24. data/ext/psych/yaml/dumper.c +394 -0
  25. data/ext/psych/yaml/emitter.c +2329 -0
  26. data/ext/psych/yaml/loader.c +459 -0
  27. data/ext/psych/yaml/parser.c +1370 -0
  28. data/ext/psych/yaml/reader.c +469 -0
  29. data/ext/psych/yaml/scanner.c +3576 -0
  30. data/ext/psych/yaml/writer.c +141 -0
  31. data/ext/psych/yaml/yaml.h +1971 -0
  32. data/ext/psych/yaml/yaml_private.h +664 -0
  33. data/lib/psych.jar +0 -0
  34. data/lib/psych.rb +504 -0
  35. data/lib/psych/class_loader.rb +101 -0
  36. data/lib/psych/coder.rb +94 -0
  37. data/lib/psych/core_ext.rb +35 -0
  38. data/lib/psych/deprecated.rb +85 -0
  39. data/lib/psych/exception.rb +13 -0
  40. data/lib/psych/handler.rb +249 -0
  41. data/lib/psych/handlers/document_stream.rb +22 -0
  42. data/lib/psych/handlers/recorder.rb +39 -0
  43. data/lib/psych/json/ruby_events.rb +19 -0
  44. data/lib/psych/json/stream.rb +16 -0
  45. data/lib/psych/json/tree_builder.rb +12 -0
  46. data/lib/psych/json/yaml_events.rb +29 -0
  47. data/lib/psych/nodes.rb +77 -0
  48. data/lib/psych/nodes/alias.rb +18 -0
  49. data/lib/psych/nodes/document.rb +60 -0
  50. data/lib/psych/nodes/mapping.rb +56 -0
  51. data/lib/psych/nodes/node.rb +55 -0
  52. data/lib/psych/nodes/scalar.rb +67 -0
  53. data/lib/psych/nodes/sequence.rb +81 -0
  54. data/lib/psych/nodes/stream.rb +37 -0
  55. data/lib/psych/omap.rb +4 -0
  56. data/lib/psych/parser.rb +51 -0
  57. data/lib/psych/scalar_scanner.rb +149 -0
  58. data/lib/psych/set.rb +4 -0
  59. data/lib/psych/stream.rb +37 -0
  60. data/lib/psych/streaming.rb +27 -0
  61. data/lib/psych/syntax_error.rb +21 -0
  62. data/lib/psych/tree_builder.rb +96 -0
  63. data/lib/psych/versions.rb +3 -0
  64. data/lib/psych/visitors.rb +6 -0
  65. data/lib/psych/visitors/depth_first.rb +26 -0
  66. data/lib/psych/visitors/emitter.rb +51 -0
  67. data/lib/psych/visitors/json_tree.rb +24 -0
  68. data/lib/psych/visitors/to_ruby.rb +404 -0
  69. data/lib/psych/visitors/visitor.rb +19 -0
  70. data/lib/psych/visitors/yaml_tree.rb +605 -0
  71. data/lib/psych/y.rb +9 -0
  72. data/lib/psych_jars.rb +5 -0
  73. data/test/psych/handlers/test_recorder.rb +25 -0
  74. data/test/psych/helper.rb +121 -0
  75. data/test/psych/json/test_stream.rb +109 -0
  76. data/test/psych/nodes/test_enumerable.rb +43 -0
  77. data/test/psych/test_alias_and_anchor.rb +96 -0
  78. data/test/psych/test_array.rb +57 -0
  79. data/test/psych/test_boolean.rb +36 -0
  80. data/test/psych/test_class.rb +36 -0
  81. data/test/psych/test_coder.rb +206 -0
  82. data/test/psych/test_date_time.rb +38 -0
  83. data/test/psych/test_deprecated.rb +214 -0
  84. data/test/psych/test_document.rb +46 -0
  85. data/test/psych/test_emitter.rb +93 -0
  86. data/test/psych/test_encoding.rb +259 -0
  87. data/test/psych/test_exception.rb +157 -0
  88. data/test/psych/test_hash.rb +94 -0
  89. data/test/psych/test_json_tree.rb +65 -0
  90. data/test/psych/test_merge_keys.rb +180 -0
  91. data/test/psych/test_nil.rb +18 -0
  92. data/test/psych/test_null.rb +19 -0
  93. data/test/psych/test_numeric.rb +45 -0
  94. data/test/psych/test_object.rb +44 -0
  95. data/test/psych/test_object_references.rb +71 -0
  96. data/test/psych/test_omap.rb +75 -0
  97. data/test/psych/test_parser.rb +339 -0
  98. data/test/psych/test_psych.rb +168 -0
  99. data/test/psych/test_safe_load.rb +97 -0
  100. data/test/psych/test_scalar.rb +11 -0
  101. data/test/psych/test_scalar_scanner.rb +106 -0
  102. data/test/psych/test_serialize_subclasses.rb +38 -0
  103. data/test/psych/test_set.rb +49 -0
  104. data/test/psych/test_stream.rb +93 -0
  105. data/test/psych/test_string.rb +226 -0
  106. data/test/psych/test_struct.rb +49 -0
  107. data/test/psych/test_symbol.rb +25 -0
  108. data/test/psych/test_tainted.rb +130 -0
  109. data/test/psych/test_to_yaml_properties.rb +63 -0
  110. data/test/psych/test_tree_builder.rb +79 -0
  111. data/test/psych/test_yaml.rb +1292 -0
  112. data/test/psych/test_yamldbm.rb +193 -0
  113. data/test/psych/test_yamlstore.rb +85 -0
  114. data/test/psych/visitors/test_depth_first.rb +49 -0
  115. data/test/psych/visitors/test_emitter.rb +144 -0
  116. data/test/psych/visitors/test_to_ruby.rb +333 -0
  117. data/test/psych/visitors/test_yaml_tree.rb +173 -0
  118. metadata +240 -0
@@ -0,0 +1,19 @@
1
+ module Psych
2
+ module Visitors
3
+ class Visitor
4
+ def accept target
5
+ visit target
6
+ end
7
+
8
+ private
9
+
10
+ DISPATCH = Hash.new do |hash, klass|
11
+ hash[klass] = "visit_#{klass.name.gsub('::', '_')}"
12
+ end
13
+
14
+ def visit target
15
+ send DISPATCH[target.class], target
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,605 @@
1
+ require 'psych/tree_builder'
2
+ require 'psych/scalar_scanner'
3
+ require 'psych/class_loader'
4
+
5
+ module Psych
6
+ module Visitors
7
+ ###
8
+ # YAMLTree builds a YAML ast given a Ruby object. For example:
9
+ #
10
+ # builder = Psych::Visitors::YAMLTree.new
11
+ # builder << { :foo => 'bar' }
12
+ # builder.tree # => #<Psych::Nodes::Stream .. }
13
+ #
14
+ class YAMLTree < Psych::Visitors::Visitor
15
+ class Registrar # :nodoc:
16
+ def initialize
17
+ @obj_to_id = {}
18
+ @obj_to_node = {}
19
+ @targets = []
20
+ @counter = 0
21
+ end
22
+
23
+ def register target, node
24
+ return unless target.respond_to? :object_id
25
+ @targets << target
26
+ @obj_to_node[target.object_id] = node
27
+ end
28
+
29
+ def key? target
30
+ @obj_to_node.key? target.object_id
31
+ rescue NoMethodError
32
+ false
33
+ end
34
+
35
+ def id_for target
36
+ @obj_to_id[target.object_id] ||= (@counter += 1)
37
+ end
38
+
39
+ def node_for target
40
+ @obj_to_node[target.object_id]
41
+ end
42
+ end
43
+
44
+ attr_reader :started, :finished
45
+ alias :finished? :finished
46
+ alias :started? :started
47
+
48
+ def self.create options = {}, emitter = nil
49
+ emitter ||= TreeBuilder.new
50
+ class_loader = ClassLoader.new
51
+ ss = ScalarScanner.new class_loader
52
+ new(emitter, ss, options)
53
+ end
54
+
55
+ def self.new emitter = nil, ss = nil, options = nil
56
+ return super if emitter && ss && options
57
+
58
+ if $VERBOSE
59
+ warn "This API is deprecated, please pass an emitter, scalar scanner, and options or call #{self}.create() (#{caller.first})"
60
+ end
61
+ create emitter, ss
62
+ end
63
+
64
+ def initialize emitter, ss, options
65
+ super()
66
+ @started = false
67
+ @finished = false
68
+ @emitter = emitter
69
+ @st = Registrar.new
70
+ @ss = ss
71
+ @options = options
72
+ @line_width = options[:line_width]
73
+ @coders = []
74
+
75
+ @dispatch_cache = Hash.new do |h,klass|
76
+ method = "visit_#{(klass.name || '').split('::').join('_')}"
77
+
78
+ method = respond_to?(method) ? method : h[klass.superclass]
79
+
80
+ raise(TypeError, "Can't dump #{target.class}") unless method
81
+
82
+ h[klass] = method
83
+ end
84
+ end
85
+
86
+ def start encoding = Nodes::Stream::UTF8
87
+ @emitter.start_stream(encoding).tap do
88
+ @started = true
89
+ end
90
+ end
91
+
92
+ def finish
93
+ @emitter.end_stream.tap do
94
+ @finished = true
95
+ end
96
+ end
97
+
98
+ def tree
99
+ finish unless finished?
100
+ @emitter.root
101
+ end
102
+
103
+ def push object
104
+ start unless started?
105
+ version = []
106
+ version = [1,1] if @options[:header]
107
+
108
+ case @options[:version]
109
+ when Array
110
+ version = @options[:version]
111
+ when String
112
+ version = @options[:version].split('.').map { |x| x.to_i }
113
+ else
114
+ version = [1,1]
115
+ end if @options.key? :version
116
+
117
+ @emitter.start_document version, [], false
118
+ accept object
119
+ @emitter.end_document !@emitter.streaming?
120
+ end
121
+ alias :<< :push
122
+
123
+ def accept target
124
+ # return any aliases we find
125
+ if @st.key? target
126
+ oid = @st.id_for target
127
+ node = @st.node_for target
128
+ anchor = oid.to_s
129
+ node.anchor = anchor
130
+ return @emitter.alias anchor
131
+ end
132
+
133
+ if target.respond_to?(:to_yaml)
134
+ begin
135
+ loc = target.method(:to_yaml).source_location.first
136
+ if loc !~ /(syck\/rubytypes.rb|psych\/core_ext.rb)/
137
+ unless target.respond_to?(:encode_with)
138
+ if $VERBOSE
139
+ warn "implementing to_yaml is deprecated, please implement \"encode_with\""
140
+ end
141
+
142
+ target.to_yaml(:nodump => true)
143
+ end
144
+ end
145
+ rescue
146
+ # public_method or source_location might be overridden,
147
+ # and it's OK to skip it since it's only to emit a warning
148
+ end
149
+ end
150
+
151
+ if target.respond_to?(:encode_with)
152
+ dump_coder target
153
+ else
154
+ send(@dispatch_cache[target.class], target)
155
+ end
156
+ end
157
+
158
+ def visit_Psych_Omap o
159
+ seq = @emitter.start_sequence(nil, '!omap', false, Nodes::Sequence::BLOCK)
160
+ register(o, seq)
161
+
162
+ o.each { |k,v| visit_Hash k => v }
163
+ @emitter.end_sequence
164
+ end
165
+
166
+ def visit_Encoding o
167
+ tag = "!ruby/encoding"
168
+ @emitter.scalar o.name, nil, tag, false, false, Nodes::Scalar::ANY
169
+ end
170
+
171
+ def visit_Object o
172
+ tag = Psych.dump_tags[o.class]
173
+ unless tag
174
+ klass = o.class == Object ? nil : o.class.name
175
+ tag = ['!ruby/object', klass].compact.join(':')
176
+ end
177
+
178
+ map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
179
+ register(o, map)
180
+
181
+ dump_ivars o
182
+ @emitter.end_mapping
183
+ end
184
+
185
+ def visit_Struct o
186
+ tag = ['!ruby/struct', o.class.name].compact.join(':')
187
+
188
+ register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
189
+ o.members.each do |member|
190
+ @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY
191
+ accept o[member]
192
+ end
193
+
194
+ dump_ivars o
195
+
196
+ @emitter.end_mapping
197
+ end
198
+
199
+ def visit_Exception o
200
+ tag = ['!ruby/exception', o.class.name].join ':'
201
+
202
+ @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
203
+
204
+ {
205
+ 'message' => private_iv_get(o, 'mesg'),
206
+ 'backtrace' => private_iv_get(o, 'backtrace'),
207
+ }.each do |k,v|
208
+ next unless v
209
+ @emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
210
+ accept v
211
+ end
212
+
213
+ dump_ivars o
214
+
215
+ @emitter.end_mapping
216
+ end
217
+
218
+ def visit_NameError o
219
+ tag = ['!ruby/exception', o.class.name].join ':'
220
+
221
+ @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
222
+
223
+ {
224
+ 'message' => o.message.to_s,
225
+ 'backtrace' => private_iv_get(o, 'backtrace'),
226
+ }.each do |k,v|
227
+ next unless v
228
+ @emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
229
+ accept v
230
+ end
231
+
232
+ dump_ivars o
233
+
234
+ @emitter.end_mapping
235
+ end
236
+
237
+ def visit_Regexp o
238
+ register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY)
239
+ end
240
+
241
+ def visit_DateTime o
242
+ formatted = if o.offset.zero?
243
+ o.strftime("%Y-%m-%d %H:%M:%S.%9N Z".freeze)
244
+ else
245
+ o.strftime("%Y-%m-%d %H:%M:%S.%9N %:z".freeze)
246
+ end
247
+ tag = '!ruby/object:DateTime'
248
+ register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY)
249
+ end
250
+
251
+ def visit_Time o
252
+ formatted = format_time o
253
+ register o, @emitter.scalar(formatted, nil, nil, true, false, Nodes::Scalar::ANY)
254
+ end
255
+
256
+ def visit_Rational o
257
+ register o, @emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK)
258
+
259
+ [
260
+ 'denominator', o.denominator.to_s,
261
+ 'numerator', o.numerator.to_s
262
+ ].each do |m|
263
+ @emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
264
+ end
265
+
266
+ @emitter.end_mapping
267
+ end
268
+
269
+ def visit_Complex o
270
+ register o, @emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK)
271
+
272
+ ['real', o.real.to_s, 'image', o.imag.to_s].each do |m|
273
+ @emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
274
+ end
275
+
276
+ @emitter.end_mapping
277
+ end
278
+
279
+ def visit_Integer o
280
+ @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
281
+ end
282
+ alias :visit_TrueClass :visit_Integer
283
+ alias :visit_FalseClass :visit_Integer
284
+ alias :visit_Date :visit_Integer
285
+
286
+ def visit_Float o
287
+ if o.nan?
288
+ @emitter.scalar '.nan', nil, nil, true, false, Nodes::Scalar::ANY
289
+ elsif o.infinite?
290
+ @emitter.scalar((o.infinite? > 0 ? '.inf' : '-.inf'),
291
+ nil, nil, true, false, Nodes::Scalar::ANY)
292
+ else
293
+ @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
294
+ end
295
+ end
296
+
297
+ def visit_BigDecimal o
298
+ @emitter.scalar o._dump, nil, '!ruby/object:BigDecimal', false, false, Nodes::Scalar::ANY
299
+ end
300
+
301
+ def visit_String o
302
+ plain = true
303
+ quote = true
304
+ style = Nodes::Scalar::PLAIN
305
+ tag = nil
306
+
307
+ if binary?(o)
308
+ o = [o].pack('m').chomp
309
+ tag = '!binary' # FIXME: change to below when syck is removed
310
+ #tag = 'tag:yaml.org,2002:binary'
311
+ style = Nodes::Scalar::LITERAL
312
+ plain = false
313
+ quote = false
314
+ elsif o =~ /\n(?!\Z)/ # match \n except blank line at the end of string
315
+ style = Nodes::Scalar::LITERAL
316
+ elsif o == '<<'
317
+ style = Nodes::Scalar::SINGLE_QUOTED
318
+ tag = 'tag:yaml.org,2002:str'
319
+ plain = false
320
+ quote = false
321
+ elsif @line_width && o.length > @line_width
322
+ style = Nodes::Scalar::FOLDED
323
+ elsif o =~ /^[^[:word:]][^"]*$/
324
+ style = Nodes::Scalar::DOUBLE_QUOTED
325
+ elsif not String === @ss.tokenize(o)
326
+ style = Nodes::Scalar::SINGLE_QUOTED
327
+ end
328
+
329
+ is_primitive = o.class == ::String
330
+ ivars = find_ivars o, is_primitive
331
+
332
+ if ivars.empty?
333
+ unless is_primitive
334
+ tag = "!ruby/string:#{o.class}"
335
+ plain = false
336
+ quote = false
337
+ end
338
+ @emitter.scalar o, nil, tag, plain, quote, style
339
+ else
340
+ maptag = '!ruby/string'
341
+ maptag << ":#{o.class}" unless o.class == ::String
342
+
343
+ register o, @emitter.start_mapping(nil, maptag, false, Nodes::Mapping::BLOCK)
344
+ @emitter.scalar 'str', nil, nil, true, false, Nodes::Scalar::ANY
345
+ @emitter.scalar o, nil, tag, plain, quote, style
346
+
347
+ dump_ivars o
348
+
349
+ @emitter.end_mapping
350
+ end
351
+ end
352
+
353
+ def visit_Module o
354
+ raise TypeError, "can't dump anonymous module: #{o}" unless o.name
355
+ register o, @emitter.scalar(o.name, nil, '!ruby/module', false, false, Nodes::Scalar::SINGLE_QUOTED)
356
+ end
357
+
358
+ def visit_Class o
359
+ raise TypeError, "can't dump anonymous class: #{o}" unless o.name
360
+ register o, @emitter.scalar(o.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED)
361
+ end
362
+
363
+ def visit_Range o
364
+ register o, @emitter.start_mapping(nil, '!ruby/range', false, Nodes::Mapping::BLOCK)
365
+ ['begin', o.begin, 'end', o.end, 'excl', o.exclude_end?].each do |m|
366
+ accept m
367
+ end
368
+ @emitter.end_mapping
369
+ end
370
+
371
+ def visit_Hash o
372
+ if o.class == ::Hash
373
+ register(o, @emitter.start_mapping(nil, nil, true, Psych::Nodes::Mapping::BLOCK))
374
+ o.each do |k,v|
375
+ accept k
376
+ accept v
377
+ end
378
+ @emitter.end_mapping
379
+ else
380
+ visit_hash_subclass o
381
+ end
382
+ end
383
+
384
+ def visit_Psych_Set o
385
+ register(o, @emitter.start_mapping(nil, '!set', false, Psych::Nodes::Mapping::BLOCK))
386
+
387
+ o.each do |k,v|
388
+ accept k
389
+ accept v
390
+ end
391
+
392
+ @emitter.end_mapping
393
+ end
394
+
395
+ def visit_Array o
396
+ if o.class == ::Array
397
+ register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
398
+ o.each { |c| accept c }
399
+ @emitter.end_sequence
400
+ else
401
+ visit_array_subclass o
402
+ end
403
+ end
404
+
405
+ def visit_NilClass o
406
+ @emitter.scalar('', nil, 'tag:yaml.org,2002:null', true, false, Nodes::Scalar::ANY)
407
+ end
408
+
409
+ def visit_Symbol o
410
+ if o.empty?
411
+ @emitter.scalar "", nil, '!ruby/symbol', false, false, Nodes::Scalar::ANY
412
+ else
413
+ @emitter.scalar ":#{o}", nil, nil, true, false, Nodes::Scalar::ANY
414
+ end
415
+ end
416
+
417
+ def visit_BasicObject o
418
+ tag = Psych.dump_tags[o.class]
419
+ tag ||= "!ruby/marshalable:#{o.class.name}"
420
+
421
+ map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
422
+ register(o, map)
423
+
424
+ o.marshal_dump.each(&method(:accept))
425
+
426
+ @emitter.end_mapping
427
+ end
428
+
429
+ private
430
+ # FIXME: Remove the index and count checks in Psych 3.0
431
+ NULL = "\x00"
432
+ BINARY_RANGE = "\x00-\x7F"
433
+ WS_RANGE = "^ -~\t\r\n"
434
+
435
+ def binary? string
436
+ (string.encoding == Encoding::ASCII_8BIT && !string.ascii_only?) ||
437
+ string.index(NULL) ||
438
+ string.count(BINARY_RANGE, WS_RANGE).fdiv(string.length) > 0.3
439
+ end
440
+
441
+ def visit_array_subclass o
442
+ tag = "!ruby/array:#{o.class}"
443
+ ivars = o.instance_variables
444
+ if ivars.empty?
445
+ node = @emitter.start_sequence(nil, tag, false, Nodes::Sequence::BLOCK)
446
+ register o, node
447
+ o.each { |c| accept c }
448
+ @emitter.end_sequence
449
+ else
450
+ node = @emitter.start_mapping(nil, tag, false, Nodes::Sequence::BLOCK)
451
+ register o, node
452
+
453
+ # Dump the internal list
454
+ accept 'internal'
455
+ @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
456
+ o.each { |c| accept c }
457
+ @emitter.end_sequence
458
+
459
+ # Dump the ivars
460
+ accept 'ivars'
461
+ @emitter.start_mapping(nil, nil, true, Nodes::Sequence::BLOCK)
462
+ ivars.each do |ivar|
463
+ accept ivar
464
+ accept o.instance_variable_get ivar
465
+ end
466
+ @emitter.end_mapping
467
+
468
+ @emitter.end_mapping
469
+ end
470
+ end
471
+
472
+ def visit_hash_subclass o
473
+ ivars = o.instance_variables
474
+ if ivars.any?
475
+ tag = "!ruby/hash-with-ivars:#{o.class}"
476
+ node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)
477
+ register(o, node)
478
+
479
+ # Dump the elements
480
+ accept 'elements'
481
+ @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
482
+ o.each do |k,v|
483
+ accept k
484
+ accept v
485
+ end
486
+ @emitter.end_mapping
487
+
488
+ # Dump the ivars
489
+ accept 'ivars'
490
+ @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
491
+ o.instance_variables.each do |ivar|
492
+ accept ivar
493
+ accept o.instance_variable_get ivar
494
+ end
495
+ @emitter.end_mapping
496
+
497
+ @emitter.end_mapping
498
+ else
499
+ tag = "!ruby/hash:#{o.class}"
500
+ node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)
501
+ register(o, node)
502
+ o.each do |k,v|
503
+ accept k
504
+ accept v
505
+ end
506
+ @emitter.end_mapping
507
+ end
508
+ end
509
+
510
+ def dump_list o
511
+ end
512
+
513
+ # '%:z' was no defined until 1.9.3
514
+ if RUBY_VERSION < '1.9.3'
515
+ def format_time time
516
+ formatted = time.strftime("%Y-%m-%d %H:%M:%S.%9N")
517
+
518
+ if time.utc?
519
+ formatted += " Z"
520
+ else
521
+ zone = time.strftime('%z')
522
+ formatted += " #{zone[0,3]}:#{zone[3,5]}"
523
+ end
524
+
525
+ formatted
526
+ end
527
+ else
528
+ def format_time time
529
+ if time.utc?
530
+ time.strftime("%Y-%m-%d %H:%M:%S.%9N Z")
531
+ else
532
+ time.strftime("%Y-%m-%d %H:%M:%S.%9N %:z")
533
+ end
534
+ end
535
+ end
536
+
537
+ # FIXME: remove this method once "to_yaml_properties" is removed
538
+ def find_ivars target, is_primitive=false
539
+ begin
540
+ loc = target.method(:to_yaml_properties).source_location.first
541
+ unless loc.start_with?(Psych::DEPRECATED) || loc.end_with?('rubytypes.rb')
542
+ if $VERBOSE
543
+ warn "#{loc}: to_yaml_properties is deprecated, please implement \"encode_with(coder)\""
544
+ end
545
+ return target.to_yaml_properties
546
+ end
547
+ rescue
548
+ # public_method or source_location might be overridden,
549
+ # and it's OK to skip it since it's only to emit a warning.
550
+ end
551
+
552
+ is_primitive ? [] : target.instance_variables
553
+ end
554
+
555
+ def register target, yaml_obj
556
+ @st.register target, yaml_obj
557
+ yaml_obj
558
+ end
559
+
560
+ def dump_coder o
561
+ @coders << o
562
+ tag = Psych.dump_tags[o.class]
563
+ unless tag
564
+ klass = o.class == Object ? nil : o.class.name
565
+ tag = ['!ruby/object', klass].compact.join(':')
566
+ end
567
+
568
+ c = Psych::Coder.new(tag)
569
+ o.encode_with(c)
570
+ emit_coder c, o
571
+ end
572
+
573
+ def emit_coder c, o
574
+ case c.type
575
+ when :scalar
576
+ @emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false, Nodes::Scalar::ANY
577
+ when :seq
578
+ @emitter.start_sequence nil, c.tag, c.tag.nil?, Nodes::Sequence::BLOCK
579
+ c.seq.each do |thing|
580
+ accept thing
581
+ end
582
+ @emitter.end_sequence
583
+ when :map
584
+ register o, @emitter.start_mapping(nil, c.tag, c.implicit, c.style)
585
+ c.map.each do |k,v|
586
+ accept k
587
+ accept v
588
+ end
589
+ @emitter.end_mapping
590
+ when :object
591
+ accept c.object
592
+ end
593
+ end
594
+
595
+ def dump_ivars target
596
+ ivars = find_ivars target
597
+
598
+ ivars.each do |iv|
599
+ @emitter.scalar("#{iv.to_s.sub(/^@/, '')}", nil, nil, true, false, Nodes::Scalar::ANY)
600
+ accept target.instance_variable_get(iv)
601
+ end
602
+ end
603
+ end
604
+ end
605
+ end