ya2yaml 0.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. data/LICENSE +19 -0
  2. data/README +107 -0
  3. data/lib/ya2yaml.rb +356 -0
  4. data/test/t.gif +0 -0
  5. data/test/t.yaml +5 -0
  6. data/test/test.rb +341 -0
  7. metadata +54 -0
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2006 Akira FUNAI <funai.akira@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a
4
+ copy of this software and associated documentation files (the "Software"),
5
+ to deal in the Software without restriction, including without limitation
6
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
7
+ and/or sell copies of the Software, and to permit persons to whom the
8
+ Software is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19
+ DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,107 @@
1
+ = Ya2YAML - An UTF8 safe YAML dumper
2
+
3
+ Project Contact: Akira FUNAI <mailto:funai.akira@gmail.com>
4
+
5
+ Ya2YAML is "yet another to_yaml". It emits YAML document with complete UTF8 support (string/binary detection, "\u" escape sequences and Unicode specific line breaks). I hope someone might find it useful until Syck/RbYAML come out with UTF8/16 support.
6
+
7
+ == Usage
8
+
9
+ *code*:
10
+
11
+ $KCODE = 'UTF8'
12
+ require 'ya2yaml'
13
+
14
+ obj = [
15
+ "abc\nxyz\n",
16
+ "日本語\n文字列\n",
17
+ "\xfd\xfe\xff",
18
+ ]
19
+ puts obj.ya2yaml(:syck_compatible => true)
20
+
21
+ *output*:
22
+
23
+ ---
24
+ - |
25
+ abc
26
+ xyz
27
+ - |
28
+ 日本語
29
+ 文字列
30
+ - !binary |
31
+ /f7/
32
+
33
+ == Method and Objects
34
+
35
+ When you require 'ya2yaml', public method 'Object#ya2yaml' is defined. Currently these Objects are supported.
36
+
37
+ as YAML generic types:
38
+ - Array
39
+ - Hash
40
+ - NilClass
41
+ - String
42
+ - TrueClass
43
+ - FalseClass
44
+ - Fixnum
45
+ - Float
46
+ - Date
47
+ - Time
48
+
49
+ as Ruby specific types:
50
+ - Symbol
51
+ - Range
52
+ - Regexp
53
+ - Struct
54
+ - everything else as a generic Object (serializes instance variables)
55
+
56
+ A String which contains any non-UTF8 character will be regarded as "binary" and encoded in BASE64.
57
+
58
+ == Options
59
+
60
+ # set them individually
61
+ obj.ya2yaml(
62
+ :indent_size => 4,
63
+ :minimum_block_length => 16,
64
+ :printable_with_syck => true,
65
+ :escape_b_specific => true,
66
+ :escape_as_utf8 => true
67
+ )
68
+
69
+ # or simply set this for a safe roundtrip with Syck.
70
+ obj.ya2yaml(:syck_compatible => true)
71
+
72
+ **CAUTION** Some of these options are to avoid compatibility issue with Syck. When you set these options to false, the emitted YAML document might not be loadable with YAML.load() although the syntax is valid.
73
+
74
+ - :indent_size
75
+ - default: 2
76
+ - Number of indentation spaces for a level.
77
+
78
+ - :minimum_block_length
79
+ - default: 0
80
+ - Minimum length of a string emitted in block scalar style. If a string is shorter than this value, it will be emitted in one line.
81
+
82
+ - :printable_with_syck
83
+ - default: false
84
+ - When set to true, Ya2YAML will regard some kind of strings (which cause Syck roundtrip failures) as "non-printable" and double-quote them.
85
+
86
+ - :escape_b_specific
87
+ - default: false
88
+ - When set to true, Ya2YAML will regard Unicode specific line breaks (LS and PS) as "non-printable" and escape them.
89
+
90
+ - :escape_as_utf8
91
+ - default: false
92
+ - When set to true, Ya2YAML uses Ruby-like escape sequences in UTF8 code instead of "\uXXXX" style in UCS code. It also suppresses use of "\L" and "\P" (escape sequences for LS and PS).
93
+
94
+ - :syck_compatible
95
+ - default: false
96
+ - When set to true, These options are set to true at once. You have to set this to false when you set them individually.
97
+ - :printable_with_syck
98
+ - :escape_b_specific
99
+ - :escape_as_utf8
100
+
101
+ == More information
102
+
103
+ Visit http://rubyforge.org/projects/ya2yaml
104
+
105
+ == License
106
+
107
+ Ya2YAML is distributed with a MIT license, which can be found in the file LICENSE.
data/lib/ya2yaml.rb ADDED
@@ -0,0 +1,356 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # $Id: ya2yaml.rb,v 0.23 2006-09-14 05:42:04+09 funai Exp funai $
4
+ #
5
+ # Author:: Akira FUNAI
6
+ # Copyright:: Copyright (c) 2006 Akira FUNAI
7
+ # License:: MIT License
8
+
9
+ class Ya2YAML
10
+
11
+ def initialize(options = {})
12
+ options[:indent_size] = 2 if options[:indent_size].to_i <= 0
13
+ options[:minimum_block_length] = 0 if options[:minimum_block_length].to_i <= 0
14
+ options.update(
15
+ {
16
+ :printable_with_syck => true,
17
+ :escape_b_specific => true,
18
+ :escape_as_utf8 => true,
19
+ }
20
+ ) if options[:syck_compatible]
21
+
22
+ @options = options
23
+ end
24
+
25
+ def _ya2yaml(obj)
26
+ throw 'set $KCODE to "UTF8".' if $KCODE != 'UTF8'
27
+ '--- ' + emit(obj,1) + "\n"
28
+ end
29
+
30
+ private
31
+
32
+ def emit(obj,level)
33
+ case obj.class.to_s
34
+ when 'Array'
35
+ if (obj.length == 0)
36
+ '[]'
37
+ else
38
+ indent = "\n" + s_indent(level - 1)
39
+ obj.collect {|o|
40
+ indent + '- ' + emit(o,level + 1)
41
+ }.join('')
42
+ end
43
+ when 'Hash'
44
+ if (obj.length == 0)
45
+ '{}'
46
+ else
47
+ indent = "\n" + s_indent(level - 1)
48
+ obj.keys.sort {|x,y| x.to_s <=> y.to_s }.collect {|k|
49
+ key = emit(k,level + 1)
50
+ if (
51
+ is_one_plain_line?(key) ||
52
+ key =~ /\A(#{REX_BOOL}|#{REX_FLOAT}|#{REX_INT}|#{REX_NULL})\z/x
53
+ )
54
+ indent + key + ': ' + emit(obj[k],level + 1)
55
+ else
56
+ indent + '? ' + key +
57
+ indent + ': ' + emit(obj[k],level + 1)
58
+ end
59
+ }.join('')
60
+ end
61
+ when 'NilClass'
62
+ '~'
63
+ when 'String'
64
+ emit_string(obj,level)
65
+ when 'TrueClass','FalseClass'
66
+ obj.to_s
67
+ when 'Fixnum','Float'
68
+ obj.to_s
69
+ when 'Date'
70
+ obj.to_s
71
+ when 'Time'
72
+ offset = obj.gmtoff
73
+ off_hm = sprintf(
74
+ '%+.2d:%.2d',
75
+ (offset / 3600.0).to_i,
76
+ (offset % 3600.0) / 60
77
+ )
78
+ u_sec = (obj.usec != 0) ? sprintf(".%.6d",obj.usec) : ''
79
+ obj.strftime("%Y-%m-%d %H:%M:%S#{u_sec} #{off_hm}")
80
+ when 'Symbol'
81
+ '!ruby/symbol ' + obj.to_s
82
+ when 'Range'
83
+ '!ruby/range ' + obj.to_s
84
+ when 'Regexp'
85
+ '!ruby/regexp ' + obj.inspect
86
+ else
87
+ case
88
+ when obj.is_a?(Struct)
89
+ struct_members = {}
90
+ obj.each_pair{|k,v| struct_members[k.to_s] = v }
91
+ '!ruby/struct:' + obj.class.to_s.sub(/^Struct::/,'') + ' ' +
92
+ emit(struct_members,level + 1)
93
+ else
94
+ # serialized as a generic object
95
+ object_members = {}
96
+ obj.instance_variables.each{|k,v|
97
+ object_members[k.sub(/^@/,'')] = obj.instance_variable_get(k)
98
+ }
99
+ '!ruby/object:' + obj.class.to_s + ' ' +
100
+ emit(object_members,level + 1)
101
+ end
102
+ end
103
+ end
104
+
105
+ def emit_string(str,level)
106
+ (is_string,is_printable,is_one_line,is_one_plain_line) = string_type(str)
107
+ if is_string
108
+ if is_printable
109
+ if is_one_plain_line
110
+ emit_simple_string(str,level)
111
+ else
112
+ (is_one_line || str.length < @options[:minimum_block_length]) ?
113
+ emit_quoted_string(str,level) :
114
+ emit_block_string(str,level)
115
+ end
116
+ else
117
+ emit_quoted_string(str,level)
118
+ end
119
+ else
120
+ emit_base64_binary(str,level)
121
+ end
122
+ end
123
+
124
+ def emit_simple_string(str,level)
125
+ str
126
+ end
127
+
128
+ def emit_block_string(str,level)
129
+ str = normalize_line_break(str)
130
+
131
+ indent = s_indent(level)
132
+ indentation_indicator = (str =~ /\A /) ? indent.size.to_s : ''
133
+ str =~ /(#{REX_NORMAL_LB}*)\z/
134
+ chomping_indicator = case $1.length
135
+ when 0
136
+ '-'
137
+ when 1
138
+ ''
139
+ else
140
+ '+'
141
+ end
142
+
143
+ str.chomp!
144
+ str.gsub!(/#{REX_NORMAL_LB}/) {
145
+ $1 + indent
146
+ }
147
+ '|' + indentation_indicator + chomping_indicator + "\n" + indent + str
148
+ end
149
+
150
+ def emit_quoted_string(str,level)
151
+ str = yaml_escape(normalize_line_break(str))
152
+ if (str.length < @options[:minimum_block_length])
153
+ str.gsub!(/#{REX_NORMAL_LB}/) { ESCAPE_SEQ_LB[$1] }
154
+ else
155
+ str.gsub!(/#{REX_NORMAL_LB}$/) { ESCAPE_SEQ_LB[$1] }
156
+ str.gsub!(/(#{REX_NORMAL_LB}+)(.)/) {
157
+ trail_c = $3
158
+ $1 + trail_c.sub(/([\t ])/) { ESCAPE_SEQ_WS[$1] }
159
+ }
160
+ indent = s_indent(level)
161
+ str.gsub!(/#{REX_NORMAL_LB}/) {
162
+ ESCAPE_SEQ_LB[$1] + "\\\n" + indent
163
+ }
164
+ end
165
+ '"' + str + '"'
166
+ end
167
+
168
+ def emit_base64_binary(str,level)
169
+ indent = "\n" + s_indent(level)
170
+ base64 = [str].pack('m')
171
+ '!binary |' + indent + base64.gsub(/\n(?!\z)/,indent)
172
+ end
173
+
174
+ def string_type(str)
175
+ (ucs_codes = str.unpack('U*')) rescue (
176
+ # ArgumentError -> binary data
177
+ return false,false,false,false
178
+ )
179
+ if (
180
+ @options[:printable_with_syck] &&
181
+ str =~ /\A#{REX_ANY_LB}* | #{REX_ANY_LB}*\z|#{REX_ANY_LB}{2}\z/
182
+ )
183
+ # detour Syck bug
184
+ return true,false,is_one_line?(str),false
185
+ end
186
+ ucs_codes.each {|ucs_code|
187
+ return true,false,is_one_line?(str),false unless is_printable?(ucs_code)
188
+ }
189
+ return true,true,is_one_line?(str),is_one_plain_line?(str)
190
+ end
191
+
192
+ def is_printable?(ucs_code)
193
+ # YAML 1.1 / 4.1.1.
194
+ (
195
+ [0x09,0x0a,0x0d,0x85].include?(ucs_code) ||
196
+ (ucs_code <= 0x7e && ucs_code >= 0x20) ||
197
+ (ucs_code <= 0xd7ff && ucs_code >= 0xa0) ||
198
+ (ucs_code <= 0xfffd && ucs_code >= 0xe000) ||
199
+ (ucs_code <= 0x10ffff && ucs_code >= 0x10000)
200
+ ) &&
201
+ !(
202
+ # treat LS/PS as non-printable characters
203
+ @options[:escape_b_specific] &&
204
+ (ucs_code == 0x2028 || ucs_code == 0x2029)
205
+ )
206
+ end
207
+
208
+ def is_one_line?(str)
209
+ str !~ /#{REX_ANY_LB}(?!\z)/
210
+ end
211
+
212
+ def is_one_plain_line?(str)
213
+ # YAML 1.1 / 4.6.11.
214
+ str !~ /^([\-\?:,\[\]\{\}\#&\*!\|>'"%@`\s]|---|\.\.\.)/ &&
215
+ str !~ /[:\#\s\[\]\{\},]/ &&
216
+ str !~ /#{REX_ANY_LB}/ &&
217
+ str !~ /^(#{REX_BOOL}|#{REX_FLOAT}|#{REX_INT}|#{REX_MERGE}
218
+ |#{REX_NULL}|#{REX_TIMESTAMP}|#{REX_VALUE})$/x
219
+ end
220
+
221
+ def s_indent(level)
222
+ # YAML 1.1 / 4.2.2.
223
+ ' ' * (level * @options[:indent_size])
224
+ end
225
+
226
+ def normalize_line_break(str)
227
+ # YAML 1.1 / 4.1.4.
228
+ str.gsub(/(#{REX_CRLF}|#{REX_CR}|#{REX_NEL})/,"\n")
229
+ end
230
+
231
+ def yaml_escape(str)
232
+ # YAML 1.1 / 4.1.6.
233
+ str.gsub(/[^a-zA-Z0-9]/u) {|c|
234
+ ucs_code, = (c.unpack('U') rescue [??])
235
+ case
236
+ when ESCAPE_SEQ[c]
237
+ ESCAPE_SEQ[c]
238
+ when is_printable?(ucs_code)
239
+ c
240
+ when @options[:escape_as_utf8]
241
+ '\\x' + c.unpack('H2' * c.size).join('\\x')
242
+ when ucs_code == 0x2028 || ucs_code == 0x2029
243
+ ESCAPE_SEQ_LB[c]
244
+ when ucs_code <= 0x7f
245
+ sprintf('\\x%.2x',ucs_code)
246
+ when ucs_code <= 0xffff
247
+ sprintf('\\u%.4x',ucs_code)
248
+ else
249
+ sprintf('\\U%.8x',ucs_code)
250
+ end
251
+ }
252
+ end
253
+
254
+ module Constants
255
+ UCS_0X85 = [0x85].pack('U') # c285@UTF8 Unicode next line
256
+ UCS_0XA0 = [0xa0].pack('U') # c2a0@UTF8 Unicode non-breaking space
257
+ UCS_0X2028 = [0x2028].pack('U') # e280a8@UTF8 Unicode line separator
258
+ UCS_0X2029 = [0x2029].pack('U') # e280a9@UTF8 Unicode paragraph separator
259
+
260
+ # non-break characters
261
+ ESCAPE_SEQ = {
262
+ "\x00" => '\\0',
263
+ "\x07" => '\\a',
264
+ "\x08" => '\\b',
265
+ "\x0b" => '\\v',
266
+ "\x0c" => '\\f',
267
+ "\x1b" => '\\e',
268
+ "\"" => '\\"',
269
+ "\\" => '\\\\',
270
+ }
271
+
272
+ # non-breaking space
273
+ ESCAPE_SEQ_NS = {
274
+ UCS_0XA0 => '\\_',
275
+ }
276
+
277
+ # white spaces
278
+ ESCAPE_SEQ_WS = {
279
+ "\x09" => '\\t',
280
+ " " => '\\x20',
281
+ }
282
+
283
+ # line breaks
284
+ ESCAPE_SEQ_LB ={
285
+ "\x0a" => '\\n',
286
+ "\x0d" => '\\r',
287
+ UCS_0X85 => '\\N',
288
+ UCS_0X2028 => '\\L',
289
+ UCS_0X2029 => '\\P',
290
+ }
291
+
292
+ # regexps for line breaks
293
+ REX_LF = Regexp.escape("\x0a")
294
+ REX_CR = Regexp.escape("\x0d")
295
+ REX_CRLF = Regexp.escape("\x0d\x0a")
296
+ REX_NEL = Regexp.escape(UCS_0X85)
297
+ REX_LS = Regexp.escape(UCS_0X2028)
298
+ REX_PS = Regexp.escape(UCS_0X2029)
299
+
300
+ REX_ANY_LB = /(#{REX_LF}|#{REX_CR}|#{REX_NEL}|#{REX_LS}|#{REX_PS})/
301
+ REX_NORMAL_LB = /(#{REX_LF}|#{REX_LS}|#{REX_PS})/
302
+
303
+ # regexps for language-Independent types for YAML1.1
304
+ REX_BOOL = /
305
+ y|Y|yes|Yes|YES|n|N|no|No|NO
306
+ |true|True|TRUE|false|False|FALSE
307
+ |on|On|ON|off|Off|OFF
308
+ /x
309
+ REX_FLOAT = /
310
+ [-+]?([0-9][0-9_]*)?\.[0-9.]*([eE][-+][0-9]+)? # (base 10)
311
+ |[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]* # (base 60)
312
+ |[-+]?\.(inf|Inf|INF) # (infinity)
313
+ |\.(nan|NaN|NAN) # (not a number)
314
+ /x
315
+ REX_INT = /
316
+ [-+]?0b[0-1_]+ # (base 2)
317
+ |[-+]?0[0-7_]+ # (base 8)
318
+ |[-+]?(0|[1-9][0-9_]*) # (base 10)
319
+ |[-+]?0x[0-9a-fA-F_]+ # (base 16)
320
+ |[-+]?[1-9][0-9_]*(:[0-5]?[0-9])+ # (base 60)
321
+ /x
322
+ REX_MERGE = /
323
+ <<
324
+ /x
325
+ REX_NULL = /
326
+ ~ # (canonical)
327
+ |null|Null|NULL # (English)
328
+ | # (Empty)
329
+ /x
330
+ REX_TIMESTAMP = /
331
+ [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] # (ymd)
332
+ |[0-9][0-9][0-9][0-9] # (year)
333
+ -[0-9][0-9]? # (month)
334
+ -[0-9][0-9]? # (day)
335
+ ([Tt]|[ \t]+)[0-9][0-9]? # (hour)
336
+ :[0-9][0-9] # (minute)
337
+ :[0-9][0-9] # (second)
338
+ (\.[0-9]*)? # (fraction)
339
+ (([ \t]*)Z|[-+][0-9][0-9]?(:[0-9][0-9])?)? # (time zone)
340
+ /x
341
+ REX_VALUE = /
342
+ =
343
+ /x
344
+ end
345
+
346
+ include Constants
347
+
348
+ end
349
+
350
+ class Object
351
+ def ya2yaml(options = {})
352
+ Ya2YAML.new(options)._ya2yaml(self)
353
+ end
354
+ end
355
+
356
+ __END__
data/test/t.gif ADDED
Binary file
data/test/t.yaml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ list:
3
+ - perl
4
+ - ruby
5
+ - python
data/test/test.rb ADDED
@@ -0,0 +1,341 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # $Id: test.rb,v 1.2 2006-10-03 01:04:35+09 funai Exp funai $
4
+
5
+ $: << (File.dirname(__FILE__) + '/../lib')
6
+
7
+ Dir.chdir(File.dirname(__FILE__))
8
+
9
+ $KCODE = 'UTF8'
10
+ require 'ya2yaml'
11
+
12
+ require 'yaml'
13
+ require 'test/unit'
14
+
15
+ class TC_Ya2YAML < Test::Unit::TestCase
16
+
17
+ @@struct_klass = Struct::new('Foo',:bar,:buz)
18
+ class Moo
19
+ attr_accessor :val1,:val2
20
+ def initialize(val1,val2)
21
+ @val1 = val1
22
+ @val2 = val2
23
+ end
24
+ def ==(k)
25
+ (k.class == self.class) &&
26
+ (k.val1 == self.val1) &&
27
+ (k.val2 == self.val2)
28
+ end
29
+ end
30
+ puts "test may take minutes. please wait.\n"
31
+
32
+ def setup
33
+ @text = ''
34
+ @gif = ''
35
+ File.open('./t.yaml','r') {|f| @text = f.read}
36
+ File.open('./t.gif','r') {|f| @gif = f.read}
37
+
38
+ @struct = @@struct_klass.new('barbarbar',@@struct_klass.new('baaaar',12345))
39
+ @klass = Moo.new('boobooboo',Time.new())
40
+ end
41
+
42
+ def test_options
43
+ [
44
+ [
45
+ {},
46
+ "--- \n- \"\\u0086\"\n- |-\n a\xe2\x80\xa8 b\xe2\x80\xa9 c\n- |4-\n abc\n xyz\n",
47
+ ],
48
+ [
49
+ {:indent_size => 4},
50
+ "--- \n- \"\\u0086\"\n- |-\n a\xe2\x80\xa8 b\xe2\x80\xa9 c\n- |8-\n abc\n xyz\n",
51
+ ],
52
+ [
53
+ {:minimum_block_length => 16},
54
+ "--- \n- \"\\u0086\"\n- \"a\\Lb\\Pc\"\n- \" abc\\nxyz\"\n",
55
+ ],
56
+ # [
57
+ # {:emit_c_document_end => true},
58
+ # "--- \n- \"\\u0086\"\n- |-\n a\xe2\x80\xa8 b\xe2\x80\xa9 c\n- |4-\n abc\n xyz\n...\n",
59
+ # ],
60
+ [
61
+ {:printable_with_syck => true},
62
+ "--- \n- \"\\u0086\"\n- |-\n a\xe2\x80\xa8 b\xe2\x80\xa9 c\n- \" abc\\n\\\n xyz\"\n",
63
+ ],
64
+ [
65
+ {:escape_b_specific => true},
66
+ "--- \n- \"\\u0086\"\n- \"a\\Lb\\Pc\"\n- |4-\n abc\n xyz\n",
67
+ ],
68
+ [
69
+ {:escape_as_utf8 => true},
70
+ "--- \n- \"\\xc2\\x86\"\n- |-\n a\xe2\x80\xa8 b\xe2\x80\xa9 c\n- |4-\n abc\n xyz\n",
71
+ ],
72
+ [
73
+ {:syck_compatible => true},
74
+ "--- \n- \"\\xc2\\x86\"\n- \"a\\xe2\\x80\\xa8b\\xe2\\x80\\xa9c\"\n- \" abc\\n\\\n xyz\"\n",
75
+ ],
76
+ ].each {|opt,yaml|
77
+ y = ["\xc2\x86","a\xe2\x80\xa8b\xe2\x80\xa9c"," abc\nxyz"].ya2yaml(opt)
78
+ # puts y
79
+
80
+ assert_equal(y,yaml)
81
+ }
82
+ end
83
+
84
+ def test_normalize_line_breaks
85
+ [
86
+ ["\n\n\n\n", "--- \"\\n\\n\\n\\n\"\n",],
87
+ ["\r\n\r\n\r\n", "--- \"\\n\\n\\n\"\n",],
88
+ ["\r\n\n\n", "--- \"\\n\\n\\n\"\n",],
89
+ ["\n\r\n\n", "--- \"\\n\\n\\n\"\n",],
90
+ ["\n\n\r\n", "--- \"\\n\\n\\n\"\n",],
91
+ ["\n\n\n\r", "--- \"\\n\\n\\n\\n\"\n",],
92
+ ["\r\r\n\r", "--- \"\\n\\n\\n\"\n",],
93
+ ["\r\r\r\r", "--- \"\\n\\n\\n\\n\"\n",],
94
+ ["\r\xc2\x85\r\n", "--- \"\\n\\n\\n\"\n",],
95
+ ["\r\xe2\x80\xa8\r\n","--- \"\\n\\L\\n\"\n",],
96
+ ["\r\xe2\x80\xa9\r\n","--- \"\\n\\P\\n\"\n",],
97
+ ].each {|src,yaml|
98
+ y = src.ya2yaml(
99
+ :minimum_block_length => 16
100
+ )
101
+ # p y
102
+ assert_equal(y,yaml)
103
+ }
104
+ end
105
+
106
+ def test_roundtrip_single_byte_char
107
+ ("\x00".."\x7f").each {|c|
108
+ y = c.ya2yaml()
109
+ # puts y
110
+ r = YAML.load(y)
111
+ assert_equal((c == "\r" ? "\n" : c),r) # "\r" is normalized as "\n".
112
+ }
113
+ end
114
+
115
+ def test_roundtrip_multi_byte_char
116
+ [
117
+ 0x80,
118
+ 0x85,
119
+ 0xa0,
120
+ 0x07ff,
121
+ 0x0800,
122
+ 0x0fff,
123
+ 0x1000,
124
+ 0x2028,
125
+ 0x2029,
126
+ 0xcfff,
127
+ 0xd000,
128
+ 0xd7ff,
129
+ 0xe000,
130
+ 0xfffd,
131
+ 0x10000,
132
+ 0x3ffff,
133
+ 0x40000,
134
+ 0xfffff,
135
+ 0x100000,
136
+ 0x10ffff,
137
+ ].each {|ucs_code|
138
+ [-1,0,1].each {|ofs|
139
+ (c = [ucs_code + ofs].pack('U')) rescue next
140
+ c_hex = c.unpack('H8')
141
+ y = c.ya2yaml(
142
+ :escape_b_specific => true,
143
+ :escape_as_utf8 => true
144
+ )
145
+ # puts y
146
+ r = YAML.load(y)
147
+ assert_equal(
148
+ [c_hex,(c =~ /\xc2\x85/u ? "\n" : c)],
149
+ [c_hex,r]
150
+ ) # "\N" is normalized as "\n".
151
+ }
152
+ }
153
+ end
154
+
155
+ def test_roundtrip_ambiguous_string
156
+ [
157
+ 'true',
158
+ 'false',
159
+ 'TRUE',
160
+ 'FALSE',
161
+ 'Y',
162
+ 'N',
163
+ 'y',
164
+ 'n',
165
+ 'on',
166
+ 'off',
167
+ true,
168
+ false,
169
+ '0b0101',
170
+ '-0b0101',
171
+ 0b0101,
172
+ -0b0101,
173
+ '031',
174
+ '-031',
175
+ 031,
176
+ -031,
177
+ '123.001e-1',
178
+ '123.01',
179
+ '123',
180
+ 123.001e-1,
181
+ 123.01,
182
+ 123,
183
+ '-123.001e-1',
184
+ '-123.01',
185
+ '-123',
186
+ -123.001e-1,
187
+ -123.01,
188
+ -123,
189
+ 'INF',
190
+ 'inf',
191
+ 'NaN',
192
+ 'nan',
193
+ '0xfe2a',
194
+ '-0xfe2a',
195
+ 0xfe2a,
196
+ -0xfe2a,
197
+ '1:23:32.0200',
198
+ '1:23:32',
199
+ '-1:23:32.0200',
200
+ '-1:23:32',
201
+ '<<',
202
+ '~',
203
+ 'null',
204
+ 'nUll',
205
+ 'Null',
206
+ 'NULL',
207
+ '',
208
+ nil,
209
+ '2006-09-12',
210
+ '2006-09-11T17:28:07Z',
211
+ '2006-09-11T17:28:07+09:00',
212
+ '2006-09-11 17:28:07.662694 +09:00',
213
+ '=',
214
+ ].each {|c|
215
+ ['','hoge'].each {|ext|
216
+ src = c.class == String ? (c + ext) : c
217
+ y = src.ya2yaml(
218
+ :escape_as_utf8 => true
219
+ )
220
+ # puts y
221
+ r = YAML.load(y)
222
+ assert_equal(src,r)
223
+ }
224
+ }
225
+ end
226
+
227
+ def test_roundtrip_string
228
+ chars = "aあ\t\-\?,\[\{\#&\*!\|>'\"\%\@\`.\\ \n\xc2\xa0\xe2\x80\xa8".split('')
229
+
230
+ chars.each {|i|
231
+ chars.each {|j|
232
+ chars.each {|k|
233
+ chars.each {|l|
234
+ src = i + j + k + l
235
+ y = src.ya2yaml(
236
+ :printable_with_syck => true,
237
+ :escape_b_specific => true,
238
+ :escape_as_utf8 => true
239
+ )
240
+ # puts y
241
+ r = YAML.load(y)
242
+ assert_equal(src,r)
243
+ }
244
+ }
245
+ }
246
+ }
247
+ end
248
+
249
+ def test_roundtrip_types
250
+ objects = [
251
+ [],
252
+ [1],
253
+ {},
254
+ {'foo' => 'bar'},
255
+ nil,
256
+ 'hoge',
257
+ "abc\nxyz\n",
258
+ "\xff\xff",
259
+ true,
260
+ false,
261
+ 1000,
262
+ 1000.1,
263
+ -1000,
264
+ -1000.1,
265
+ Date.today(),
266
+ Time.new(),
267
+ :foo,
268
+ 1..10,
269
+ /abc\nxyz/i,
270
+ @struct,
271
+ @klass,
272
+ ]
273
+
274
+ objects.each {|obj|
275
+ src = case obj.class.to_s
276
+ when 'Array'
277
+ (obj.length) == 0 ? [] : objects
278
+ when 'Hash'
279
+ if (obj.length) == 0
280
+ {}
281
+ else
282
+ h = {}
283
+ c = 0
284
+ objects.each {|val|
285
+ h[c] = {}
286
+ objects.each {|key|
287
+ h[c][key] = val unless (key.class == Hash || key.class == Moo)
288
+ }
289
+ c += 1
290
+ }
291
+ h
292
+ end
293
+ else
294
+ obj
295
+ end
296
+ y = src.ya2yaml(
297
+ :syck_compatible => true
298
+ )
299
+ # puts y
300
+
301
+ r = YAML.load(y)
302
+ assert_equal(src,r)
303
+ }
304
+ end
305
+
306
+ def test_roundtrip_various
307
+ [
308
+ [1,2,['c','d',[[['e']],[]],'f'],3,Time.new(),[[:foo]],nil,true,false,[],{},{[123,223]=>456},{[1]=>2,'a'=>'b','c' => [9,9,9],Time.new() => 'hoge'},],
309
+ [],
310
+ {[123,223]=>456},
311
+ {},
312
+ {'foo' => {1 => {2=>3,4=>5},6 => [7,8]}},
313
+ "abc",
314
+ " abc\n def\ndef\ndef\ndef\ndef\n",
315
+ "abc\n def\ndef\n",
316
+ "abc\n def\ndef\n\n",
317
+ "abc\n def\ndef\n\n ",
318
+ "abc\n def\ndef\n \n",
319
+ "abc\n def\ndef \n \n",
320
+ "abc\n def\ndef \n \n ",
321
+ ' ほげほげほげ',
322
+ {"ほげ\nほげ\n ほげ" => 123},
323
+ [["ほげ\nほげ\n ほげ"]],
324
+ "ほげh\x4fge\nほげ\nほげ",
325
+ [{'ほげ'=>'abc',"ほげ\nほげ"=>'ほげ'},'ほげ',@text],
326
+ [Date.today,-9.011,0.023,4,-5,{1=>-2,-1=>@text,'_foo'=>'bar','ぬお-ぬお'=>321}],
327
+ {1=>-2,-1=>@gif,'_foo'=>'bar','ぬお-ぬお'=>321},
328
+ ].each {|src|
329
+ y = src.ya2yaml(
330
+ :syck_compatible => true
331
+ )
332
+ # puts y
333
+
334
+ r = YAML.load(y)
335
+ assert_equal(src,r)
336
+ }
337
+ end
338
+
339
+ end
340
+
341
+ __END__
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.0
3
+ specification_version: 1
4
+ name: ya2yaml
5
+ version: !ruby/object:Gem::Version
6
+ version: "0.23"
7
+ date: 2006-10-03 00:00:00 +09:00
8
+ summary: An UTF8 safe YAML dumper.
9
+ require_paths:
10
+ - lib
11
+ email: funai.akira@gmail.com
12
+ homepage: http://rubyforge.org/projects/ya2yaml/
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: ya2yaml
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Akira FUNAI
31
+ files:
32
+ - lib/ya2yaml.rb
33
+ - README
34
+ - LICENSE
35
+ - test/t.gif
36
+ - test/t.yaml
37
+ - test/test.rb
38
+ test_files:
39
+ - test/test.rb
40
+ rdoc_options:
41
+ - --main
42
+ - README
43
+ - --charset
44
+ - UTF8
45
+ extra_rdoc_files:
46
+ - README
47
+ executables: []
48
+
49
+ extensions: []
50
+
51
+ requirements: []
52
+
53
+ dependencies: []
54
+