RbYAML 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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