psych 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/.autotest +18 -0
  2. data/.gemtest +0 -0
  3. data/CHANGELOG.rdoc +3 -0
  4. data/Manifest.txt +87 -0
  5. data/README.rdoc +50 -0
  6. data/Rakefile +66 -0
  7. data/ext/psych/emitter.c +517 -0
  8. data/ext/psych/emitter.h +8 -0
  9. data/ext/psych/extconf.rb +22 -0
  10. data/ext/psych/parser.c +384 -0
  11. data/ext/psych/parser.h +6 -0
  12. data/ext/psych/psych.c +34 -0
  13. data/ext/psych/psych.h +20 -0
  14. data/ext/psych/to_ruby.c +41 -0
  15. data/ext/psych/to_ruby.h +8 -0
  16. data/ext/psych/yaml_tree.c +24 -0
  17. data/ext/psych/yaml_tree.h +8 -0
  18. data/lib/psych.rb +263 -0
  19. data/lib/psych/coder.rb +94 -0
  20. data/lib/psych/core_ext.rb +39 -0
  21. data/lib/psych/deprecated.rb +82 -0
  22. data/lib/psych/handler.rb +221 -0
  23. data/lib/psych/json.rb +6 -0
  24. data/lib/psych/json/ruby_events.rb +19 -0
  25. data/lib/psych/json/stream.rb +15 -0
  26. data/lib/psych/json/tree_builder.rb +12 -0
  27. data/lib/psych/json/yaml_events.rb +29 -0
  28. data/lib/psych/nodes.rb +77 -0
  29. data/lib/psych/nodes/alias.rb +18 -0
  30. data/lib/psych/nodes/document.rb +60 -0
  31. data/lib/psych/nodes/mapping.rb +56 -0
  32. data/lib/psych/nodes/node.rb +52 -0
  33. data/lib/psych/nodes/scalar.rb +67 -0
  34. data/lib/psych/nodes/sequence.rb +81 -0
  35. data/lib/psych/nodes/stream.rb +37 -0
  36. data/lib/psych/omap.rb +4 -0
  37. data/lib/psych/parser.rb +47 -0
  38. data/lib/psych/scalar_scanner.rb +105 -0
  39. data/lib/psych/set.rb +4 -0
  40. data/lib/psych/stream.rb +36 -0
  41. data/lib/psych/streaming.rb +22 -0
  42. data/lib/psych/tree_builder.rb +94 -0
  43. data/lib/psych/visitors.rb +6 -0
  44. data/lib/psych/visitors/depth_first.rb +26 -0
  45. data/lib/psych/visitors/emitter.rb +44 -0
  46. data/lib/psych/visitors/json_tree.rb +21 -0
  47. data/lib/psych/visitors/to_ruby.rb +267 -0
  48. data/lib/psych/visitors/visitor.rb +19 -0
  49. data/lib/psych/visitors/yaml_tree.rb +373 -0
  50. data/test/psych/helper.rb +63 -0
  51. data/test/psych/json/test_stream.rb +109 -0
  52. data/test/psych/nodes/test_enumerable.rb +43 -0
  53. data/test/psych/test_alias_and_anchor.rb +26 -0
  54. data/test/psych/test_array.rb +19 -0
  55. data/test/psych/test_boolean.rb +36 -0
  56. data/test/psych/test_class.rb +17 -0
  57. data/test/psych/test_coder.rb +184 -0
  58. data/test/psych/test_date_time.rb +17 -0
  59. data/test/psych/test_deprecated.rb +210 -0
  60. data/test/psych/test_document.rb +46 -0
  61. data/test/psych/test_emitter.rb +94 -0
  62. data/test/psych/test_encoding.rb +179 -0
  63. data/test/psych/test_engine_manager.rb +57 -0
  64. data/test/psych/test_exception.rb +39 -0
  65. data/test/psych/test_hash.rb +30 -0
  66. data/test/psych/test_json_tree.rb +65 -0
  67. data/test/psych/test_merge_keys.rb +72 -0
  68. data/test/psych/test_nil.rb +18 -0
  69. data/test/psych/test_null.rb +19 -0
  70. data/test/psych/test_object.rb +27 -0
  71. data/test/psych/test_omap.rb +68 -0
  72. data/test/psych/test_parser.rb +297 -0
  73. data/test/psych/test_psych.rb +168 -0
  74. data/test/psych/test_scalar.rb +11 -0
  75. data/test/psych/test_scalar_scanner.rb +69 -0
  76. data/test/psych/test_serialize_subclasses.rb +38 -0
  77. data/test/psych/test_set.rb +49 -0
  78. data/test/psych/test_stream.rb +49 -0
  79. data/test/psych/test_string.rb +49 -0
  80. data/test/psych/test_struct.rb +51 -0
  81. data/test/psych/test_symbol.rb +17 -0
  82. data/test/psych/test_to_yaml_properties.rb +63 -0
  83. data/test/psych/test_tree_builder.rb +79 -0
  84. data/test/psych/test_yaml.rb +1256 -0
  85. data/test/psych/visitors/test_depth_first.rb +49 -0
  86. data/test/psych/visitors/test_emitter.rb +144 -0
  87. data/test/psych/visitors/test_to_ruby.rb +325 -0
  88. data/test/psych/visitors/test_yaml_tree.rb +155 -0
  89. metadata +232 -0
@@ -0,0 +1,8 @@
1
+ #ifndef PSYCH_EMITTER_H
2
+ #define PSYCH_EMITTER_H
3
+
4
+ #include <psych.h>
5
+
6
+ void Init_psych_emitter();
7
+
8
+ #endif
@@ -0,0 +1,22 @@
1
+ require 'mkmf'
2
+
3
+ # :stopdoc:
4
+
5
+ RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
6
+
7
+ INCLUDEDIR = Config::CONFIG['includedir']
8
+ LIBDIR = Config::CONFIG['libdir']
9
+ LIB_DIRS = ['/opt/local/lib', '/usr/local/lib', LIBDIR, '/usr/lib']
10
+ libyaml = dir_config 'libyaml', '/opt/local/include', '/opt/local/lib'
11
+
12
+ def asplode missing
13
+ abort "#{missing} is missing. Try 'port install libyaml +universal' " +
14
+ "or 'yum install libyaml-devel'"
15
+ end
16
+
17
+ asplode('yaml.h') unless find_header 'yaml.h'
18
+ asplode('libyaml') unless find_library 'yaml', 'yaml_get_version'
19
+
20
+ create_makefile 'psych'
21
+
22
+ # :startdoc:
@@ -0,0 +1,384 @@
1
+ #include <psych.h>
2
+
3
+ VALUE cPsychParser;
4
+ VALUE ePsychSyntaxError;
5
+
6
+ static ID id_read;
7
+ static ID id_path;
8
+ static ID id_empty;
9
+ static ID id_start_stream;
10
+ static ID id_end_stream;
11
+ static ID id_start_document;
12
+ static ID id_end_document;
13
+ static ID id_alias;
14
+ static ID id_scalar;
15
+ static ID id_start_sequence;
16
+ static ID id_end_sequence;
17
+ static ID id_start_mapping;
18
+ static ID id_end_mapping;
19
+
20
+ #define PSYCH_TRANSCODE(_str, _yaml_enc, _internal_enc) \
21
+ do { \
22
+ rb_enc_associate_index((_str), (_yaml_enc)); \
23
+ if(_internal_enc) \
24
+ (_str) = rb_str_export_to_enc((_str), (_internal_enc)); \
25
+ } while (0)
26
+
27
+ static int io_reader(void * data, unsigned char *buf, size_t size, size_t *read)
28
+ {
29
+ VALUE io = (VALUE)data;
30
+ VALUE string = rb_funcall(io, id_read, 1, INT2NUM(size));
31
+
32
+ *read = 0;
33
+
34
+ if(! NIL_P(string)) {
35
+ void * str = (void *)StringValuePtr(string);
36
+ *read = (size_t)RSTRING_LEN(string);
37
+ memcpy(buf, str, *read);
38
+ }
39
+
40
+ return 1;
41
+ }
42
+
43
+ static void dealloc(void * ptr)
44
+ {
45
+ yaml_parser_t * parser;
46
+
47
+ parser = (yaml_parser_t *)ptr;
48
+ yaml_parser_delete(parser);
49
+ xfree(parser);
50
+ }
51
+
52
+ static VALUE allocate(VALUE klass)
53
+ {
54
+ yaml_parser_t * parser;
55
+
56
+ parser = xmalloc(sizeof(yaml_parser_t));
57
+ yaml_parser_initialize(parser);
58
+
59
+ return Data_Wrap_Struct(klass, 0, dealloc, parser);
60
+ }
61
+
62
+ /*
63
+ * call-seq:
64
+ * parser.parse(yaml)
65
+ *
66
+ * Parse the YAML document contained in +yaml+. Events will be called on
67
+ * the handler set on the parser instance.
68
+ *
69
+ * See Psych::Parser and Psych::Parser#handler
70
+ */
71
+ static VALUE parse(VALUE self, VALUE yaml)
72
+ {
73
+ yaml_parser_t * parser;
74
+ yaml_event_t event;
75
+ int done = 0;
76
+ #ifdef HAVE_RUBY_ENCODING_H
77
+ int encoding = rb_utf8_encindex();
78
+ rb_encoding * internal_enc = rb_default_internal_encoding();
79
+ #endif
80
+ VALUE handler = rb_iv_get(self, "@handler");
81
+
82
+ Data_Get_Struct(self, yaml_parser_t, parser);
83
+
84
+ if(rb_respond_to(yaml, id_read)) {
85
+ yaml_parser_set_input(parser, io_reader, (void *)yaml);
86
+ } else {
87
+ StringValue(yaml);
88
+ yaml_parser_set_input_string(
89
+ parser,
90
+ (const unsigned char *)RSTRING_PTR(yaml),
91
+ (size_t)RSTRING_LEN(yaml)
92
+ );
93
+ }
94
+
95
+ while(!done) {
96
+ if(!yaml_parser_parse(parser, &event)) {
97
+ VALUE path;
98
+ size_t line = parser->mark.line;
99
+ size_t column = parser->mark.column;
100
+
101
+ if(rb_respond_to(yaml, id_path))
102
+ path = rb_funcall(yaml, id_path, 0);
103
+ else
104
+ path = rb_str_new2("<unknown>");
105
+
106
+ yaml_parser_delete(parser);
107
+ yaml_parser_initialize(parser);
108
+
109
+ rb_raise(ePsychSyntaxError, "(%s): couldn't parse YAML at line %d column %d",
110
+ StringValuePtr(path),
111
+ (int)line, (int)column);
112
+ }
113
+
114
+ switch(event.type) {
115
+ case YAML_STREAM_START_EVENT:
116
+
117
+ rb_funcall(handler, id_start_stream, 1,
118
+ INT2NUM((long)event.data.stream_start.encoding)
119
+ );
120
+ break;
121
+ case YAML_DOCUMENT_START_EVENT:
122
+ {
123
+ /* Get a list of tag directives (if any) */
124
+ VALUE tag_directives = rb_ary_new();
125
+ /* Grab the document version */
126
+ VALUE version = event.data.document_start.version_directive ?
127
+ rb_ary_new3(
128
+ (long)2,
129
+ INT2NUM((long)event.data.document_start.version_directive->major),
130
+ INT2NUM((long)event.data.document_start.version_directive->minor)
131
+ ) : rb_ary_new();
132
+
133
+ if(event.data.document_start.tag_directives.start) {
134
+ yaml_tag_directive_t *start =
135
+ event.data.document_start.tag_directives.start;
136
+ yaml_tag_directive_t *end =
137
+ event.data.document_start.tag_directives.end;
138
+ for(; start != end; start++) {
139
+ VALUE handle = Qnil;
140
+ VALUE prefix = Qnil;
141
+ if(start->handle) {
142
+ handle = rb_str_new2((const char *)start->handle);
143
+ #ifdef HAVE_RUBY_ENCODING_H
144
+ PSYCH_TRANSCODE(handle, encoding, internal_enc);
145
+ #endif
146
+ }
147
+
148
+ if(start->prefix) {
149
+ prefix = rb_str_new2((const char *)start->prefix);
150
+ #ifdef HAVE_RUBY_ENCODING_H
151
+ PSYCH_TRANSCODE(prefix, encoding, internal_enc);
152
+ #endif
153
+ }
154
+
155
+ rb_ary_push(tag_directives, rb_ary_new3((long)2, handle, prefix));
156
+ }
157
+ }
158
+ rb_funcall(handler, id_start_document, 3,
159
+ version, tag_directives,
160
+ event.data.document_start.implicit == 1 ? Qtrue : Qfalse
161
+ );
162
+ }
163
+ break;
164
+ case YAML_DOCUMENT_END_EVENT:
165
+ rb_funcall(handler, id_end_document, 1,
166
+ event.data.document_end.implicit == 1 ? Qtrue : Qfalse
167
+ );
168
+ break;
169
+ case YAML_ALIAS_EVENT:
170
+ {
171
+ VALUE alias = Qnil;
172
+ if(event.data.alias.anchor) {
173
+ alias = rb_str_new2((const char *)event.data.alias.anchor);
174
+ #ifdef HAVE_RUBY_ENCODING_H
175
+ PSYCH_TRANSCODE(alias, encoding, internal_enc);
176
+ #endif
177
+ }
178
+
179
+ rb_funcall(handler, id_alias, 1, alias);
180
+ }
181
+ break;
182
+ case YAML_SCALAR_EVENT:
183
+ {
184
+ VALUE anchor = Qnil;
185
+ VALUE tag = Qnil;
186
+ VALUE plain_implicit, quoted_implicit, style;
187
+ VALUE val = rb_str_new(
188
+ (const char *)event.data.scalar.value,
189
+ (long)event.data.scalar.length
190
+ );
191
+
192
+ #ifdef HAVE_RUBY_ENCODING_H
193
+ PSYCH_TRANSCODE(val, encoding, internal_enc);
194
+ #endif
195
+
196
+ if(event.data.scalar.anchor) {
197
+ anchor = rb_str_new2((const char *)event.data.scalar.anchor);
198
+ #ifdef HAVE_RUBY_ENCODING_H
199
+ PSYCH_TRANSCODE(anchor, encoding, internal_enc);
200
+ #endif
201
+ }
202
+
203
+ if(event.data.scalar.tag) {
204
+ tag = rb_str_new2((const char *)event.data.scalar.tag);
205
+ #ifdef HAVE_RUBY_ENCODING_H
206
+ PSYCH_TRANSCODE(tag, encoding, internal_enc);
207
+ #endif
208
+ }
209
+
210
+ plain_implicit =
211
+ event.data.scalar.plain_implicit == 0 ? Qfalse : Qtrue;
212
+
213
+ quoted_implicit =
214
+ event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue;
215
+
216
+ style = INT2NUM((long)event.data.scalar.style);
217
+
218
+ rb_funcall(handler, id_scalar, 6,
219
+ val, anchor, tag, plain_implicit, quoted_implicit, style);
220
+ }
221
+ break;
222
+ case YAML_SEQUENCE_START_EVENT:
223
+ {
224
+ VALUE anchor = Qnil;
225
+ VALUE tag = Qnil;
226
+ VALUE implicit, style;
227
+ if(event.data.sequence_start.anchor) {
228
+ anchor = rb_str_new2((const char *)event.data.sequence_start.anchor);
229
+ #ifdef HAVE_RUBY_ENCODING_H
230
+ PSYCH_TRANSCODE(anchor, encoding, internal_enc);
231
+ #endif
232
+ }
233
+
234
+ tag = Qnil;
235
+ if(event.data.sequence_start.tag) {
236
+ tag = rb_str_new2((const char *)event.data.sequence_start.tag);
237
+ #ifdef HAVE_RUBY_ENCODING_H
238
+ PSYCH_TRANSCODE(tag, encoding, internal_enc);
239
+ #endif
240
+ }
241
+
242
+ implicit =
243
+ event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue;
244
+
245
+ style = INT2NUM((long)event.data.sequence_start.style);
246
+
247
+ rb_funcall(handler, id_start_sequence, 4,
248
+ anchor, tag, implicit, style);
249
+ }
250
+ break;
251
+ case YAML_SEQUENCE_END_EVENT:
252
+ rb_funcall(handler, id_end_sequence, 0);
253
+ break;
254
+ case YAML_MAPPING_START_EVENT:
255
+ {
256
+ VALUE anchor = Qnil;
257
+ VALUE tag = Qnil;
258
+ VALUE implicit, style;
259
+ if(event.data.mapping_start.anchor) {
260
+ anchor = rb_str_new2((const char *)event.data.mapping_start.anchor);
261
+ #ifdef HAVE_RUBY_ENCODING_H
262
+ PSYCH_TRANSCODE(anchor, encoding, internal_enc);
263
+ #endif
264
+ }
265
+
266
+ if(event.data.mapping_start.tag) {
267
+ tag = rb_str_new2((const char *)event.data.mapping_start.tag);
268
+ #ifdef HAVE_RUBY_ENCODING_H
269
+ PSYCH_TRANSCODE(tag, encoding, internal_enc);
270
+ #endif
271
+ }
272
+
273
+ implicit =
274
+ event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue;
275
+
276
+ style = INT2NUM((long)event.data.mapping_start.style);
277
+
278
+ rb_funcall(handler, id_start_mapping, 4,
279
+ anchor, tag, implicit, style);
280
+ }
281
+ break;
282
+ case YAML_MAPPING_END_EVENT:
283
+ rb_funcall(handler, id_end_mapping, 0);
284
+ break;
285
+ case YAML_NO_EVENT:
286
+ rb_funcall(handler, id_empty, 0);
287
+ break;
288
+ case YAML_STREAM_END_EVENT:
289
+ rb_funcall(handler, id_end_stream, 0);
290
+ done = 1;
291
+ break;
292
+ }
293
+ }
294
+
295
+ return self;
296
+ }
297
+
298
+ /*
299
+ * call-seq:
300
+ * parser.external_encoding=(encoding)
301
+ *
302
+ * Set the encoding for this parser to +encoding+
303
+ */
304
+ static VALUE set_external_encoding(VALUE self, VALUE encoding)
305
+ {
306
+ yaml_parser_t * parser;
307
+ VALUE exception;
308
+
309
+ Data_Get_Struct(self, yaml_parser_t, parser);
310
+
311
+ if(parser->encoding) {
312
+ exception = rb_const_get_at(mPsych, rb_intern("Exception"));
313
+ rb_raise(exception, "don't set the encoding twice!");
314
+ }
315
+
316
+ yaml_parser_set_encoding(parser, NUM2INT(encoding));
317
+
318
+ return encoding;
319
+ }
320
+
321
+ /*
322
+ * call-seq:
323
+ * parser.mark # => #<Psych::Parser::Mark>
324
+ *
325
+ * Returns a Psych::Parser::Mark object that contains line, column, and index
326
+ * information.
327
+ */
328
+ static VALUE mark(VALUE self)
329
+ {
330
+ VALUE mark_klass;
331
+ VALUE args[3];
332
+ yaml_parser_t * parser;
333
+
334
+ Data_Get_Struct(self, yaml_parser_t, parser);
335
+ mark_klass = rb_const_get_at(cPsychParser, rb_intern("Mark"));
336
+ args[0] = INT2NUM(parser->mark.index);
337
+ args[1] = INT2NUM(parser->mark.line);
338
+ args[2] = INT2NUM(parser->mark.column);
339
+
340
+ return rb_class_new_instance(3, args, mark_klass);
341
+ }
342
+
343
+ void Init_psych_parser()
344
+ {
345
+ #if 0
346
+ mPsych = rb_define_module("Psych");
347
+ #endif
348
+
349
+ cPsychParser = rb_define_class_under(mPsych, "Parser", rb_cObject);
350
+ rb_define_alloc_func(cPsychParser, allocate);
351
+
352
+ /* Any encoding: Let the parser choose the encoding */
353
+ rb_define_const(cPsychParser, "ANY", INT2NUM(YAML_ANY_ENCODING));
354
+
355
+ /* UTF-8 Encoding */
356
+ rb_define_const(cPsychParser, "UTF8", INT2NUM(YAML_UTF8_ENCODING));
357
+
358
+ /* UTF-16-LE Encoding with BOM */
359
+ rb_define_const(cPsychParser, "UTF16LE", INT2NUM(YAML_UTF16LE_ENCODING));
360
+
361
+ /* UTF-16-BE Encoding with BOM */
362
+ rb_define_const(cPsychParser, "UTF16BE", INT2NUM(YAML_UTF16BE_ENCODING));
363
+
364
+ ePsychSyntaxError = rb_define_class_under(mPsych, "SyntaxError", rb_eSyntaxError);
365
+
366
+ rb_define_method(cPsychParser, "parse", parse, 1);
367
+ rb_define_method(cPsychParser, "mark", mark, 0);
368
+ rb_define_method(cPsychParser, "external_encoding=", set_external_encoding, 1);
369
+
370
+ id_read = rb_intern("read");
371
+ id_path = rb_intern("path");
372
+ id_empty = rb_intern("empty");
373
+ id_start_stream = rb_intern("start_stream");
374
+ id_end_stream = rb_intern("end_stream");
375
+ id_start_document = rb_intern("start_document");
376
+ id_end_document = rb_intern("end_document");
377
+ id_alias = rb_intern("alias");
378
+ id_scalar = rb_intern("scalar");
379
+ id_start_sequence = rb_intern("start_sequence");
380
+ id_end_sequence = rb_intern("end_sequence");
381
+ id_start_mapping = rb_intern("start_mapping");
382
+ id_end_mapping = rb_intern("end_mapping");
383
+ }
384
+ /* vim: set noet sws=4 sw=4: */
@@ -0,0 +1,6 @@
1
+ #ifndef PSYCH_PARSER_H
2
+ #define PSYCH_PARSER_H
3
+
4
+ void Init_psych_parser();
5
+
6
+ #endif
data/ext/psych/psych.c ADDED
@@ -0,0 +1,34 @@
1
+ #include <psych.h>
2
+
3
+ /* call-seq: Psych.libyaml_version
4
+ *
5
+ * Returns the version of libyaml being used
6
+ */
7
+ static VALUE libyaml_version(VALUE module)
8
+ {
9
+ int major, minor, patch;
10
+ VALUE list[3];
11
+
12
+ yaml_get_version(&major, &minor, &patch);
13
+
14
+ list[0] = INT2NUM((long)major);
15
+ list[1] = INT2NUM((long)minor);
16
+ list[2] = INT2NUM((long)patch);
17
+
18
+ return rb_ary_new4((long)3, list);
19
+ }
20
+
21
+ VALUE mPsych;
22
+
23
+ void Init_psych()
24
+ {
25
+ mPsych = rb_define_module("Psych");
26
+
27
+ rb_define_singleton_method(mPsych, "libyaml_version", libyaml_version, 0);
28
+
29
+ Init_psych_parser();
30
+ Init_psych_emitter();
31
+ Init_psych_to_ruby();
32
+ Init_psych_yaml_tree();
33
+ }
34
+ /* vim: set noet sws=4 sw=4: */