RbYAML 0.0.1

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 (66) hide show
  1. data/LICENSE +19 -0
  2. data/README +31 -0
  3. data/lib/rbyaml.rb +378 -0
  4. data/lib/rbyaml/composer.rb +189 -0
  5. data/lib/rbyaml/constructor.rb +374 -0
  6. data/lib/rbyaml/detector.rb +44 -0
  7. data/lib/rbyaml/dumper.rb +40 -0
  8. data/lib/rbyaml/emitter.rb +1116 -0
  9. data/lib/rbyaml/error.rb +81 -0
  10. data/lib/rbyaml/events.rb +92 -0
  11. data/lib/rbyaml/loader.rb +49 -0
  12. data/lib/rbyaml/nodes.rb +69 -0
  13. data/lib/rbyaml/parser.rb +488 -0
  14. data/lib/rbyaml/reader.rb +127 -0
  15. data/lib/rbyaml/representer.rb +183 -0
  16. data/lib/rbyaml/scanner.rb +1258 -0
  17. data/lib/rbyaml/serializer.rb +120 -0
  18. data/lib/rbyaml/test.rb +56 -0
  19. data/lib/rbyaml/tokens.rb +163 -0
  20. data/lib/rbyaml/yaml.rb +143 -0
  21. data/test/test_rbyaml.rb +18 -0
  22. data/test/yaml/gems.yml +130951 -0
  23. data/test/yaml/gems2.yml +113 -0
  24. data/test/yaml/test1.yml +3 -0
  25. data/test/yaml/test10.yml +8 -0
  26. data/test/yaml/test12.yml +8 -0
  27. data/test/yaml/test13.yml +4 -0
  28. data/test/yaml/test14.yml +4 -0
  29. data/test/yaml/test15.yml +8 -0
  30. data/test/yaml/test16.yml +7 -0
  31. data/test/yaml/test18.yml +6 -0
  32. data/test/yaml/test19.yml +5 -0
  33. data/test/yaml/test2.yml +3 -0
  34. data/test/yaml/test20.yml +6 -0
  35. data/test/yaml/test21.yml +4 -0
  36. data/test/yaml/test22.yml +4 -0
  37. data/test/yaml/test23.yml +13 -0
  38. data/test/yaml/test24.yml +14 -0
  39. data/test/yaml/test25.yml +7 -0
  40. data/test/yaml/test26.yml +7 -0
  41. data/test/yaml/test27.yml +29 -0
  42. data/test/yaml/test28.yml +26 -0
  43. data/test/yaml/test29.yml +13 -0
  44. data/test/yaml/test3.yml +8 -0
  45. data/test/yaml/test30.yml +7 -0
  46. data/test/yaml/test31.yml +2 -0
  47. data/test/yaml/test32.yml +13 -0
  48. data/test/yaml/test33.yml +2 -0
  49. data/test/yaml/test34.yml +8 -0
  50. data/test/yaml/test35.yml +4 -0
  51. data/test/yaml/test36.yml +8 -0
  52. data/test/yaml/test37.yml +2 -0
  53. data/test/yaml/test38.yml +8 -0
  54. data/test/yaml/test39.yml +2 -0
  55. data/test/yaml/test4.yml +8 -0
  56. data/test/yaml/test40.yml +3 -0
  57. data/test/yaml/test41.yml +5 -0
  58. data/test/yaml/test42.yml +12 -0
  59. data/test/yaml/test43.yml +15 -0
  60. data/test/yaml/test44.yml +23 -0
  61. data/test/yaml/test5.yml +3 -0
  62. data/test/yaml/test6.yml +5 -0
  63. data/test/yaml/test7.yml +10 -0
  64. data/test/yaml/test8.yml +10 -0
  65. data/test/yaml/test9.yml +8 -0
  66. metadata +111 -0
@@ -0,0 +1,374 @@
1
+ require 'base64'
2
+ require 'set'
3
+
4
+ require 'rbyaml/error'
5
+ require 'rbyaml/nodes'
6
+ require 'rbyaml/composer'
7
+
8
+ module RbYAML
9
+ class ConstructorError < MarkedYAMLError
10
+ end
11
+
12
+ module BaseConstructor
13
+ include Composer
14
+
15
+ @@yaml_constructors = {}
16
+ @@yaml_multi_constructors = {}
17
+
18
+ def initialize_constructor
19
+ @constructed_objects = {}
20
+ end
21
+
22
+ def check_data
23
+ # If there are more documents available?
24
+ check_node
25
+ end
26
+
27
+ def get_data
28
+ # Construct and return the next document.
29
+ construct_document(get_node) if check_node
30
+ end
31
+
32
+ def each_document
33
+ # Iterator protocol.
34
+ while check_node
35
+ yield construct_document(get_node)
36
+ end
37
+ end
38
+
39
+ def construct_document(node)
40
+ data = construct_object(node)
41
+ @constructed_objects = {}
42
+ data
43
+ end
44
+
45
+ def construct_object(node)
46
+ return @constructed_objects[node] if @constructed_objects.include?(node)
47
+ constructor = nil
48
+ ruby_cls = RbYAML::tagged_classes[node.tag]
49
+ if @@yaml_constructors.include?(node.tag)
50
+ constructor = @@yaml_constructors[node.tag]
51
+ elsif !ruby_cls.nil? && self.respond_to?(:construct_ruby_object) && (ruby_cls.method_defined?(:yaml_initialize) || ruby_cls.respond_to?(:yaml_new))
52
+ constructor = lambda { |node| send(:construct_ruby_object,RbYAML::tagged_classes[node.tag],node) }
53
+ else
54
+ through = false
55
+ for tag_prefix in @@yaml_multi_constructors.keys
56
+ through = true
57
+ if Regexp.new("^"+Regexp.escape(tag_prefix)) =~ node.tag
58
+ tag_suffix = node.tag[tag_prefix.length..-1]
59
+ if Symbol === @@yaml_multi_constructors[tag_prefix]
60
+ constructor = lambda { |node| send(@@yaml_multi_constructors[tag_prefix],tag_suffix, node) }
61
+ else
62
+ constructor = lambda { |node| @@yaml_multi_constructors[tag_prefix].call(tag_suffix, node) }
63
+ end
64
+ end
65
+ break
66
+ end
67
+ if !through
68
+ if @@yaml_multi_constructors.include?(nil)
69
+ if Symbol === @@yaml_multi_constructors[nil]
70
+ constructor = lambda { |node| send(@@yaml_multi_constructors[nil],node.tag, node) }
71
+ else
72
+ constructor = lambda { |node| @@yaml_multi_constructors[nil].call(node.tag, node) }
73
+ end
74
+ elsif @@yaml_constructors.include?(nil)
75
+ constructor = @@yaml_constructors[nil]
76
+ else
77
+ constructor = lambda { |node| construct_primitive(node) }
78
+ end
79
+ end
80
+ end
81
+ data = (Symbol === constructor) ? send(constructor,node) : constructor.call(node)
82
+ @constructed_objects[node] = data
83
+ data
84
+ end
85
+
86
+ def construct_primitive(node)
87
+ if ScalarNode === node
88
+ construct_scalar(node)
89
+ elsif SequenceNode === node
90
+ construct_sequence(node)
91
+ elsif MappingNode === node
92
+ construct_mapping(node)
93
+ end
94
+ end
95
+
96
+ def construct_scalar(node)
97
+ if !ScalarNode === node
98
+ if MappingNode === node
99
+ for key_node in node.value.keys
100
+ if key_node.tag == "tag:yaml.org,2002:value"
101
+ return construct_scalar(node.value[key_node])
102
+ end
103
+ end
104
+ end
105
+ raise ConstructorError.new(nil, nil,"expected a scalar node, but found #{node.tid}",node.start_mark)
106
+ end
107
+ node.value
108
+ end
109
+
110
+ def construct_sequence(node)
111
+ raise ConstructorError.new(nil,nil,"expected a sequence node, but found #{node.tid}",node.start_mark) if !SequenceNode === node
112
+ sequence = []
113
+ for child in node.value
114
+ sequence << construct_object(child)
115
+ end
116
+ sequence
117
+ end
118
+
119
+ def construct_mapping(node)
120
+ raise ConstructorError.new(nil,nil,"expected a mapping node, but found #{node.tid}",node.start_mark) if !MappingNode === node
121
+ mapping = {}
122
+ merge = nil
123
+ for key_node in node.value.keys
124
+ if key_node.tag == "tag:yaml.org,2002:merge"
125
+ raise ConstructorError.new("while constructing a mapping", node.start_mark,"found duplicate merge key", key_node.start_mark) if !merge.nil?
126
+ value_node = node.value[key_node]
127
+ if MappingNode === value_node
128
+ merge = [construct_mapping(value_node)]
129
+ elsif SequenceNode === value_node
130
+ merge = []
131
+ for subnode in value_node.value
132
+ if !MappingNode === subnode
133
+ raise ConstructorError.new("while constructing a mapping",node.start_mark,"expected a mapping for merging, but found #{subnode.tid}", subnode.start_mark)
134
+ end
135
+ merge << construct_mapping(subnode)
136
+ end
137
+ merge.reverse!
138
+ else
139
+ raise ConstructorError.new("while constructing a mapping", node.start_mark,"expected a mapping or list of mappings for merging, but found #{value_node.tid}", value_node.start_mark)
140
+ end
141
+ elsif key_node.tag == "tag:yaml.org,2002:value"
142
+ raise ConstructorError.new("while construction a mapping", node.start_mark,"found duplicate value key", key_node.start_mark) if mapping.include?("=")
143
+ value = construct_object(node.value[key_node])
144
+ mapping["="] = value
145
+
146
+ else
147
+ key = construct_object(key_node)
148
+ # raise ConstructorError.new("while constructing a mapping", node.start_mark,"found duplicate key", key_node.start_mark) if mapping.include?(key)
149
+ end
150
+ value = construct_object(node.value[key_node])
151
+ mapping[key] = value
152
+ end
153
+ if !merge.nil?
154
+ merge << mapping
155
+ mapping = {}
156
+ for submapping in merge
157
+ mapping.merge!(submapping)
158
+ end
159
+ end
160
+ mapping
161
+ end
162
+
163
+ def construct_pairs(node)
164
+ raise ConstructorError.new(nil,nil,"expected a mapping node, but found #{node.tid}",node.start_mark) if !MappingNode === node
165
+ pairs = []
166
+ for key_node in node.value.keys
167
+ key = construct_object(key_node)
168
+ value = construct_object(node.value[key_node])
169
+ pairs << [key, value]
170
+ end
171
+ pairs
172
+ end
173
+
174
+ def self.add_constructor(tag, constructor)
175
+ @@yaml_constructors[tag] = constructor
176
+ end
177
+
178
+ def self.add_multi_constructor(tag_prefix, multi_constructor)
179
+ @@yaml_multi_constructors[tag_prefix] = multi_constructor
180
+ end
181
+ end
182
+
183
+ module SafeConstructor
184
+ include BaseConstructor
185
+
186
+ def construct_yaml_null(node)
187
+ construct_scalar(node)
188
+ nil
189
+ end
190
+
191
+ BOOL_VALUES = {
192
+ "y" => true,
193
+ "n" => false,
194
+ "yes" => true,
195
+ "no" => false,
196
+ "true" => true,
197
+ "false" => false,
198
+ "on" => true,
199
+ "off" => false
200
+ }
201
+
202
+ def construct_yaml_bool(node)
203
+ value = construct_scalar(node)
204
+ SafeConstructor::BOOL_VALUES[value.downcase]
205
+ end
206
+
207
+ def construct_yaml_int(node)
208
+ value = construct_scalar(node).to_s
209
+ value = value.gsub(/_/, '')
210
+ sign = +1
211
+ sign = -1 if value[0] == ?-
212
+ value = value[1..-1] if "+-".include?(value[0])
213
+ if value == "0"
214
+ return 0
215
+ elsif value[0..1] == "0b"
216
+ return sign*value[2..-1].to_i(2)
217
+ elsif value[0..1] == "0x"
218
+ return sign*value[2..-1].to_i(16)
219
+ elsif value[0] == ?0
220
+ return sign*value[1..-1].to_i(8)
221
+ elsif value.include?(?:)
222
+ digits = (value.split(/:/).map {|val| val.to_i}).reverse
223
+ base = 1
224
+ value = 0
225
+ for digit in digits
226
+ value += digit*base
227
+ base *= 60
228
+ end
229
+ return sign*value
230
+ else
231
+ return sign*value.to_i
232
+ end
233
+ end
234
+
235
+ INF_VALUE = +1.0/0.0
236
+ NAN_VALUE = 0.0/0.0
237
+
238
+ def construct_yaml_float(node)
239
+ value = construct_scalar(node).to_s
240
+ value = value.gsub(/_/, '')
241
+ sign = +1
242
+ sign = -1 if value[0] == ?-
243
+ value = value[1..-1] if "+-".include?(value[0])
244
+ if value.downcase == ".inf"
245
+ return sign*SafeConstructor::INF_VALUE
246
+ elsif value.downcase == ".nan"
247
+ return SafeConstructor::NAN_VALUE
248
+ elsif value.include?(?:)
249
+ digits = (value.split(/:/).map {|val| val.to_f}).reverse
250
+ base = 1
251
+ value = 0.0
252
+ for digit in digits
253
+ value += digit*base
254
+ base *= 60
255
+ end
256
+ return sign*value
257
+ else
258
+ return value.to_f
259
+ end
260
+ end
261
+
262
+ def construct_yaml_binary(node)
263
+ value = construct_scalar(node)
264
+ Base64.decode64(value.to_s)
265
+ end
266
+
267
+ TIMESTAMP_REGEXP = /^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:(?:[Tt]|[ \t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\.([0-9]*))?(?:[ \t]*(?:Z|([-+][0-9][0-9]?)(?::([0-9][0-9])?)?))?)?$/
268
+
269
+ def construct_yaml_timestamp(node)
270
+ value = construct_scalar(node)
271
+ match = SafeConstructor::TIMESTAMP_REGEXP.match(node.value)
272
+ values = match.captures.map {|val| val.to_i}
273
+ fraction = values[6]
274
+ if fraction != 0
275
+ fraction *= 10 while 10*fraction < 1000
276
+ values[6] = fraction
277
+ end
278
+ stamp = Time.gm(values[0],values[1],values[2],values[3],values[4],values[5],values[6])
279
+
280
+ diff = values[7] * 3600 + values[8] * 60
281
+ return stamp-diff
282
+ end
283
+
284
+ def construct_yaml_omap(node)
285
+ # Note: we do not check for duplicate keys, because its too
286
+ # CPU-expensive.
287
+ raise ConstructorError.new("while constructing an ordered map", node.start_mark,
288
+ "expected a sequence, but found #{node.tid}", node.start_mark) if !SequenceNode === node
289
+ omap = []
290
+ for subnode in node.value
291
+ raise ConstructorError.new("while constructing an ordered map", node.start_mark,
292
+ "expected a mapping of length 1, but found #{subnode.tid}",subnode.start_mark) if !MappingNode === subnode
293
+ raise ConstructorError.new("while constructing an ordered map", node.start_mark,
294
+ "expected a single mapping item, but found #{subnode.value.length} items",subnode.start_mark) if subnode.value.length != 1
295
+ key_node = subnode.value.keys[0]
296
+ key = construct_object(key_node)
297
+ value = construct_object(subnode.value[key_node])
298
+ omap << [key, value]
299
+ end
300
+ omap
301
+ end
302
+
303
+ def construct_yaml_pairs(node)
304
+ construct_yaml_omap(node)
305
+ end
306
+
307
+ def construct_yaml_set(node)
308
+ Set.new(construct_mapping(node).keys)
309
+ end
310
+
311
+ def construct_yaml_str(node)
312
+ construct_scalar(node).to_s
313
+ end
314
+
315
+ def construct_yaml_seq(node)
316
+ construct_sequence(node)
317
+ end
318
+
319
+ def construct_yaml_map(node)
320
+ construct_mapping(node)
321
+ end
322
+
323
+ def construct_yaml_object(node, cls)
324
+ mapping = construct_mapping(node)
325
+ data = cls.new
326
+ mapping.each {|key,val| data.instance_variable_set("@#{key}",val)}
327
+ data
328
+ end
329
+
330
+ def construct_undefined(node)
331
+ raise ConstructorError.new(nil,nil,"could not determine a constructor for the tag #{node.tag}",node.start_mark)
332
+ end
333
+
334
+ def construct_ruby_object(cls,node)
335
+ val = construct_primitive(node)
336
+ if cls.respond_to?(:yaml_new)
337
+ obj = cls.yaml_new(cls,node.tag,val)
338
+ else
339
+ obj = cls.allocate
340
+ obj.yaml_initialize(node.tag,val)
341
+ end
342
+ obj
343
+ end
344
+
345
+ def construct_ruby(tag,node)
346
+ obj_class = Object
347
+ tag.split( "::" ).each { |c| obj_class = obj_class.const_get( c ) } if tag
348
+ o = obj_class.allocate
349
+ mapping = construct_mapping(node)
350
+ mapping.each {|key,val| o.instance_variable_set("@#{key}",val)}
351
+ o
352
+ end
353
+ end
354
+
355
+ BaseConstructor::add_constructor('tag:yaml.org,2002:null',:construct_yaml_null)
356
+ BaseConstructor::add_constructor('tag:yaml.org,2002:bool',:construct_yaml_bool)
357
+ BaseConstructor::add_constructor('tag:yaml.org,2002:int',:construct_yaml_int)
358
+ BaseConstructor::add_constructor('tag:yaml.org,2002:float',:construct_yaml_float)
359
+ BaseConstructor::add_constructor('tag:yaml.org,2002:binary',:construct_yaml_binary)
360
+ BaseConstructor::add_constructor('tag:yaml.org,2002:timestamp',:construct_yaml_timestamp)
361
+ BaseConstructor::add_constructor('tag:yaml.org,2002:omap',:construct_yaml_omap)
362
+ BaseConstructor::add_constructor('tag:yaml.org,2002:pairs',:construct_yaml_pairs)
363
+ BaseConstructor::add_constructor('tag:yaml.org,2002:set',:construct_yaml_set)
364
+ BaseConstructor::add_constructor('tag:yaml.org,2002:str',:construct_yaml_str)
365
+ BaseConstructor::add_constructor('tag:yaml.org,2002:seq',:construct_yaml_seq)
366
+ BaseConstructor::add_constructor('tag:yaml.org,2002:map',:construct_yaml_map)
367
+ BaseConstructor::add_constructor(nil,:construct_undefined)
368
+
369
+ BaseConstructor::add_multi_constructor("!ruby/object:",:construct_ruby)
370
+
371
+ module Constructor
372
+ include SafeConstructor
373
+ end
374
+ end
@@ -0,0 +1,44 @@
1
+
2
+ module RbYAML
3
+ DEFAULT_SCALAR_TAG = 'tag:yaml.org,2002:str'
4
+ DEFAULT_SEQUENCE_TAG = 'tag:yaml.org,2002:seq'
5
+ DEFAULT_MAPPING_TAG = 'tag:yaml.org,2002:map'
6
+
7
+ module BaseDetector
8
+ @@yaml_detectors = {}
9
+
10
+ def self.add_detector(tag, regexp, first)
11
+ first.each_byte { |ch|
12
+ @@yaml_detectors[ch] ||= []
13
+ @@yaml_detectors[ch] << [tag,regexp]
14
+ }
15
+ end
16
+
17
+ def detect(value)
18
+ if value == ""
19
+ detectors = @@yaml_detectors.fetch(?\0, [])
20
+ else
21
+ detectors = @@yaml_detectors.fetch(value[0], [])
22
+ end
23
+ detectors += @@yaml_detectors.fetch(nil, [])
24
+ for tag, regexp in detectors
25
+ return tag if regexp =~ value
26
+ end
27
+ nil
28
+ end
29
+ end
30
+ module Detector
31
+ include BaseDetector
32
+ end
33
+
34
+ BaseDetector.add_detector('tag:yaml.org,2002:bool',/^(?:y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)$/,'yYnNtTfFoO')
35
+ BaseDetector.add_detector('tag:yaml.org,2002:float',/^(?:[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*|[-+]?\.(?:inf|Inf|INF)|\.(?:nan|NaN|NAN))$/,'-+0123456789.')
36
+ BaseDetector.add_detector('tag:yaml.org,2002:int',/^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?(?:0|[1-9][0-9_]*)|[-+]?0x[0-9a-fA-F_]+|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$/,'-+0123456789')
37
+ BaseDetector.add_detector('tag:yaml.org,2002:merge',/^(?:<<)$/,'<')
38
+ BaseDetector.add_detector('tag:yaml.org,2002:null',/^(?: ~|null|Null|NULL| )$/,'~nN' + ?\0.chr)
39
+ BaseDetector.add_detector('tag:yaml.org,2002:timestamp',/^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?(?:[Tt]|[ \t]+)[0-9][0-9]?:[0-9][0-9]:[0-9][0-9](?:\.[0-9]*)?(?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$/,'0123456789')
40
+ BaseDetector.add_detector('tag:yaml.org,2002:value',/^(?:=)$/,'=')
41
+ # The following detector is only for documentation purposes. It cannot work
42
+ # because plain scalars cannot start with '!', '&', or '*'.
43
+ BaseDetector.add_detector('tag:yaml.org,2002:yaml',/^(?:!|&|\*)$/,'!&*')
44
+ end
@@ -0,0 +1,40 @@
1
+ require 'rbyaml/emitter'
2
+ require 'rbyaml/serializer'
3
+ require 'rbyaml/representer'
4
+ require 'rbyaml/detector'
5
+
6
+ module RbYAML
7
+ class CommonDumper
8
+ include Emitter, Serializer
9
+
10
+ def initialize(stream,canonical=nil,indent=nil,width=nil,line_break=nil,explicit_start=nil,explicit_end=nil,version=nil,tags=nil)
11
+ super()
12
+ initialize_emitter(stream,canonical,indent,width,line_break)
13
+ initialize_serializer(explicit_start,explicit_end,version,tags)
14
+ end
15
+ end
16
+
17
+ class BaseDumper < CommonDumper
18
+ include BaseRepresenter, BaseDetector
19
+ def initialize(stream,canonical=nil,indent=nil,width=nil,line_break=nil,explicit_start=nil,explicit_end=nil,version=nil,tags=nil)
20
+ super
21
+ initialize_representer
22
+ end
23
+ end
24
+
25
+ class SafeDumper < CommonDumper
26
+ include SafeRepresenter, Detector
27
+ def initialize(stream,canonical=nil,indent=nil,width=nil,line_break=nil,explicit_start=nil,explicit_end=nil,version=nil,tags=nil)
28
+ super
29
+ initialize_representer
30
+ end
31
+ end
32
+
33
+ class Dumper < CommonDumper
34
+ include Representer, Detector
35
+ def initialize(stream,canonical=nil,indent=nil,width=nil,line_break=nil,explicit_start=nil,explicit_end=nil,version=nil,tags=nil)
36
+ super
37
+ initialize_representer
38
+ end
39
+ end
40
+ end