RbYAML 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/lib/rbyaml.rb +14 -256
  2. data/lib/rbyaml.rb.~1.2.~ +383 -0
  3. data/lib/rbyaml/composer.rb +9 -11
  4. data/lib/rbyaml/{composer.rb.~1.2.~ → composer.rb.~1.3.~} +28 -25
  5. data/lib/rbyaml/constants.rb +95 -0
  6. data/lib/rbyaml/constructor.rb +180 -89
  7. data/lib/rbyaml/{constructor.rb.~1.2.~ → constructor.rb.~1.9.~} +137 -95
  8. data/lib/rbyaml/dumper.rb +12 -9
  9. data/lib/rbyaml/dumper.rb.~1.3.~ +36 -0
  10. data/lib/rbyaml/emitter.rb +14 -28
  11. data/lib/rbyaml/{emitter.rb.~1.2.~ → emitter.rb.~1.6.~} +22 -33
  12. data/lib/rbyaml/error.rb +4 -57
  13. data/lib/rbyaml/error.rb.~1.2.~ +75 -0
  14. data/lib/rbyaml/events.rb +8 -14
  15. data/lib/rbyaml/{events.rb.~1.2.~ → events.rb.~1.4.~} +29 -6
  16. data/lib/rbyaml/nodes.rb +5 -5
  17. data/lib/rbyaml/{nodes.rb.~1.2.~ → nodes.rb.~1.3.~} +13 -9
  18. data/lib/rbyaml/parser.rb +70 -108
  19. data/lib/rbyaml/parser.rb.~1.4.~ +632 -0
  20. data/lib/rbyaml/representer.rb +19 -157
  21. data/lib/rbyaml/representer.rb.old +317 -0
  22. data/lib/rbyaml/{representer.rb.~1.2.~ → representer.rb.~1.5.~} +60 -26
  23. data/lib/rbyaml/resolver.rb +6 -6
  24. data/lib/rbyaml/{resolver.rb.~1.1.~ → resolver.rb.~1.6.~} +20 -20
  25. data/lib/rbyaml/rubytypes.rb +391 -0
  26. data/lib/rbyaml/scanner.rb +123 -225
  27. data/lib/rbyaml/{scanner.rb.~1.2.~ → scanner.rb.~1.5.~} +466 -378
  28. data/lib/rbyaml/serializer.rb +9 -9
  29. data/lib/rbyaml/{serializer.rb.~1.2.~ → serializer.rb.~1.4.~} +19 -17
  30. data/lib/rbyaml/stream.rb +48 -0
  31. data/lib/rbyaml/tag.rb +72 -0
  32. data/lib/rbyaml/tokens.rb +22 -16
  33. data/lib/rbyaml/{tokens.rb.~1.2.~ → tokens.rb.~1.3.~} +44 -4
  34. data/lib/rbyaml/types.rb +146 -0
  35. data/lib/rbyaml/util.rb.~1.3.~ +38 -0
  36. data/lib/rbyaml/yaml.rb +22 -32
  37. data/lib/rbyaml/{yaml.rb.~1.2.~ → yaml.rb.~1.5.~} +17 -17
  38. data/test/load_one.rb +6 -0
  39. data/test/load_one_yaml.rb +6 -0
  40. data/test/output_events.rb +9 -0
  41. data/test/test_add_ctor.rb +51 -0
  42. data/test/test_add_ctor.rb.~1.1.~ +30 -0
  43. data/test/test_bm.rb +2 -2
  44. data/test/test_bm.rb.~1.1.~ +28 -0
  45. data/test/test_gems.rb +10 -0
  46. data/test/test_one.rb.~1.1.~ +5 -0
  47. data/test/test_one_syck.rb +5 -0
  48. data/test/test_rbyaml.rb +63 -32
  49. data/test/test_rbyaml.rb.~1.6.~ +59 -0
  50. data/test/{test_rbyaml.rb.~1.2.~ → test_rbyaml_old.rb} +13 -4
  51. data/test/test_time_events.rb +24 -0
  52. data/test/test_time_nodes.rb +24 -0
  53. data/test/test_time_tokens.rb +24 -0
  54. data/test/yaml/gems_new.yml +147456 -0
  55. data/test/yaml/test1.rb +8 -0
  56. data/test/yaml/test10.rb +14 -0
  57. data/test/yaml/test11.rb +13 -0
  58. data/test/yaml/test12.rb +9 -0
  59. data/test/yaml/test13.rb +9 -0
  60. data/test/yaml/test14.rb +13 -0
  61. data/test/yaml/test15.rb +12 -0
  62. data/test/yaml/test16.rb +11 -0
  63. data/test/yaml/test16.rb.~1.1.~ +11 -0
  64. data/test/yaml/test17.rb +10 -0
  65. data/test/yaml/test18.rb +13 -0
  66. data/test/yaml/test19.rb +9 -0
  67. data/test/yaml/test19.yml +1 -1
  68. data/test/yaml/test2.rb +8 -0
  69. data/test/yaml/test20.rb +11 -0
  70. data/test/yaml/test20.rb.~1.1.~ +9 -0
  71. data/test/yaml/test20.yml +1 -1
  72. data/test/yaml/test3.rb +13 -0
  73. data/test/yaml/test4.rb +13 -0
  74. data/test/yaml/test5.rb +8 -0
  75. data/test/yaml/test6.rb +10 -0
  76. data/test/yaml/test7.rb +15 -0
  77. data/test/yaml/test8.rb +15 -0
  78. data/test/yaml/test9.rb +13 -0
  79. metadata +61 -16
  80. data/lib/rbyaml/dumper.rb.~1.2.~ +0 -43
  81. data/lib/rbyaml/parser.rb.~1.2.~ +0 -494
@@ -3,7 +3,7 @@ require 'rbyaml/events'
3
3
  require 'rbyaml/nodes'
4
4
 
5
5
  module RbYAML
6
- class ComposerError < MarkedYAMLError
6
+ class ComposerError < YAMLError
7
7
  end
8
8
 
9
9
  class Composer
@@ -42,14 +42,14 @@ module RbYAML
42
42
  if @parser.peek_event.__is_alias
43
43
  event = @parser.get_event
44
44
  anchor = event.anchor
45
- raise ComposerError.new(nil, nil, "found undefined alias #{anchor}", event.start_mark) if !@anchors.include?(anchor)
45
+ raise ComposerError.new(nil, "found undefined alias #{anchor}") if !@anchors.include?(anchor)
46
46
  return @anchors[anchor]
47
47
  end
48
48
  event = @parser.peek_event
49
49
  anchor = event.anchor
50
50
  if !anchor.nil?
51
51
  if @anchors.include?(anchor)
52
- raise ComposerError.new("found duplicate anchor #{anchor}; first occurence", @anchors[anchor].start_mark,"second occurence", event.start_mark)
52
+ raise ComposerError.new("found duplicate anchor #{anchor}; first occurence","second occurence")
53
53
  end
54
54
  end
55
55
  @resolver.descend_resolver(parent,index)
@@ -68,7 +68,7 @@ module RbYAML
68
68
  event = @parser.get_event
69
69
  tag = event.tag
70
70
  tag = @resolver.resolve(ScalarNode,event.value,event.implicit) if tag.nil? || tag == "!"
71
- node = ScalarNode.new(tag, event.value,event.start_mark, event.end_mark, event.style)
71
+ node = ScalarNode.new(tag, event.value,event.style)
72
72
  @anchors[anchor] = node if !anchor.nil?
73
73
  node
74
74
  end
@@ -77,15 +77,14 @@ module RbYAML
77
77
  start_event = @parser.get_event
78
78
  tag = start_event.tag
79
79
  tag = @resolver.resolve(SequenceNode,nil,start_event.implicit) if tag.nil? || tag == "!"
80
- node = SequenceNode.new(tag,[],start_event.start_mark,nil,start_event.flow_style)
80
+ node = SequenceNode.new(tag,[],start_event.flow_style)
81
81
  @anchors[anchor] = node if !anchor.nil?
82
82
  index = 0
83
83
  while !@parser.peek_event.__is_sequence_end
84
84
  node.value << compose_node(node,index)
85
85
  index += 1
86
86
  end
87
- end_event = @parser.get_event
88
- node.end_mark = end_event.end_mark
87
+ @parser.get_event
89
88
  node
90
89
  end
91
90
 
@@ -93,19 +92,18 @@ module RbYAML
93
92
  start_event = @parser.get_event
94
93
  tag = start_event.tag
95
94
  tag = @resolver.resolve(MappingNode,nil,start_event.implicit) if tag.nil? || tag == "!"
96
- node = MappingNode.new(tag, {},start_event.start_mark,nil,start_event.flow_style)
95
+ node = MappingNode.new(tag, {},start_event.flow_style)
97
96
  @anchors[anchor] = node if !anchor.nil?
98
97
  while !@parser.peek_event.__is_mapping_end
99
98
  key_event = @parser.peek_event
100
99
  item_key = compose_node(node,nil)
101
100
  if node.value.include?(item_key)
102
- raise ComposerError.new("while composing a mapping", start_event.start_mark,"found duplicate key", key_event.start_mark)
101
+ raise ComposerError.new("while composing a mapping","found duplicate key")
103
102
  end
104
103
  item_value = compose_node(node,item_key)
105
104
  node.value[item_key] = item_value
106
105
  end
107
- end_event = @parser.get_event
108
- node.end_mark = end_event.end_mark
106
+ @parser.get_event
109
107
  node
110
108
  end
111
109
  end
@@ -6,13 +6,15 @@ module RbYAML
6
6
  class ComposerError < MarkedYAMLError
7
7
  end
8
8
 
9
- module Composer
10
- def initialize_composer
9
+ class Composer
10
+ def initialize(parser,resolver)
11
+ @parser = parser
12
+ @resolver = resolver
11
13
  @anchors = {}
12
14
  end
13
15
 
14
16
  def check_node
15
- !check_event(StreamEndEvent)
17
+ !@parser.peek_event.__is_stream_end
16
18
  end
17
19
 
18
20
  def get_node
@@ -25,75 +27,76 @@ module RbYAML
25
27
 
26
28
  def compose_document
27
29
  # Drop the STREAM-START event.
28
- get_event if check_event(StreamStartEvent)
29
- get_event
30
+ @parser.get_event if @parser.peek_event.__is_stream_start
31
+ # Drop the DOCUMENT-START event.
32
+ @parser.get_event
30
33
  # Compose the root node.
31
34
  node = compose_node(nil,nil)
32
35
  # Drop the DOCUMENT-END event.
33
- get_event
36
+ @parser.get_event
34
37
  @anchors = {}
35
38
  node
36
39
  end
37
40
 
38
41
  def compose_node(parent,index)
39
- if check_event(AliasEvent)
40
- event = get_event
42
+ if @parser.peek_event.__is_alias
43
+ event = @parser.get_event
41
44
  anchor = event.anchor
42
45
  raise ComposerError.new(nil, nil, "found undefined alias #{anchor}", event.start_mark) if !@anchors.include?(anchor)
43
46
  return @anchors[anchor]
44
47
  end
45
- event = peek_event
48
+ event = @parser.peek_event
46
49
  anchor = event.anchor
47
50
  if !anchor.nil?
48
51
  if @anchors.include?(anchor)
49
52
  raise ComposerError.new("found duplicate anchor #{anchor}; first occurence", @anchors[anchor].start_mark,"second occurence", event.start_mark)
50
53
  end
51
54
  end
52
- descend_resolver(parent,index)
53
- if check_event(ScalarEvent)
55
+ @resolver.descend_resolver(parent,index)
56
+ if @parser.peek_event.__is_scalar
54
57
  node = compose_scalar_node(anchor)
55
- elsif check_event(SequenceStartEvent)
58
+ elsif @parser.peek_event.__is_sequence_start
56
59
  node = compose_sequence_node(anchor)
57
- elsif check_event(MappingStartEvent)
60
+ elsif @parser.peek_event.__is_mapping_start
58
61
  node = compose_mapping_node(anchor)
59
62
  end
60
- ascend_resolver
63
+ @resolver.ascend_resolver
61
64
  node
62
65
  end
63
66
 
64
67
  def compose_scalar_node(anchor)
65
- event = get_event
68
+ event = @parser.get_event
66
69
  tag = event.tag
67
- tag = resolve(ScalarNode,event.value,event.implicit) if tag.nil? || tag == "!"
70
+ tag = @resolver.resolve(ScalarNode,event.value,event.implicit) if tag.nil? || tag == "!"
68
71
  node = ScalarNode.new(tag, event.value,event.start_mark, event.end_mark, event.style)
69
72
  @anchors[anchor] = node if !anchor.nil?
70
73
  node
71
74
  end
72
75
 
73
76
  def compose_sequence_node(anchor)
74
- start_event = get_event
77
+ start_event = @parser.get_event
75
78
  tag = start_event.tag
76
- tag = resolve(SequenceNode,nil,start_event.implicit) if tag.nil? || tag == "!"
79
+ tag = @resolver.resolve(SequenceNode,nil,start_event.implicit) if tag.nil? || tag == "!"
77
80
  node = SequenceNode.new(tag,[],start_event.start_mark,nil,start_event.flow_style)
78
81
  @anchors[anchor] = node if !anchor.nil?
79
82
  index = 0
80
- while !check_event(SequenceEndEvent)
83
+ while !@parser.peek_event.__is_sequence_end
81
84
  node.value << compose_node(node,index)
82
85
  index += 1
83
86
  end
84
- end_event = get_event
87
+ end_event = @parser.get_event
85
88
  node.end_mark = end_event.end_mark
86
89
  node
87
90
  end
88
91
 
89
92
  def compose_mapping_node(anchor)
90
- start_event = get_event
93
+ start_event = @parser.get_event
91
94
  tag = start_event.tag
92
- tag = resolve(MappingNode,nil,start_event.implicit) if tag.nil? || tag == "!"
95
+ tag = @resolver.resolve(MappingNode,nil,start_event.implicit) if tag.nil? || tag == "!"
93
96
  node = MappingNode.new(tag, {},start_event.start_mark,nil,start_event.flow_style)
94
97
  @anchors[anchor] = node if !anchor.nil?
95
- while !check_event(MappingEndEvent)
96
- key_event = peek_event
98
+ while !@parser.peek_event.__is_mapping_end
99
+ key_event = @parser.peek_event
97
100
  item_key = compose_node(node,nil)
98
101
  if node.value.include?(item_key)
99
102
  raise ComposerError.new("while composing a mapping", start_event.start_mark,"found duplicate key", key_event.start_mark)
@@ -101,7 +104,7 @@ module RbYAML
101
104
  item_value = compose_node(node,item_key)
102
105
  node.value[item_key] = item_value
103
106
  end
104
- end_event = get_event
107
+ end_event = @parser.get_event
105
108
  node.end_mark = end_event.end_mark
106
109
  node
107
110
  end
@@ -0,0 +1,95 @@
1
+ require 'rbyaml/emitter'
2
+ require 'rbyaml/serializer'
3
+ require 'rbyaml/representer'
4
+ require 'rbyaml/resolver'
5
+
6
+ module RbYAML
7
+ #
8
+ # Constants
9
+ #
10
+ VERSION = '0.20'
11
+ SUPPORTED_YAML_VERSIONS = ['1.0','1.1']
12
+
13
+ LINE_BR_REG = /[\n\x85]|(?:\r[^\n])/
14
+ NON_PRINTABLE_RE = /[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\xFF]/
15
+
16
+ ENDING = /^---[\0 \t\r\n\x85]$/
17
+ START = /^\.\.\.[\0 \t\r\n\x85]$/
18
+ NULL_OR_OTHER = "\0 \t\r\n\x85"
19
+ # BEG = /^([^\0 \t\r\n\x85\-?:,\[\]{}#&*!|>'"%@`]|([\-?:][^\0 \t\r\n\x85]))/ #Since current SYCK handles this one wrong, we have to allow backtick right now.
20
+ BEG = /^([^\0 \t\r\n\x85\-?:,\[\]{}#&*!|>'"%@]|([\-?:][^\0 \t\r\n\x85]))/
21
+ NULL_OR_LINEBR = "\0\r\n\x85"
22
+ ALPHA_REG = /[-0-9A-Za-z_]/
23
+ NULL_BL_LINEBR = "\0 \r\n\x85"
24
+ NULL_BL_T_LINEBR = NULL_OR_OTHER
25
+ NON_ALPHA = /[^-0-9A-Za-z_]/
26
+ NON_ALPHA_OR_NUM = "\0 \t\r\n\x85?:,]}%@`"
27
+ NULL_T_BL_LINEBR = NULL_OR_OTHER
28
+ BLANK_T = " \t"
29
+ PLUS_MIN = /[+-]/
30
+ BLANK_OR_LINEBR = " \r\n\x85"
31
+ FULL_LINEBR = "\r\n\x85"
32
+ UNESCAPES = {
33
+ "0" => "\0",
34
+ "a" => "\x07",
35
+ "b" => "\x08",
36
+ "t" => "\x09",
37
+ "\t" => "\x09",
38
+ "n" => "\x0A",
39
+ "v" => "\x0B",
40
+ "f" => "\x0C",
41
+ "r" => "\x0D",
42
+ "e" => "\x1B",
43
+ " " => "\x20",
44
+ '"' => '"',
45
+ "\\" => "\\",
46
+ "N" => "\x85",
47
+ "_" => "\xA0"
48
+ }
49
+
50
+ ESCAPE_CODES = {
51
+ 'x' => 2
52
+ }
53
+
54
+
55
+ ESCAPE_REPLACEMENTS = {
56
+ ?\0 => "0",
57
+ ?\x07 => "a",
58
+ ?\x08 => "b",
59
+ ?\x09 => "t",
60
+ ?\x0A => "n",
61
+ ?\x0B => "v",
62
+ ?\x0C => "f",
63
+ ?\x0D => "r",
64
+ ?\x1B => "e",
65
+ ?" => "\"",
66
+ ?\\ => "\\",
67
+ ?\x85 => "N",
68
+ ?\xA0 => "_"
69
+ }
70
+
71
+ SPACES_AND_STUFF = "'\"\\\0 \t\r\n\x85"
72
+ DOUBLE_ESC = "\"\\"
73
+ NOT_HEXA = /[^0-9A-Fa-f]/
74
+ R_flowzero = /[\0 \t\r\n\x85]|(:[\0 \t\r\n\x28])/
75
+ R_flownonzero = /[\0 \t\r\n\x85\[\]{},:?]/
76
+ S4 = "\0 \t\r\n\x28[]{}"
77
+ END_OR_START = /^(---|\.\.\.)[\0 \t\r\n\x85]$/
78
+ STRANGE_CHR = /[\]\[\-';\/?:@&=+$,.!~*()%\w]/
79
+ HEXA_REG = /[0-9A-Fa-f]/
80
+
81
+ #
82
+ # Default settings
83
+ #
84
+ DEFAULTS = {
85
+ :Indent => 2, :UseHeader => false, :UseVersion => false, :Version => '1.1',
86
+ :ExplicitStart => true, :ExplicitEnd => false,
87
+ :SortKeys => false, :AnchorFormat => 'id%03d', :ExplicitTypes => false,
88
+ :Canonical => false,
89
+ :WidthType => 'absolute', :BestWidth => 80,
90
+ :UseBlock => false, :UseFold => false, :Encoding => :None,
91
+ :UsePlain => false, :UseSingle => false, :UseDouble => false,
92
+ :Emitter => RbYAML::Emitter, :Serializer => RbYAML::Serializer,
93
+ :Representer => RbYAML::Representer, :Resolver => RbYAML::Resolver
94
+ }
95
+ end
@@ -1,5 +1,7 @@
1
1
  require 'base64'
2
- require 'set'
2
+ require 'date'
3
+
4
+ require 'rbyaml/util'
3
5
 
4
6
  require 'rbyaml/error'
5
7
  require 'rbyaml/nodes'
@@ -13,7 +15,7 @@ end
13
15
 
14
16
  class Proc
15
17
  def __call(obj,*args)
16
- call(*args)
18
+ call(obj,*args)
17
19
  end
18
20
  end
19
21
 
@@ -25,7 +27,7 @@ end
25
27
 
26
28
 
27
29
  module RbYAML
28
- class ConstructorError < MarkedYAMLError
30
+ class ConstructorError < YAMLError
29
31
  end
30
32
 
31
33
  class BaseConstructor
@@ -33,6 +35,31 @@ module RbYAML
33
35
  @@yaml_multi_constructors = {}
34
36
  @@yaml_multi_regexps = {}
35
37
 
38
+ def get_yaml_constructor(key)
39
+ @@yaml_constructors[key]
40
+ end
41
+
42
+ def get_yaml_multi_constructor(key)
43
+ @@yaml_multi_constructors[key]
44
+ end
45
+
46
+ def get_yaml_multi_regexp(key)
47
+ @@yaml_multi_regexps[key]
48
+ end
49
+
50
+ def get_yaml_multi_regexps
51
+ @@yaml_multi_regexps
52
+ end
53
+
54
+ def self.add_constructor(tag, constructor)
55
+ @@yaml_constructors[tag] = constructor
56
+ end
57
+
58
+ def self.add_multi_constructor(tag_prefix, multi_constructor)
59
+ @@yaml_multi_constructors[tag_prefix] = multi_constructor
60
+ @@yaml_multi_regexps[tag_prefix] = Regexp.new("^"+Regexp.escape(tag_prefix))
61
+ end
62
+
36
63
  def initialize(composer)
37
64
  @composer = composer
38
65
  @constructed_objects = {}
@@ -62,107 +89,127 @@ module RbYAML
62
89
  @recursive_objects = {}
63
90
  data
64
91
  end
92
+
93
+ class RecursiveProxy
94
+ attr_writer :value
95
+ def method_missing(*args)
96
+ @value.send(*args)
97
+ end
98
+ def class
99
+ @value.class
100
+ end
101
+ def to_s
102
+ @value.to_s
103
+ end
104
+ end
65
105
 
66
106
  def construct_object(node)
67
107
  return @constructed_objects[node] if @constructed_objects.include?(node)
68
- raise ConstructorError.new(nil,nil,"found recursive nod",node.start_mark) if @recursive_objects.include?(node)
69
- @recursive_objects[node] = nil
70
- constructor = @@yaml_constructors[node.tag]
108
+ @constructed_objects[node] = RecursiveProxy.new
109
+ constructor = get_yaml_constructor(node.tag)
71
110
  if !constructor
72
111
  ruby_cls = RbYAML::tagged_classes[node.tag]
73
112
  if ruby_cls && (ruby_cls.method_defined?(:yaml_initialize) || ruby_cls.respond_to?(:yaml_new))
74
- constructor = lambda { |node| send(:construct_ruby_object,ruby_cls,node) }
113
+ constructor = lambda { |obj,node| send(:construct_ruby_object,ruby_cls,node) }
75
114
  else
76
115
  through = true
77
- for tag_prefix,reg in @@yaml_multi_regexps
116
+ for tag_prefix,reg in get_yaml_multi_regexps
78
117
  if reg =~ node.tag
79
118
  tag_suffix = node.tag[tag_prefix.length..-1]
80
- constructor = lambda { |node| @@yaml_multi_constructors[tag_prefix].__call(self,tag_suffix, node) }
119
+ constructor = lambda { |obj, node| get_yaml_multi_constructor(tag_prefix).__call(self,tag_suffix, node) }
81
120
  through = false
82
121
  break
83
122
  end
84
123
  end
85
124
  if through
86
- ctor = @@yaml_multi_constructors[nil] || @@yaml_constructors[nil]
125
+ ctor = get_yaml_multi_constructor(nil)
87
126
  if ctor
88
- constructor = lambda { |node| ctor.__call(self,node.tag,node) }
127
+ constructor = lambda { |obj, node| ctor.__call(self,node.tag,node) }
89
128
  else
90
- constructor = lambda { |node| construct_primitive(node) }
129
+ ctor = get_yaml_constructor(nil)
130
+ if ctor
131
+ constructor = lambda { |obj, node| ctor.__call(self,node)}
132
+ else
133
+ constructor = lambda { |obj, node| construct_primitive(node) }
134
+ end
91
135
  end
92
136
  end
93
137
  end
94
138
  end
95
139
  data = constructor.__call(self,node)
140
+ @constructed_objects[node].value = data
96
141
  @constructed_objects[node] = data
97
- @recursive_objects.delete(node)
98
142
  data
99
143
  end
100
144
 
101
145
  def construct_primitive(node)
102
146
  if node.__is_scalar
103
- construct_scalar(node)
147
+ str(node)
104
148
  elsif node.__is_sequence
105
- construct_sequence(node)
149
+ seq(node)
106
150
  elsif node.__is_mapping
107
- construct_mapping(node)
151
+ map(node)
108
152
  else
109
153
  puts node.tag
110
154
  end
111
155
  end
112
156
 
113
- def construct_scalar(node)
157
+ def str(node)
114
158
  if !node.__is_scalar
115
159
  if node.__is_mapping
116
160
  for key_node in node.value.keys
117
161
  if key_node.tag == "tag:yaml.org,2002:value"
118
- return construct_scalar(node.value[key_node])
162
+ return str(node.value[key_node])
119
163
  end
120
164
  end
121
165
  end
122
- raise ConstructorError.new(nil, nil,"expected a scalar node, but found #{node.tid}",node.start_mark)
166
+ raise ConstructorError.new(nil,"expected a scalar node, but found #{node.tid}")
123
167
  end
124
168
  node.value
125
169
  end
126
170
 
127
- def construct_sequence(node)
128
- raise ConstructorError.new(nil,nil,"expected a sequence node, but found #{node.tid}",node.start_mark) if !node.__is_sequence
171
+ def construct_private_type(node)
172
+ PrivateType.new(node.tag,node.value)
173
+ end
174
+
175
+ def seq(node)
176
+ raise ConstructorError.new(nil,"expected a sequence node, but found #{node.tid}") if !node.__is_sequence
129
177
  node.value.map {|child| construct_object(child) }
130
178
  end
131
179
 
132
- def construct_mapping(node)
133
- raise ConstructorError.new(nil,nil,"expected a mapping node, but found #{node.tid}",node.start_mark) if !node.__is_mapping
180
+ def map(node)
181
+ raise ConstructorError.new(nil,"expected a mapping node, but found #{node.tid}") if !node.__is_mapping
134
182
  mapping = {}
135
183
  merge = nil
136
184
  for key_node,value_node in node.value
137
185
  if key_node.tag == "tag:yaml.org,2002:merge"
138
- raise ConstructorError.new("while constructing a mapping", node.start_mark,"found duplicate merge key", key_node.start_mark) if !merge.nil?
186
+ raise ConstructorError.new("while constructing a mapping","found duplicate merge key") if !merge.nil?
139
187
  if value_node.__is_mapping
140
- merge = [construct_mapping(value_node)]
188
+ merge = [map(value_node)]
141
189
  elsif value_node.__is_sequence
142
190
  merge = []
143
191
  for subnode in value_node.value
144
192
  if !subnode.__is_mapping
145
- raise ConstructorError.new("while constructing a mapping",node.start_mark,"expected a mapping for merging, but found #{subnode.tid}", subnode.start_mark)
193
+ raise ConstructorError.new("while constructing a mapping","expected a mapping for merging, but found #{subnode.tid}")
146
194
  end
147
- merge.unshift(construct_mapping(subnode))
195
+ merge.unshift(map(subnode))
148
196
  end
149
197
  else
150
- 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)
198
+ raise ConstructorError.new("while constructing a mapping","expected a mapping or list of mappings for merging, but found #{value_node.tid}")
151
199
  end
152
200
  elsif key_node.tag == "tag:yaml.org,2002:value"
153
- raise ConstructorError.new("while construction a mapping", node.start_mark,"found duplicate value key", key_node.start_mark) if mapping.include?("=")
201
+ raise ConstructorError.new("while construction a mapping","found duplicate value key") if mapping.include?("=")
154
202
  value = construct_object(value_node)
155
203
  mapping["="] = value
156
204
  else
157
205
  key = construct_object(key_node)
158
- # raise ConstructorError.new("while constructing a mapping", node.start_mark,"found duplicate key", key_node.start_mark) if mapping.include?(key)
206
+ value = construct_object(value_node)
207
+ mapping[key] = value
159
208
  end
160
- value = construct_object(value_node)
161
- mapping[key] = value
162
209
  end
163
210
  if !merge.nil?
164
211
  merge << mapping
165
- mapping = {}
212
+ mapping = { }
166
213
  for submapping in merge
167
214
  mapping.merge!(submapping)
168
215
  end
@@ -171,29 +218,49 @@ module RbYAML
171
218
  end
172
219
 
173
220
  def construct_pairs(node)
174
- raise ConstructorError.new(nil,nil,"expected a mapping node, but found #{node.tid}",node.start_mark) if !node.__is_mapping
221
+ raise ConstructorError.new(nil,"expected a mapping node, but found #{node.tid}") if !node.__is_mapping
175
222
  node.value.collect {|key_node,value_node| [construct_object(key_node), construct_object(value_node)] }
176
223
  end
224
+ end
177
225
 
226
+ class SafeConstructor < BaseConstructor
227
+ @@yaml_safe_constructors = {}
228
+ @@yaml_safe_multi_constructors = {}
229
+ @@yaml_safe_multi_regexps = {}
230
+
231
+ def get_yaml_constructor(key)
232
+ @@yaml_safe_constructors[key] || super(key)
233
+ end
234
+
235
+ def get_yaml_multi_constructor(key)
236
+ @@yaml_safe_multi_constructors[key] || super(key)
237
+ end
238
+
239
+ def get_yaml_multi_regexp(key)
240
+ @@yaml_safe_multi_regexps[key] || super(key)
241
+ end
242
+
243
+ def get_yaml_multi_regexps
244
+ super.update(@@yaml_safe_multi_regexps)
245
+ end
246
+
178
247
  def self.add_constructor(tag, constructor)
179
- @@yaml_constructors[tag] = constructor
248
+ @@yaml_safe_constructors[tag] = constructor
180
249
  end
181
250
 
182
251
  def self.add_multi_constructor(tag_prefix, multi_constructor)
183
- @@yaml_multi_constructors[tag_prefix] = multi_constructor
184
- @@yaml_multi_regexps[tag_prefix] = Regexp.new("^"+Regexp.escape(tag_prefix))
252
+ @@yaml_safe_multi_constructors[tag_prefix] = multi_constructor
253
+ @@yaml_safe_multi_regexps[tag_prefix] = Regexp.new("^"+Regexp.escape(tag_prefix))
185
254
  end
186
- end
187
255
 
188
- class SafeConstructor < BaseConstructor
189
256
  def construct_yaml_null(node)
190
- construct_scalar(node)
257
+ str(node)
191
258
  nil
192
259
  end
193
260
 
194
261
  BOOL_VALUES = {
195
- "y" => true,
196
- "n" => false,
262
+ # "y" => true,
263
+ # "n" => false,
197
264
  "yes" => true,
198
265
  "no" => false,
199
266
  "true" => true,
@@ -203,12 +270,12 @@ module RbYAML
203
270
  }
204
271
 
205
272
  def construct_yaml_bool(node)
206
- value = construct_scalar(node)
273
+ value = str(node)
207
274
  BOOL_VALUES[value.downcase]
208
275
  end
209
276
 
210
277
  def construct_yaml_int(node)
211
- value = construct_scalar(node).to_s
278
+ value = str(node).to_s
212
279
  value = value.gsub(/_/, '')
213
280
  sign = +1
214
281
  first = value[0]
@@ -249,7 +316,7 @@ module RbYAML
249
316
  NAN_VALUE = 0.0/0.0
250
317
 
251
318
  def construct_yaml_float(node)
252
- value = construct_scalar(node).to_s
319
+ value = str(node).to_s
253
320
  value = value.gsub(/_/, '')
254
321
  sign = +1
255
322
  first = value[0]
@@ -278,15 +345,22 @@ module RbYAML
278
345
  end
279
346
 
280
347
  def construct_yaml_binary(node)
281
- value = construct_scalar(node)
282
- Base64.decode64(value.to_s)
348
+ value = str(node)
349
+ Base64.decode64(value.split(/[\n\x85]|(?:\r[^\n])/).to_s)
283
350
  end
284
351
 
285
352
  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])?)?))?)?$/
353
+
354
+ YMD_REGEXP = /^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)$/
286
355
 
287
356
  def construct_yaml_timestamp(node)
288
- value = construct_scalar(node)
289
- match = TIMESTAMP_REGEXP.match(node.value)
357
+ if (match = YMD_REGEXP.match(node.value))
358
+ values = match.captures.map {|val| val.to_i}
359
+ return Date.new(values[0],values[1],values[2])
360
+ end
361
+ unless (match = TIMESTAMP_REGEXP.match(node.value))
362
+ return construct_private_type(node)
363
+ end
290
364
  values = match.captures.map {|val| val.to_i}
291
365
  fraction = values[6]
292
366
  if fraction != 0
@@ -302,14 +376,13 @@ module RbYAML
302
376
  def construct_yaml_omap(node)
303
377
  # Note: we do not check for duplicate keys, because its too
304
378
  # CPU-expensive.
305
- raise ConstructorError.new("while constructing an ordered map", node.start_mark,
306
- "expected a sequence, but found #{node.tid}", node.start_mark) if !node.__is_sequence
379
+ raise ConstructorError.new("while constructing an ordered map","expected a sequence, but found #{node.tid}") if !node.__is_sequence
307
380
  omap = []
308
381
  for subnode in node.value
309
- raise ConstructorError.new("while constructing an ordered map", node.start_mark,
310
- "expected a mapping of length 1, but found #{subnode.tid}",subnode.start_mark) if !subnode.__is_mapping
311
- raise ConstructorError.new("while constructing an ordered map", node.start_mark,
312
- "expected a single mapping item, but found #{subnode.value.length} items",subnode.start_mark) if subnode.value.length != 1
382
+ raise ConstructorError.new("while constructing an ordered map",
383
+ "expected a mapping of length 1, but found #{subnode.tid}") if !subnode.__is_mapping
384
+ raise ConstructorError.new("while constructing an ordered map",
385
+ "expected a single mapping item, but found #{subnode.value.length} items") if subnode.value.length != 1
313
386
  key_node = subnode.value.keys[0]
314
387
  key = construct_object(key_node)
315
388
  value = construct_object(subnode.value[key_node])
@@ -323,69 +396,87 @@ module RbYAML
323
396
  end
324
397
 
325
398
  def construct_yaml_set(node)
326
- Set.new(construct_mapping(node).keys)
399
+ Set.new(map(node).keys)
327
400
  end
328
401
 
329
402
  def construct_yaml_str(node)
330
- construct_scalar(node).to_s
403
+ val = str(node).to_s
404
+ val.empty? ? nil : val
331
405
  end
332
406
 
333
407
  def construct_yaml_seq(node)
334
- construct_sequence(node)
408
+ seq(node)
335
409
  end
336
410
 
337
411
  def construct_yaml_map(node)
338
- construct_mapping(node)
412
+ map(node)
339
413
  end
340
414
 
341
415
  def construct_yaml_object(node, cls)
342
- mapping = construct_mapping(node)
416
+ mapping = map(node)
343
417
  data = cls.new
344
418
  mapping.each {|key,val| data.instance_variable_set("@#{key}",val)}
345
419
  data
346
420
  end
347
421
 
348
422
  def construct_undefined(node)
349
- raise ConstructorError.new(nil,nil,"could not determine a constructor for the tag #{node.tag}",node.start_mark)
423
+ raise ConstructorError.new(nil,"could not determine a constructor for the tag #{node.tag}")
350
424
  end
425
+ end
426
+
427
+ SafeConstructor.add_constructor('tag:yaml.org,2002:null',:construct_yaml_null)
428
+ SafeConstructor.add_constructor('tag:yaml.org,2002:bool',:construct_yaml_bool)
429
+ SafeConstructor.add_constructor('tag:yaml.org,2002:int',:construct_yaml_int)
430
+ SafeConstructor.add_constructor('tag:yaml.org,2002:float',:construct_yaml_float)
431
+ SafeConstructor.add_constructor('tag:yaml.org,2002:binary',:construct_yaml_binary)
432
+ SafeConstructor.add_constructor('tag:yaml.org,2002:timestamp',:construct_yaml_timestamp)
433
+ SafeConstructor.add_constructor('tag:yaml.org,2002:omap',:construct_yaml_omap)
434
+ SafeConstructor.add_constructor('tag:yaml.org,2002:pairs',:construct_yaml_pairs)
435
+ SafeConstructor.add_constructor('tag:yaml.org,2002:set',:construct_yaml_set)
436
+ SafeConstructor.add_constructor('tag:yaml.org,2002:str',:construct_yaml_str)
437
+ SafeConstructor.add_constructor('tag:yaml.org,2002:seq',:construct_yaml_seq)
438
+ SafeConstructor.add_constructor('tag:yaml.org,2002:map',:construct_yaml_map)
439
+ SafeConstructor.add_constructor(nil,:construct_private_type)
351
440
 
352
- def construct_ruby_object(cls,node)
353
- val = construct_primitive(node)
354
- if cls.respond_to?(:yaml_new)
355
- obj = cls.yaml_new(cls,node.tag,val)
356
- else
357
- obj = cls.allocate
358
- obj.yaml_initialize(node.tag,val)
359
- end
360
- obj
441
+ class Constructor < SafeConstructor
442
+ @@yaml_main_constructors = {}
443
+ @@yaml_main_multi_constructors = {}
444
+ @@yaml_main_multi_regexps = {}
445
+
446
+ def get_yaml_constructor(key)
447
+ @@yaml_main_constructors[key] || super(key)
448
+ end
449
+
450
+ def get_yaml_multi_constructor(key)
451
+ @@yaml_main_multi_constructors[key] || super(key)
452
+ end
453
+
454
+ def get_yaml_multi_regexp(key)
455
+ @@yaml_main_multi_regexps[key] || super(key)
456
+ end
457
+
458
+ def get_yaml_multi_regexps
459
+ super.update(@@yaml_main_multi_regexps)
460
+ end
461
+
462
+ def self.add_constructor(tag, constructor)
463
+ @@yaml_main_constructors[tag] = constructor
464
+ end
465
+
466
+ def self.add_multi_constructor(tag_prefix, multi_constructor)
467
+ @@yaml_main_multi_constructors[tag_prefix] = multi_constructor
468
+ @@yaml_main_multi_regexps[tag_prefix] = Regexp.new("^"+Regexp.escape(tag_prefix))
361
469
  end
362
470
 
363
471
  def construct_ruby(tag,node)
364
472
  obj_class = Object
365
473
  tag.split( "::" ).each { |c| obj_class = obj_class.const_get( c ) } if tag
366
474
  o = obj_class.allocate
367
- mapping = construct_mapping(node)
475
+ mapping = map(node)
368
476
  mapping.each {|key,val| o.instance_variable_set("@#{key}",val)}
369
477
  o
370
478
  end
371
479
  end
372
-
373
- SafeConstructor::add_constructor('tag:yaml.org,2002:null',:construct_yaml_null)
374
- BaseConstructor::add_constructor('tag:yaml.org,2002:bool',:construct_yaml_bool)
375
- BaseConstructor::add_constructor('tag:yaml.org,2002:int',:construct_yaml_int)
376
- BaseConstructor::add_constructor('tag:yaml.org,2002:float',:construct_yaml_float)
377
- BaseConstructor::add_constructor('tag:yaml.org,2002:binary',:construct_yaml_binary)
378
- BaseConstructor::add_constructor('tag:yaml.org,2002:timestamp',:construct_yaml_timestamp)
379
- BaseConstructor::add_constructor('tag:yaml.org,2002:omap',:construct_yaml_omap)
380
- BaseConstructor::add_constructor('tag:yaml.org,2002:pairs',:construct_yaml_pairs)
381
- BaseConstructor::add_constructor('tag:yaml.org,2002:set',:construct_yaml_set)
382
- BaseConstructor::add_constructor('tag:yaml.org,2002:str',:construct_yaml_str)
383
- BaseConstructor::add_constructor('tag:yaml.org,2002:seq',:construct_yaml_seq)
384
- BaseConstructor::add_constructor('tag:yaml.org,2002:map',:construct_yaml_map)
385
- BaseConstructor::add_constructor(nil,:construct_undefined)
386
-
387
- BaseConstructor::add_multi_constructor("!ruby/object:",:construct_ruby)
388
480
 
389
- class Constructor < SafeConstructor
390
- end
481
+ Constructor.add_multi_constructor("!ruby/object:",:construct_ruby)
391
482
  end