syck 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/.autotest.erb +8 -0
  2. data/.gemtest +0 -0
  3. data/CHANGELOG.rdoc +6 -0
  4. data/Manifest.txt +52 -0
  5. data/README.rdoc +51 -0
  6. data/Rakefile +32 -0
  7. data/ext/syck/bytecode.c +1165 -0
  8. data/ext/syck/emitter.c +1247 -0
  9. data/ext/syck/extconf.h +3 -0
  10. data/ext/syck/extconf.rb +5 -0
  11. data/ext/syck/gram.c +1894 -0
  12. data/ext/syck/gram.h +79 -0
  13. data/ext/syck/handler.c +173 -0
  14. data/ext/syck/implicit.c +2990 -0
  15. data/ext/syck/node.c +407 -0
  16. data/ext/syck/rubyext.c +2328 -0
  17. data/ext/syck/syck.c +524 -0
  18. data/ext/syck/syck.h +453 -0
  19. data/ext/syck/token.c +2724 -0
  20. data/ext/syck/yaml2byte.c +259 -0
  21. data/ext/syck/yamlbyte.h +171 -0
  22. data/lib/syck.bundle +0 -0
  23. data/lib/syck.rb +447 -0
  24. data/lib/syck/baseemitter.rb +242 -0
  25. data/lib/syck/basenode.rb +222 -0
  26. data/lib/syck/constants.rb +45 -0
  27. data/lib/syck/encoding.rb +35 -0
  28. data/lib/syck/error.rb +34 -0
  29. data/lib/syck/loader.rb +14 -0
  30. data/lib/syck/rubytypes.rb +450 -0
  31. data/lib/syck/stream.rb +41 -0
  32. data/lib/syck/stringio.rb +85 -0
  33. data/lib/syck/syck.rb +16 -0
  34. data/lib/syck/tag.rb +95 -0
  35. data/lib/syck/types.rb +192 -0
  36. data/lib/syck/yamlnode.rb +54 -0
  37. data/lib/syck/ypath.rb +54 -0
  38. data/lib/yaml/syck.rb +14 -0
  39. data/test/helper.rb +2 -0
  40. data/test/test_array.rb +13 -0
  41. data/test/test_boolean.rb +36 -0
  42. data/test/test_class.rb +11 -0
  43. data/test/test_exception.rb +45 -0
  44. data/test/test_hash.rb +24 -0
  45. data/test/test_null.rb +19 -0
  46. data/test/test_omap.rb +55 -0
  47. data/test/test_set.rb +30 -0
  48. data/test/test_string.rb +44 -0
  49. data/test/test_struct.rb +32 -0
  50. data/test/test_symbol.rb +21 -0
  51. data/test/test_time.rb +23 -0
  52. data/test/test_yaml.rb +1403 -0
  53. data/test/test_yaml_properties.rb +63 -0
  54. metadata +187 -0
@@ -0,0 +1,242 @@
1
+ #
2
+ # BaseEmitter
3
+ #
4
+
5
+ require 'syck/constants'
6
+ require 'syck/encoding'
7
+ require 'syck/error'
8
+
9
+ module Syck
10
+ module BaseEmitter
11
+ def options( opt = nil )
12
+ if opt
13
+ @options[opt] || DEFAULTS[opt]
14
+ else
15
+ @options
16
+ end
17
+ end
18
+
19
+ def options=( opt )
20
+ @options = opt
21
+ end
22
+
23
+ #
24
+ # Emit binary data
25
+ #
26
+ def binary_base64( value )
27
+ self << "!binary "
28
+ self.node_text( [value].pack("m"), '|' )
29
+ end
30
+
31
+ #
32
+ # Emit plain, normal flowing text
33
+ #
34
+ def node_text( value, block = nil )
35
+ @seq_map = false
36
+ valx = value.dup
37
+ unless block
38
+ block =
39
+ if options(:UseBlock)
40
+ '|'
41
+ elsif not options(:UseFold) and valx =~ /\n[ \t]/ and not valx =~ /#{ESCAPE_CHAR}/
42
+ '|'
43
+ else
44
+ '>'
45
+ end
46
+ indt = $&.to_i if block =~ /\d+/
47
+ if valx =~ /(\A\n*[ \t#]|^---\s+)/
48
+ indt = options(:Indent) unless indt.to_i > 0
49
+ block += indt.to_s
50
+ end
51
+
52
+ block +=
53
+ if valx =~ /\n\Z\n/
54
+ "+"
55
+ elsif valx =~ /\Z\n/
56
+ ""
57
+ else
58
+ "-"
59
+ end
60
+ end
61
+ block += "\n"
62
+ if block[0] == ?"
63
+ esc_skip = ( "\t\n" unless valx =~ /^[ \t]/ ) || ""
64
+ valx = fold( Syck.escape( valx, esc_skip ) + "\"" ).chomp
65
+ self << '"' + indent_text( valx, indt, false )
66
+ else
67
+ if block[0] == ?>
68
+ valx = fold( valx )
69
+ end
70
+ #p [block, indt]
71
+ self << block + indent_text( valx, indt )
72
+ end
73
+ end
74
+
75
+ #
76
+ # Emit a simple, unqouted string
77
+ #
78
+ def simple( value )
79
+ @seq_map = false
80
+ self << value.to_s
81
+ end
82
+
83
+ #
84
+ # Emit double-quoted string
85
+ #
86
+ def double( value )
87
+ "\"#{Syck.escape( value )}\""
88
+ end
89
+
90
+ #
91
+ # Emit single-quoted string
92
+ #
93
+ def single( value )
94
+ "'#{value}'"
95
+ end
96
+
97
+ #
98
+ # Write a text block with the current indent
99
+ #
100
+ def indent_text( text, mod, first_line = true )
101
+ return "" if text.to_s.empty?
102
+ spacing = indent( mod )
103
+ text = text.gsub( /\A([^\n])/, "#{ spacing }\\1" ) if first_line
104
+ return text.gsub( /\n^([^\n])/, "\n#{spacing}\\1" )
105
+ end
106
+
107
+ #
108
+ # Write a current indent
109
+ #
110
+ def indent( mod = nil )
111
+ #p [ self.id, level, mod, :INDENT ]
112
+ if level <= 0
113
+ mod ||= 0
114
+ else
115
+ mod ||= options(:Indent)
116
+ mod += ( level - 1 ) * options(:Indent)
117
+ end
118
+ return " " * mod
119
+ end
120
+
121
+ #
122
+ # Add indent to the buffer
123
+ #
124
+ def indent!
125
+ self << indent
126
+ end
127
+
128
+ #
129
+ # Folding paragraphs within a column
130
+ #
131
+ def fold( value )
132
+ value.gsub( /(^[ \t]+.*$)|(\S.{0,#{options(:BestWidth) - 1}})(?:[ \t]+|(\n+(?=[ \t]|\Z))|$)/ ) do
133
+ $1 || $2 + ( $3 || "\n" )
134
+ end
135
+ end
136
+
137
+ #
138
+ # Quick mapping
139
+ #
140
+ def map( type, &e )
141
+ val = Mapping.new
142
+ e.call( val )
143
+ self << "#{type} " if type.length.nonzero?
144
+
145
+ #
146
+ # Empty hashes
147
+ #
148
+ if val.length.zero?
149
+ self << "{}"
150
+ @seq_map = false
151
+ else
152
+ # FIXME
153
+ # if @buffer.length == 1 and options(:UseHeader) == false and type.length.zero?
154
+ # @headless = 1
155
+ # end
156
+
157
+ defkey = @options.delete( :DefaultKey )
158
+ if defkey
159
+ seq_map_shortcut
160
+ self << "= : "
161
+ defkey.to_yaml( :Emitter => self )
162
+ end
163
+
164
+ #
165
+ # Emit the key and value
166
+ #
167
+ val.each { |v|
168
+ seq_map_shortcut
169
+ if v[0].is_complex_yaml?
170
+ self << "? "
171
+ end
172
+ v[0].to_yaml( :Emitter => self )
173
+ if v[0].is_complex_yaml?
174
+ self << "\n"
175
+ indent!
176
+ end
177
+ self << ": "
178
+ v[1].to_yaml( :Emitter => self )
179
+ }
180
+ end
181
+ end
182
+
183
+ def seq_map_shortcut
184
+ # FIXME: seq_map needs to work with the new anchoring system
185
+ # if @seq_map
186
+ # @anchor_extras[@buffer.length - 1] = "\n" + indent
187
+ # @seq_map = false
188
+ # else
189
+ self << "\n"
190
+ indent!
191
+ # end
192
+ end
193
+
194
+ #
195
+ # Quick sequence
196
+ #
197
+ def seq( type, &e )
198
+ @seq_map = false
199
+ val = Sequence.new
200
+ e.call( val )
201
+ self << "#{type} " if type.length.nonzero?
202
+
203
+ #
204
+ # Empty arrays
205
+ #
206
+ if val.length.zero?
207
+ self << "[]"
208
+ else
209
+ # FIXME
210
+ # if @buffer.length == 1 and options(:UseHeader) == false and type.length.zero?
211
+ # @headless = 1
212
+ # end
213
+
214
+ #
215
+ # Emit the key and value
216
+ #
217
+ val.each { |v|
218
+ self << "\n"
219
+ indent!
220
+ self << "- "
221
+ @seq_map = true if v.class == Hash
222
+ v.to_yaml( :Emitter => self )
223
+ }
224
+ end
225
+ end
226
+ end
227
+
228
+ #
229
+ # Emitter helper classes
230
+ #
231
+ class Mapping < Array
232
+ def add( k, v )
233
+ push [k, v]
234
+ end
235
+ end
236
+
237
+ class Sequence < Array
238
+ def add( v )
239
+ push v
240
+ end
241
+ end
242
+ end
@@ -0,0 +1,222 @@
1
+ #
2
+ # YAML::BaseNode class
3
+ #
4
+
5
+ module Syck
6
+
7
+ #
8
+ # YAML Generic Model container
9
+ #
10
+ module BaseNode
11
+
12
+ #
13
+ # Search for YPath entry and return
14
+ # qualified nodes.
15
+ #
16
+ def select( ypath_str )
17
+ warn "#{caller[0]}: select is deprecated" if $VERBOSE
18
+ matches = match_path( ypath_str )
19
+
20
+ #
21
+ # Create a new generic view of the elements selected
22
+ #
23
+ if matches
24
+ result = []
25
+ matches.each { |m|
26
+ result.push m.last
27
+ }
28
+ Syck.transfer( 'seq', result )
29
+ end
30
+ end
31
+
32
+ #
33
+ # Search for YPath entry and return
34
+ # transformed nodes.
35
+ #
36
+ def select!( ypath_str )
37
+ warn "#{caller[0]}: select!() is deprecated" if $VERBOSE
38
+ matches = match_path( ypath_str )
39
+
40
+ #
41
+ # Create a new generic view of the elements selected
42
+ #
43
+ if matches
44
+ result = []
45
+ matches.each { |m|
46
+ result.push m.last.transform
47
+ }
48
+ result
49
+ end
50
+ end
51
+
52
+ #
53
+ # Search for YPath entry and return a list of
54
+ # qualified paths.
55
+ #
56
+ def search( ypath_str )
57
+ warn "#{caller[0]}: search() is deprecated" if $VERBOSE
58
+ matches = match_path( ypath_str )
59
+
60
+ if matches
61
+ matches.collect { |m|
62
+ path = []
63
+ m.each_index { |i|
64
+ path.push m[i] if ( i % 2 ).zero?
65
+ }
66
+ "/" + path.compact.join( "/" )
67
+ }
68
+ end
69
+ end
70
+
71
+ def at( seg )
72
+ warn "#{caller[0]}: at() is deprecated" if $VERBOSE
73
+ if Hash === @value
74
+ self[seg]
75
+ elsif Array === @value and seg =~ /\A\d+\Z/ and @value[seg.to_i]
76
+ @value[seg.to_i]
77
+ end
78
+ end
79
+
80
+ #
81
+ # YPath search returning a complete depth array
82
+ #
83
+ def match_path( ypath_str )
84
+ warn "#{caller[0]}: match_path is deprecated" if $VERBOSE
85
+ require 'syck/ypath'
86
+ matches = []
87
+ YPath.each_path( ypath_str ) do |ypath|
88
+ seg = match_segment( ypath, 0 )
89
+ matches += seg if seg
90
+ end
91
+ matches.uniq
92
+ end
93
+
94
+ #
95
+ # Search a node for a single YPath segment
96
+ #
97
+ def match_segment( ypath, depth )
98
+ warn "#{caller[0]}: match_segment is deprecated" if $VERBOSE
99
+ deep_nodes = []
100
+ seg = ypath.segments[ depth ]
101
+ if seg == "/"
102
+ unless String === @value
103
+ idx = -1
104
+ @value.collect { |v|
105
+ idx += 1
106
+ if Hash === @value
107
+ match_init = [v[0].transform, v[1]]
108
+ match_deep = v[1].match_segment( ypath, depth )
109
+ else
110
+ match_init = [idx, v]
111
+ match_deep = v.match_segment( ypath, depth )
112
+ end
113
+ if match_deep
114
+ match_deep.each { |m|
115
+ deep_nodes.push( match_init + m )
116
+ }
117
+ end
118
+ }
119
+ end
120
+ depth += 1
121
+ seg = ypath.segments[ depth ]
122
+ end
123
+ match_nodes =
124
+ case seg
125
+ when "."
126
+ [[nil, self]]
127
+ when ".."
128
+ [["..", nil]]
129
+ when "*"
130
+ if @value.is_a? Enumerable
131
+ idx = -1
132
+ @value.collect { |h|
133
+ idx += 1
134
+ if Hash === @value
135
+ [h[0].transform, h[1]]
136
+ else
137
+ [idx, h]
138
+ end
139
+ }
140
+ end
141
+ else
142
+ if seg =~ /^"(.*)"$/
143
+ seg = $1
144
+ elsif seg =~ /^'(.*)'$/
145
+ seg = $1
146
+ end
147
+ if ( v = at( seg ) )
148
+ [[ seg, v ]]
149
+ end
150
+ end
151
+ return deep_nodes unless match_nodes
152
+ pred = ypath.predicates[ depth ]
153
+ if pred
154
+ case pred
155
+ when /^\.=/
156
+ pred = $' # '
157
+ match_nodes.reject! { |n|
158
+ n.last.value != pred
159
+ }
160
+ else
161
+ match_nodes.reject! { |n|
162
+ n.last.at( pred ).nil?
163
+ }
164
+ end
165
+ end
166
+ return match_nodes + deep_nodes unless ypath.segments.length > depth + 1
167
+
168
+ #puts "DEPTH: #{depth + 1}"
169
+ deep_nodes = []
170
+ match_nodes.each { |n|
171
+ if n[1].is_a? BaseNode
172
+ match_deep = n[1].match_segment( ypath, depth + 1 )
173
+ if match_deep
174
+ match_deep.each { |m|
175
+ deep_nodes.push( n + m )
176
+ }
177
+ end
178
+ else
179
+ deep_nodes = []
180
+ end
181
+ }
182
+ deep_nodes = nil if deep_nodes.length == 0
183
+ deep_nodes
184
+ end
185
+
186
+ #
187
+ # We want the node to act like as Hash
188
+ # if it is.
189
+ #
190
+ def []( *key )
191
+ if Hash === @value
192
+ v = @value.detect { |k,| k.transform == key.first }
193
+ v[1] if v
194
+ elsif Array === @value
195
+ @value.[]( *key )
196
+ end
197
+ end
198
+
199
+ def children
200
+ if Hash === @value
201
+ @value.values.collect { |c| c[1] }
202
+ elsif Array === @value
203
+ @value
204
+ end
205
+ end
206
+
207
+ def children_with_index
208
+ warn "#{caller[0]}: children_with_index is deprecated, use children" if $VERBOSE
209
+ if Hash === @value
210
+ @value.keys.collect { |i| [self[i], i] }
211
+ elsif Array === @value
212
+ i = -1; @value.collect { |v| i += 1; [v, i] }
213
+ end
214
+ end
215
+
216
+ def emit
217
+ transform.to_yaml
218
+ end
219
+ end
220
+
221
+ end
222
+