ya2yaml-jomz 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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,113 @@
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
+ - Bignum
46
+ - Float
47
+ - Date
48
+ - Time
49
+
50
+ as Ruby specific types:
51
+ - Symbol
52
+ - Range
53
+ - Regexp
54
+ - Struct
55
+ - everything else as a generic Object (serializes instance variables)
56
+
57
+ A String which contains any non-UTF8 character will be regarded as "binary" and encoded in BASE64.
58
+
59
+ == Options
60
+
61
+ # set them individually
62
+ obj.ya2yaml(
63
+ :indent_size => 4,
64
+ :hash_order => ['name','age','address'],
65
+ :minimum_block_length => 16,
66
+ :printable_with_syck => true,
67
+ :escape_b_specific => true,
68
+ :escape_as_utf8 => true
69
+ )
70
+
71
+ # or simply set this for a safe roundtrip with Syck.
72
+ obj.ya2yaml(:syck_compatible => true)
73
+
74
+ **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.
75
+
76
+ - :indent_size
77
+ - default: 2
78
+ - Number of indentation spaces for a level.
79
+
80
+ - :hash_order
81
+ - default: nil
82
+ - Array of hash keys indicating sort order (this option only works on a top-level hash).
83
+
84
+ - :minimum_block_length
85
+ - default: 0
86
+ - 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.
87
+
88
+ - :printable_with_syck
89
+ - default: false
90
+ - When set to true, Ya2YAML will regard some kind of strings (which cause Syck roundtrip failures) as "non-printable" and double-quote them.
91
+
92
+ - :escape_b_specific
93
+ - default: false
94
+ - When set to true, Ya2YAML will regard Unicode specific line breaks (LS and PS) as "non-printable" and escape them.
95
+
96
+ - :escape_as_utf8
97
+ - default: false
98
+ - 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).
99
+
100
+ - :syck_compatible
101
+ - default: false
102
+ - When set to true, These options are set to true at once. You have to set this to false when you set them individually.
103
+ - :printable_with_syck
104
+ - :escape_b_specific
105
+ - :escape_as_utf8
106
+
107
+ == More information
108
+
109
+ Visit http://rubyforge.org/projects/ya2yaml
110
+
111
+ == License
112
+
113
+ Ya2YAML is distributed with a MIT license, which can be found in the file LICENSE.
@@ -0,0 +1,364 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # $Id: ya2yaml.rb,v 0.26 2007-01-19 20:42:42+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
+
43
+ o = obj.collect do |o|
44
+ emit(o, level + 1)
45
+ end.join(', ')
46
+ "[#{o}]"
47
+ end
48
+ when 'Hash'
49
+ if (obj.length == 0)
50
+ '{}'
51
+ else
52
+ indent = "\n" + s_indent(level - 1)
53
+ hash_order = @options[:hash_order]
54
+ if (hash_order && level == 1)
55
+ hash_keys = obj.keys.sort {|x,y|
56
+ x_order = hash_order.index(x) ? hash_order.index(x) : Float::MAX
57
+ y_order = hash_order.index(y) ? hash_order.index(y) : Float::MAX
58
+ o = (x_order <=> y_order)
59
+ (o != 0) ? o : (x.to_s <=> y.to_s)
60
+ }
61
+ else
62
+ hash_keys = obj.keys.sort {|x,y| x.to_s <=> y.to_s }
63
+ end
64
+ hash_keys.collect {|k|
65
+ key = emit(k,level + 1)
66
+ indent + key + ': ' + emit(obj[k],level + 1)
67
+ }.join('')
68
+ end
69
+ when 'NilClass'
70
+ '~'
71
+ when 'String'
72
+ emit_string(obj,level)
73
+ when 'TrueClass','FalseClass'
74
+ obj.to_s
75
+ when 'Fixnum','Bignum','Float'
76
+ obj.to_s
77
+ when 'Date'
78
+ obj.to_s
79
+ when 'Time'
80
+ offset = obj.gmtoff
81
+ off_hm = sprintf(
82
+ '%+.2d:%.2d',
83
+ (offset / 3600.0).to_i,
84
+ (offset % 3600.0) / 60
85
+ )
86
+ u_sec = (obj.usec != 0) ? sprintf(".%.6d",obj.usec) : ''
87
+ obj.strftime("%Y-%m-%d %H:%M:%S#{u_sec} #{off_hm}")
88
+ when 'Symbol'
89
+ ":#{obj.to_s}"
90
+ when 'Range'
91
+ '!ruby/range ' + obj.to_s
92
+ when 'Regexp'
93
+ '!ruby/regexp ' + obj.inspect
94
+ else
95
+ case
96
+ when obj.is_a?(Struct)
97
+ struct_members = {}
98
+ obj.each_pair{|k,v| struct_members[k.to_s] = v }
99
+ '!ruby/struct:' + obj.class.to_s.sub(/^(Struct::(.+)|.*)$/,'\2') + ' ' +
100
+ emit(struct_members,level + 1)
101
+ else
102
+ # serialized as a generic object
103
+ object_members = {}
104
+ obj.instance_variables.each{|k,v|
105
+ object_members[k.sub(/^@/,'')] = obj.instance_variable_get(k)
106
+ }
107
+ '!ruby/object:' + obj.class.to_s + ' ' +
108
+ emit(object_members,level + 1)
109
+ end
110
+ end
111
+ end
112
+
113
+ def emit_string(str,level)
114
+ (is_string,is_printable,is_one_line,is_one_plain_line) = string_type(str)
115
+ if is_string
116
+ if is_printable
117
+ if is_one_plain_line
118
+ emit_simple_string(str,level)
119
+ else
120
+ (is_one_line || str.length < @options[:minimum_block_length]) ?
121
+ emit_quoted_string(str,level) :
122
+ emit_block_string(str,level)
123
+ end
124
+ else
125
+ emit_quoted_string(str,level)
126
+ end
127
+ else
128
+ emit_base64_binary(str,level)
129
+ end
130
+ end
131
+
132
+ def emit_simple_string(str,level)
133
+ str
134
+ end
135
+
136
+ def emit_block_string(str,level)
137
+ str = normalize_line_break(str)
138
+
139
+ indent = s_indent(level)
140
+ indentation_indicator = (str =~ /\A /) ? indent.size.to_s : ''
141
+ str =~ /(#{REX_NORMAL_LB}*)\z/
142
+ chomping_indicator = case $1.length
143
+ when 0
144
+ '-'
145
+ when 1
146
+ ''
147
+ else
148
+ '+'
149
+ end
150
+
151
+ str.chomp!
152
+ str.gsub!(/#{REX_NORMAL_LB}/) {
153
+ $1 + indent
154
+ }
155
+ '|' + indentation_indicator + chomping_indicator + "\n" + indent + str
156
+ end
157
+
158
+ def emit_quoted_string(str,level)
159
+ str = yaml_escape(normalize_line_break(str))
160
+ if (str.length < @options[:minimum_block_length])
161
+ str.gsub!(/#{REX_NORMAL_LB}/) { ESCAPE_SEQ_LB[$1] }
162
+ else
163
+ str.gsub!(/#{REX_NORMAL_LB}$/) { ESCAPE_SEQ_LB[$1] }
164
+ str.gsub!(/(#{REX_NORMAL_LB}+)(.)/) {
165
+ trail_c = $3
166
+ $1 + trail_c.sub(/([\t ])/) { ESCAPE_SEQ_WS[$1] }
167
+ }
168
+ indent = s_indent(level)
169
+ str.gsub!(/#{REX_NORMAL_LB}/) {
170
+ ESCAPE_SEQ_LB[$1] + "\\\n" + indent
171
+ }
172
+ end
173
+ '"' + str + '"'
174
+ end
175
+
176
+ def emit_base64_binary(str,level)
177
+ indent = "\n" + s_indent(level)
178
+ base64 = [str].pack('m')
179
+ '!binary |' + indent + base64.gsub(/\n(?!\z)/,indent)
180
+ end
181
+
182
+ def string_type(str)
183
+ (ucs_codes = str.unpack('U*')) rescue (
184
+ # ArgumentError -> binary data
185
+ return false,false,false,false
186
+ )
187
+ if (
188
+ @options[:printable_with_syck] &&
189
+ str =~ /\A#{REX_ANY_LB}* | #{REX_ANY_LB}*\z|#{REX_ANY_LB}{2}\z/
190
+ )
191
+ # detour Syck bug
192
+ return true,false,is_one_line?(str),false
193
+ end
194
+ ucs_codes.each {|ucs_code|
195
+ return true,false,is_one_line?(str),false unless is_printable?(ucs_code)
196
+ }
197
+ return true,true,is_one_line?(str),is_one_plain_line?(str)
198
+ end
199
+
200
+ def is_printable?(ucs_code)
201
+ # YAML 1.1 / 4.1.1.
202
+ (
203
+ [0x09,0x0a,0x0d,0x85].include?(ucs_code) ||
204
+ (ucs_code <= 0x7e && ucs_code >= 0x20) ||
205
+ (ucs_code <= 0xd7ff && ucs_code >= 0xa0) ||
206
+ (ucs_code <= 0xfffd && ucs_code >= 0xe000) ||
207
+ (ucs_code <= 0x10ffff && ucs_code >= 0x10000)
208
+ ) &&
209
+ !(
210
+ # treat LS/PS as non-printable characters
211
+ @options[:escape_b_specific] &&
212
+ (ucs_code == 0x2028 || ucs_code == 0x2029)
213
+ )
214
+ end
215
+
216
+ def is_one_line?(str)
217
+ str !~ /#{REX_ANY_LB}(?!\z)/
218
+ end
219
+
220
+ def is_one_plain_line?(str)
221
+ # YAML 1.1 / 4.6.11.
222
+ str !~ /^([\-\?:,\[\]\{\}\#&\*!\|>'"%@`\s]|---|\.\.\.)/ &&
223
+ str !~ /[:\#\s\[\]\{\},]/ &&
224
+ str !~ /#{REX_ANY_LB}/ &&
225
+ str !~ /^(#{REX_BOOL}|#{REX_FLOAT}|#{REX_INT}|#{REX_MERGE}
226
+ |#{REX_NULL}|#{REX_TIMESTAMP}|#{REX_VALUE})$/x
227
+ end
228
+
229
+ def s_indent(level)
230
+ # YAML 1.1 / 4.2.2.
231
+ ' ' * (level * @options[:indent_size])
232
+ end
233
+
234
+ def normalize_line_break(str)
235
+ # YAML 1.1 / 4.1.4.
236
+ str.gsub(/(#{REX_CRLF}|#{REX_CR}|#{REX_NEL})/,"\n")
237
+ end
238
+
239
+ def yaml_escape(str)
240
+ # YAML 1.1 / 4.1.6.
241
+ str.gsub(/[^a-zA-Z0-9]/u) {|c|
242
+ ucs_code, = (c.unpack('U') rescue [??])
243
+ case
244
+ when ESCAPE_SEQ[c]
245
+ ESCAPE_SEQ[c]
246
+ when is_printable?(ucs_code)
247
+ c
248
+ when @options[:escape_as_utf8]
249
+ '\\x' + c.unpack('H2' * c.size).join('\\x')
250
+ when ucs_code == 0x2028 || ucs_code == 0x2029
251
+ ESCAPE_SEQ_LB[c]
252
+ when ucs_code <= 0x7f
253
+ sprintf('\\x%.2x',ucs_code)
254
+ when ucs_code <= 0xffff
255
+ sprintf('\\u%.4x',ucs_code)
256
+ else
257
+ sprintf('\\U%.8x',ucs_code)
258
+ end
259
+ }
260
+ end
261
+
262
+ module Constants
263
+ UCS_0X85 = [0x85].pack('U') # c285@UTF8 Unicode next line
264
+ UCS_0XA0 = [0xa0].pack('U') # c2a0@UTF8 Unicode non-breaking space
265
+ UCS_0X2028 = [0x2028].pack('U') # e280a8@UTF8 Unicode line separator
266
+ UCS_0X2029 = [0x2029].pack('U') # e280a9@UTF8 Unicode paragraph separator
267
+
268
+ # non-break characters
269
+ ESCAPE_SEQ = {
270
+ "\x00" => '\\0',
271
+ "\x07" => '\\a',
272
+ "\x08" => '\\b',
273
+ "\x0b" => '\\v',
274
+ "\x0c" => '\\f',
275
+ "\x1b" => '\\e',
276
+ "\"" => '\\"',
277
+ "\\" => '\\\\',
278
+ }
279
+
280
+ # non-breaking space
281
+ ESCAPE_SEQ_NS = {
282
+ UCS_0XA0 => '\\_',
283
+ }
284
+
285
+ # white spaces
286
+ ESCAPE_SEQ_WS = {
287
+ "\x09" => '\\t',
288
+ " " => '\\x20',
289
+ }
290
+
291
+ # line breaks
292
+ ESCAPE_SEQ_LB ={
293
+ "\x0a" => '\\n',
294
+ "\x0d" => '\\r',
295
+ UCS_0X85 => '\\N',
296
+ UCS_0X2028 => '\\L',
297
+ UCS_0X2029 => '\\P',
298
+ }
299
+
300
+ # regexps for line breaks
301
+ REX_LF = Regexp.escape("\x0a")
302
+ REX_CR = Regexp.escape("\x0d")
303
+ REX_CRLF = Regexp.escape("\x0d\x0a")
304
+ REX_NEL = Regexp.escape(UCS_0X85)
305
+ REX_LS = Regexp.escape(UCS_0X2028)
306
+ REX_PS = Regexp.escape(UCS_0X2029)
307
+
308
+ REX_ANY_LB = /(#{REX_LF}|#{REX_CR}|#{REX_NEL}|#{REX_LS}|#{REX_PS})/
309
+ REX_NORMAL_LB = /(#{REX_LF}|#{REX_LS}|#{REX_PS})/
310
+
311
+ # regexps for language-Independent types for YAML1.1
312
+ REX_BOOL = /
313
+ y|Y|yes|Yes|YES|n|N|no|No|NO
314
+ |true|True|TRUE|false|False|FALSE
315
+ |on|On|ON|off|Off|OFF
316
+ /x
317
+ REX_FLOAT = /
318
+ [-+]?([0-9][0-9_]*)?\.[0-9.]*([eE][-+][0-9]+)? # (base 10)
319
+ |[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]* # (base 60)
320
+ |[-+]?\.(inf|Inf|INF) # (infinity)
321
+ |\.(nan|NaN|NAN) # (not a number)
322
+ /x
323
+ REX_INT = /
324
+ [-+]?0b[0-1_]+ # (base 2)
325
+ |[-+]?0[0-7_]+ # (base 8)
326
+ |[-+]?(0|[1-9][0-9_]*) # (base 10)
327
+ |[-+]?0x[0-9a-fA-F_]+ # (base 16)
328
+ |[-+]?[1-9][0-9_]*(:[0-5]?[0-9])+ # (base 60)
329
+ /x
330
+ REX_MERGE = /
331
+ <<
332
+ /x
333
+ REX_NULL = /
334
+ ~ # (canonical)
335
+ |null|Null|NULL # (English)
336
+ | # (Empty)
337
+ /x
338
+ REX_TIMESTAMP = /
339
+ [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] # (ymd)
340
+ |[0-9][0-9][0-9][0-9] # (year)
341
+ -[0-9][0-9]? # (month)
342
+ -[0-9][0-9]? # (day)
343
+ ([Tt]|[ \t]+)[0-9][0-9]? # (hour)
344
+ :[0-9][0-9] # (minute)
345
+ :[0-9][0-9] # (second)
346
+ (\.[0-9]*)? # (fraction)
347
+ (([ \t]*)Z|[-+][0-9][0-9]?(:[0-9][0-9])?)? # (time zone)
348
+ /x
349
+ REX_VALUE = /
350
+ =
351
+ /x
352
+ end
353
+
354
+ include Constants
355
+
356
+ end
357
+
358
+ class Object
359
+ def ya2yaml(options = {})
360
+ Ya2YAML.new(options)._ya2yaml(self)
361
+ end
362
+ end
363
+
364
+ __END__
Binary file
@@ -0,0 +1,5 @@
1
+ ---
2
+ list:
3
+ - perl
4
+ - ruby
5
+ - python
@@ -0,0 +1,382 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # $Id: test.rb,v 1.4 2007-01-19 20:41:37+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_hash_order
85
+ [
86
+ [
87
+ nil,
88
+ "--- \na: 1\nb: 2\nc: 3\n",
89
+ ],
90
+ [
91
+ [],
92
+ "--- \na: 1\nb: 2\nc: 3\n",
93
+ ],
94
+ [
95
+ ['c','b','a'],
96
+ "--- \nc: 3\nb: 2\na: 1\n",
97
+ ],
98
+ [
99
+ ['b'],
100
+ "--- \nb: 2\na: 1\nc: 3\n",
101
+ ],
102
+ ].each {|hash_order,yaml|
103
+ y = {
104
+ 'a' => 1,
105
+ 'c' => 3,
106
+ 'b' => 2,
107
+ }.ya2yaml(
108
+ :hash_order => hash_order
109
+ )
110
+ # p y
111
+ assert_equal(y,yaml)
112
+ }
113
+ end
114
+
115
+ def test_normalize_line_breaks
116
+ [
117
+ ["\n\n\n\n", "--- \"\\n\\n\\n\\n\"\n",],
118
+ ["\r\n\r\n\r\n", "--- \"\\n\\n\\n\"\n",],
119
+ ["\r\n\n\n", "--- \"\\n\\n\\n\"\n",],
120
+ ["\n\r\n\n", "--- \"\\n\\n\\n\"\n",],
121
+ ["\n\n\r\n", "--- \"\\n\\n\\n\"\n",],
122
+ ["\n\n\n\r", "--- \"\\n\\n\\n\\n\"\n",],
123
+ ["\r\r\n\r", "--- \"\\n\\n\\n\"\n",],
124
+ ["\r\r\r\r", "--- \"\\n\\n\\n\\n\"\n",],
125
+ ["\r\xc2\x85\r\n", "--- \"\\n\\n\\n\"\n",],
126
+ ["\r\xe2\x80\xa8\r\n","--- \"\\n\\L\\n\"\n",],
127
+ ["\r\xe2\x80\xa9\r\n","--- \"\\n\\P\\n\"\n",],
128
+ ].each {|src,yaml|
129
+ y = src.ya2yaml(
130
+ :minimum_block_length => 16
131
+ )
132
+ # p y
133
+ assert_equal(y,yaml)
134
+ }
135
+ end
136
+
137
+ def test_structs
138
+ [
139
+ [Struct.new('Hoge',:foo).new(123),"--- !ruby/struct:Hoge \n foo: 123\n",],
140
+ [Struct.new(:foo).new(123), "--- !ruby/struct: \n foo: 123\n",],
141
+ ].each {|src,yaml|
142
+ y = src.ya2yaml()
143
+ assert_equal(y,yaml)
144
+ }
145
+ end
146
+
147
+ def test_roundtrip_single_byte_char
148
+ ("\x00".."\x7f").each {|c|
149
+ y = c.ya2yaml()
150
+ # puts y
151
+ r = YAML.load(y)
152
+ assert_equal((c == "\r" ? "\n" : c),r) # "\r" is normalized as "\n".
153
+ }
154
+ end
155
+
156
+ def test_roundtrip_multi_byte_char
157
+ [
158
+ 0x80,
159
+ 0x85,
160
+ 0xa0,
161
+ 0x07ff,
162
+ 0x0800,
163
+ 0x0fff,
164
+ 0x1000,
165
+ 0x2028,
166
+ 0x2029,
167
+ 0xcfff,
168
+ 0xd000,
169
+ 0xd7ff,
170
+ 0xe000,
171
+ 0xfffd,
172
+ 0x10000,
173
+ 0x3ffff,
174
+ 0x40000,
175
+ 0xfffff,
176
+ 0x100000,
177
+ 0x10ffff,
178
+ ].each {|ucs_code|
179
+ [-1,0,1].each {|ofs|
180
+ (c = [ucs_code + ofs].pack('U')) rescue next
181
+ c_hex = c.unpack('H8')
182
+ y = c.ya2yaml(
183
+ :escape_b_specific => true,
184
+ :escape_as_utf8 => true
185
+ )
186
+ # puts y
187
+ r = YAML.load(y)
188
+ assert_equal(
189
+ [c_hex,(c =~ /\xc2\x85/u ? "\n" : c)],
190
+ [c_hex,r]
191
+ ) # "\N" is normalized as "\n".
192
+ }
193
+ }
194
+ end
195
+
196
+ def test_roundtrip_ambiguous_string
197
+ [
198
+ 'true',
199
+ 'false',
200
+ 'TRUE',
201
+ 'FALSE',
202
+ 'Y',
203
+ 'N',
204
+ 'y',
205
+ 'n',
206
+ 'on',
207
+ 'off',
208
+ true,
209
+ false,
210
+ '0b0101',
211
+ '-0b0101',
212
+ 0b0101,
213
+ -0b0101,
214
+ '031',
215
+ '-031',
216
+ 031,
217
+ -031,
218
+ '123.001e-1',
219
+ '123.01',
220
+ '123',
221
+ 123.001e-1,
222
+ 123.01,
223
+ 123,
224
+ '-123.001e-1',
225
+ '-123.01',
226
+ '-123',
227
+ -123.001e-1,
228
+ -123.01,
229
+ -123,
230
+ 'INF',
231
+ 'inf',
232
+ 'NaN',
233
+ 'nan',
234
+ '0xfe2a',
235
+ '-0xfe2a',
236
+ 0xfe2a,
237
+ -0xfe2a,
238
+ '1:23:32.0200',
239
+ '1:23:32',
240
+ '-1:23:32.0200',
241
+ '-1:23:32',
242
+ '<<',
243
+ '~',
244
+ 'null',
245
+ 'nUll',
246
+ 'Null',
247
+ 'NULL',
248
+ '',
249
+ nil,
250
+ '2006-09-12',
251
+ '2006-09-11T17:28:07Z',
252
+ '2006-09-11T17:28:07+09:00',
253
+ '2006-09-11 17:28:07.662694 +09:00',
254
+ '=',
255
+ ].each {|c|
256
+ ['','hoge'].each {|ext|
257
+ src = c.class == String ? (c + ext) : c
258
+ y = src.ya2yaml(
259
+ :escape_as_utf8 => true
260
+ )
261
+ # puts y
262
+ r = YAML.load(y)
263
+ assert_equal(src,r)
264
+ }
265
+ }
266
+ end
267
+
268
+ def test_roundtrip_string
269
+ chars = "aあ\t\-\?,\[\{\#&\*!\|>'\"\%\@\`.\\ \n\xc2\xa0\xe2\x80\xa8".split('')
270
+
271
+ chars.each {|i|
272
+ chars.each {|j|
273
+ chars.each {|k|
274
+ chars.each {|l|
275
+ src = i + j + k + l
276
+ y = src.ya2yaml(
277
+ :printable_with_syck => true,
278
+ :escape_b_specific => true,
279
+ :escape_as_utf8 => true
280
+ )
281
+ # puts y
282
+ r = YAML.load(y)
283
+ assert_equal(src,r)
284
+ }
285
+ }
286
+ }
287
+ }
288
+ end
289
+
290
+ def test_roundtrip_types
291
+ objects = [
292
+ [],
293
+ [1],
294
+ {},
295
+ {'foo' => 'bar'},
296
+ nil,
297
+ 'hoge',
298
+ "abc\nxyz\n",
299
+ "\xff\xff",
300
+ true,
301
+ false,
302
+ 1000,
303
+ 1000.1,
304
+ -1000,
305
+ -1000.1,
306
+ Date.today(),
307
+ Time.new(),
308
+ :foo,
309
+ 1..10,
310
+ /abc\nxyz/i,
311
+ @struct,
312
+ @klass,
313
+ ]
314
+
315
+ objects.each {|obj|
316
+ src = case obj.class.to_s
317
+ when 'Array'
318
+ (obj.length) == 0 ? [] : objects
319
+ when 'Hash'
320
+ if (obj.length) == 0
321
+ {}
322
+ else
323
+ h = {}
324
+ c = 0
325
+ objects.each {|val|
326
+ h[c] = {}
327
+ objects.each {|key|
328
+ h[c][key] = val unless (key.class == Hash || key.class == Moo)
329
+ }
330
+ c += 1
331
+ }
332
+ h
333
+ end
334
+ else
335
+ obj
336
+ end
337
+ y = src.ya2yaml(
338
+ :syck_compatible => true
339
+ )
340
+ # puts y
341
+
342
+ r = YAML.load(y)
343
+ assert_equal(src,r)
344
+ }
345
+ end
346
+
347
+ def test_roundtrip_various
348
+ [
349
+ [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'},],
350
+ [],
351
+ {[123,223]=>456},
352
+ {},
353
+ {'foo' => {1 => {2=>3,4=>5},6 => [7,8]}},
354
+ "abc",
355
+ " abc\n def\ndef\ndef\ndef\ndef\n",
356
+ "abc\n def\ndef\n",
357
+ "abc\n def\ndef\n\n",
358
+ "abc\n def\ndef\n\n ",
359
+ "abc\n def\ndef\n \n",
360
+ "abc\n def\ndef \n \n",
361
+ "abc\n def\ndef \n \n ",
362
+ ' ほげほげほげ',
363
+ {"ほげ\nほげ\n ほげ" => 123},
364
+ [["ほげ\nほげ\n ほげ"]],
365
+ "ほげh\x4fge\nほげ\nほげ",
366
+ [{'ほげ'=>'abc',"ほげ\nほげ"=>'ほげ'},'ほげ',@text],
367
+ [Date.today,-9.011,0.023,4,-5,{1=>-2,-1=>@text,'_foo'=>'bar','ぬお-ぬお'=>321}],
368
+ {1=>-2,-1=>@gif,'_foo'=>'bar','ぬお-ぬお'=>321},
369
+ ].each {|src|
370
+ y = src.ya2yaml(
371
+ :syck_compatible => true
372
+ )
373
+ # puts y
374
+
375
+ r = YAML.load(y)
376
+ assert_equal(src,r)
377
+ }
378
+ end
379
+
380
+ end
381
+
382
+ __END__
Binary file
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "ya2yaml-jomz"
5
+ s.version = "0.3.2"
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["Peter T Bosse II", "Roman Kamyk Jr", "Antony Sastre", "Anders Tornqvist"]
8
+ s.email = [""]
9
+ s.homepage = "https://github.com/jomz/ya2yaml"
10
+ s.summary = ""
11
+ s.description = '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).'
12
+
13
+ s.required_ruby_version = ::Gem::Requirement.new(">= 1.8.7")
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+
16
+ ignores = if File.exist?('.gitignore')
17
+ File.read('.gitignore').split("\n").inject([]) {|a,p| a + Dir[p] }
18
+ else
19
+ []
20
+ end
21
+ s.files = Dir['**/*'] - ignores
22
+ s.test_files = Dir['test/**/*'] - ignores
23
+ s.require_paths = ["lib"]
24
+ end
metadata CHANGED
@@ -1,16 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ya2yaml-jomz
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 1
10
- version: 0.3.1
9
+ - 2
10
+ version: 0.3.2
11
11
  platform: ruby
12
12
  authors:
13
- - ""
13
+ - Peter T Bosse II
14
+ - Roman Kamyk Jr
15
+ - Antony Sastre
16
+ - Anders Tornqvist
14
17
  autorequire:
15
18
  bindir: bin
16
19
  cert_chain: []
@@ -19,7 +22,7 @@ date: 2011-12-29 00:00:00 +01:00
19
22
  default_executable:
20
23
  dependencies: []
21
24
 
22
- description: ""
25
+ description: 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).
23
26
  email:
24
27
  - ""
25
28
  executables: []
@@ -28,10 +31,17 @@ extensions: []
28
31
 
29
32
  extra_rdoc_files: []
30
33
 
31
- files: []
32
-
34
+ files:
35
+ - lib/ya2yaml.rb
36
+ - LICENSE
37
+ - README
38
+ - test/t.gif
39
+ - test/t.yaml
40
+ - test/test.rb
41
+ - ya2yaml-jomz-0.3.1.gem
42
+ - ya2yaml.gemspec
33
43
  has_rdoc: true
34
- homepage: ""
44
+ homepage: https://github.com/jomz/ya2yaml
35
45
  licenses: []
36
46
 
37
47
  post_install_message:
@@ -68,5 +78,7 @@ rubygems_version: 1.5.3
68
78
  signing_key:
69
79
  specification_version: 3
70
80
  summary: ""
71
- test_files: []
72
-
81
+ test_files:
82
+ - test/t.gif
83
+ - test/t.yaml
84
+ - test/test.rb