psych 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.travis.yml CHANGED
@@ -1,3 +1,9 @@
1
1
  rvm:
2
2
  - 1.9.2
3
3
  - 1.9.3
4
+ - ruby-head
5
+ before_script:
6
+ - gem install isolate
7
+ - gem install hoe
8
+ - gem install rake-compiler
9
+ script: rake isolate test
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,129 @@
1
+ Fri Mar 9 06:29:22 2012 Aaron Patterson <aaron@tenderlovemaking.com>
2
+
3
+ * ext/psych/lib/psych.rb (load, parse): stop parsing or loading after
4
+ the first document has been parsed.
5
+
6
+ * test/psych/test_stream.rb: pertinent tests.
7
+
8
+ Fri Mar 9 06:17:05 2012 Aaron Patterson <aaron@tenderlovemaking.com>
9
+
10
+ * ext/psych/lib/psych.rb (parse_stream, load_stream): if a block is
11
+ given, documents will be yielded to the block as they are parsed.
12
+ [ruby-core:42404] [Bug #5978]
13
+
14
+ * ext/psych/lib/psych/handlers/document_stream.rb: add a handler that
15
+ yields documents as they are parsed
16
+
17
+ * test/psych/test_stream.rb: corresponding tests.
18
+
19
+ Tue Mar 6 02:31:20 2012 Aaron Patterson <aaron@tenderlovemaking.com>
20
+
21
+ * ext/psych/lib/psych/core_ext.rb: only extend Kernel if IRB is loaded
22
+ in order to stop method pollution.
23
+
24
+ Tue Feb 28 10:28:51 2012 Aaron Patterson <aaron@tenderlovemaking.com>
25
+
26
+ * ext/psych/lib/psych.rb: default open YAML files with utf8 external
27
+ encoding. [ruby-core:42967]
28
+ * test/psych/test_tainted.rb: ditto
29
+
30
+ Fri Feb 24 13:54:33 2012 Aaron Patterson <aaron@tenderlovemaking.com>
31
+
32
+ * ext/psych/parser.c: prevent a memory leak by protecting calls to
33
+ handler callbacks.
34
+ * test/psych/test_parser.rb: test to demonstrate leak.
35
+
36
+ Fri Feb 24 08:08:38 2012 Aaron Patterson <aaron@tenderlovemaking.com>
37
+
38
+ * ext/psych/parser.c: set parser encoding based on the YAML input
39
+ rather than user configuration.
40
+ * test/psych/test_encoding.rb: corresponding tests.
41
+ * test/psych/test_parser.rb: ditto
42
+ * test/psych/test_tainted.rb: ditto
43
+
44
+ Fri Feb 10 03:41:31 2012 Aaron Patterson <aaron@tenderlovemaking.com>
45
+
46
+ * ext/psych/parser.c: removed external encoding setter, allow parser
47
+ to be reused.
48
+ * ext/psych/lib/psych/parser.rb: added external encoding setter.
49
+ * test/psych/test_parser.rb: test parser reuse
50
+
51
+ Wed Jan 18 12:49:15 2012 Aaron Patterson <aaron@tenderlovemaking.com>
52
+
53
+ * ext/psych/lib/psych/visitors/to_ruby.rb: Added support for loading
54
+ subclasses of String with ivars
55
+ * ext/psych/lib/psych/visitors/yaml_tree.rb: Added support for dumping
56
+ subclasses of String with ivars
57
+ * test/psych/test_string.rb: corresponding tests
58
+
59
+ Sun Dec 18 12:42:48 2011 Aaron Patterson <aaron@tenderlovemaking.com>
60
+
61
+ * ext/psych/lib/psych/visitors/to_ruby.rb: BigDecimals can be restored
62
+ from YAML.
63
+ * ext/psych/lib/psych/visitors/yaml_tree.rb: BigDecimals can be dumped
64
+ to YAML.
65
+ * test/psych/test_numeric.rb: tests for BigDecimal serialization
66
+
67
+ Sun Dec 18 12:03:13 2011 Aaron Patterson <aaron@tenderlovemaking.com>
68
+
69
+ * ext/psych/lib/psych/scalar_scanner.rb: Strings that look like dates
70
+ should be treated as strings and not dates.
71
+
72
+ * test/psych/test_scalar_scanner.rb: corresponding tests.
73
+
74
+ Wed Dec 7 08:04:31 2011 Aaron Patterson <aaron@tenderlovemaking.com>
75
+
76
+ * ext/psych/lib/psych.rb (module Psych): parse and load methods take
77
+ an optional file name that is used when raising Psych::SyntaxError
78
+ exceptions
79
+ * ext/psych/lib/psych/syntax_error.rb (module Psych): allow nil file
80
+ names and handle nil file names in the exception message
81
+ * test/psych/test_exception.rb (module Psych): Tests for changes.
82
+
83
+ Wed Nov 30 09:09:37 2011 Aaron Patterson <aaron@tenderlovemaking.com>
84
+
85
+ * ext/psych/parser.c (parse): parse method can take an option file
86
+ name for use in exception messages.
87
+ * test/psych/test_parser.rb: corresponding tests.
88
+
89
+ Tue Nov 22 04:46:22 2011 Aaron Patterson <aaron@tenderlovemaking.com>
90
+
91
+ * ext/psych/lib/psych.rb: remove autoload from psych
92
+ * ext/psych/lib/psych/json.rb: ditto
93
+
94
+ Thu Nov 17 10:36:46 2011 Aaron Patterson <aaron@tenderlovemaking.com>
95
+
96
+ * ext/psych/lib/psych.rb (load_file): make sure opened yaml files are
97
+ also closed. [ruby-core:41088]
98
+
99
+ Wed Nov 9 04:52:16 2011 Aaron Patterson <aaron@tenderlovemaking.com>
100
+
101
+ * ext/psych/lib/psych/tree_builder.rb: dump complex numbers,
102
+ rationals, etc with reference ids.
103
+ * ext/psych/lib/psych/visitors/yaml_tree.rb: ditto
104
+ * ext/psych/lib/psych/visitors/to_ruby.rb: loading complex numbers,
105
+ rationals, etc with reference ids.
106
+ * test/psych/test_object_references.rb: corresponding tests
107
+
108
+ Mon Nov 7 20:31:52 2011 Aaron Patterson <aaron@tenderlovemaking.com>
109
+
110
+ * ext/psych/lib/psych/scalar_scanner.rb: make sure strings that look
111
+ like base 60 numbers are serialized as quoted strings.
112
+ * test/psych/test_string.rb: test for change.
113
+
114
+ Wed Oct 5 02:50:27 2011 Aaron Patterson <aaron@tenderlovemaking.com>
115
+
116
+ * ext/psych/lib/psych/syntax_error.rb: Add file, line, offset, and
117
+ message attributes during parse failure.
118
+ * ext/psych/parser.c: Update parser to raise exception with correct
119
+ values.
120
+ * test/psych/test_exception.rb: corresponding tests.
121
+
122
+ Wed Oct 5 01:52:16 2011 Aaron Patterson <aaron@tenderlovemaking.com>
123
+
124
+ * ext/psych/parser.c (parse): Use context_mark for indicating error
125
+ line and column.
126
+
1
127
  Tue Oct 4 06:29:55 2011 Aaron Patterson <aaron@tenderlovemaking.com>
2
128
 
3
129
  * ext/psych/lib/psych.rb: calling `yaml` rather than `to_yaml`.
data/Manifest.txt CHANGED
@@ -1,7 +1,6 @@
1
1
  .autotest
2
2
  .travis.yml
3
3
  CHANGELOG.rdoc
4
- Gemfile
5
4
  Manifest.txt
6
5
  README.rdoc
7
6
  Rakefile
@@ -21,7 +20,7 @@ lib/psych/coder.rb
21
20
  lib/psych/core_ext.rb
22
21
  lib/psych/deprecated.rb
23
22
  lib/psych/handler.rb
24
- lib/psych/json.rb
23
+ lib/psych/handlers/document_stream.rb
25
24
  lib/psych/json/ruby_events.rb
26
25
  lib/psych/json/stream.rb
27
26
  lib/psych/json/tree_builder.rb
@@ -40,6 +39,7 @@ lib/psych/scalar_scanner.rb
40
39
  lib/psych/set.rb
41
40
  lib/psych/stream.rb
42
41
  lib/psych/streaming.rb
42
+ lib/psych/syntax_error.rb
43
43
  lib/psych/tree_builder.rb
44
44
  lib/psych/visitors.rb
45
45
  lib/psych/visitors/depth_first.rb
@@ -70,6 +70,7 @@ test/psych/test_nil.rb
70
70
  test/psych/test_null.rb
71
71
  test/psych/test_numeric.rb
72
72
  test/psych/test_object.rb
73
+ test/psych/test_object_references.rb
73
74
  test/psych/test_omap.rb
74
75
  test/psych/test_parser.rb
75
76
  test/psych/test_psych.rb
data/README.rdoc CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  == Description
6
6
 
7
- Psych is a YAML parser and emitter. Psych leverages libyaml[http://libyaml.org]
7
+ Psych is a YAML parser and emitter. Psych leverages libyaml[http://pyyaml.org/wiki/LibYAML]
8
8
  for its YAML parsing and emitting capabilities. In addition to wrapping
9
9
  libyaml, Psych also knows how to serialize and de-serialize most Ruby objects
10
10
  to and from the YAML format.
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ end
11
11
  gem 'rake-compiler', '>= 0.4.1'
12
12
  require "rake/extensiontask"
13
13
 
14
- Hoe.plugin :debugging, :doofus, :git, :gemspec, :bundler
14
+ Hoe.plugin :doofus, :git, :gemspec, :isolate
15
15
 
16
16
  $hoe = Hoe.spec 'psych' do
17
17
  developer 'Aaron Patterson', 'aaron@tenderlovemaking.com'
data/ext/psych/emitter.c CHANGED
@@ -351,7 +351,7 @@ static VALUE start_mapping(
351
351
  (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValuePtr(anchor)),
352
352
  (yaml_char_t *)(NIL_P(tag) ? NULL : StringValuePtr(tag)),
353
353
  implicit ? 1 : 0,
354
- (yaml_sequence_style_t)NUM2INT(style)
354
+ (yaml_mapping_style_t)NUM2INT(style)
355
355
  );
356
356
 
357
357
  emit(emitter, &event);
data/ext/psych/parser.c CHANGED
@@ -59,6 +59,163 @@ static VALUE allocate(VALUE klass)
59
59
  return Data_Wrap_Struct(klass, 0, dealloc, parser);
60
60
  }
61
61
 
62
+ static VALUE make_exception(yaml_parser_t * parser, VALUE path)
63
+ {
64
+ size_t line, column;
65
+
66
+ line = parser->context_mark.line + 1;
67
+ column = parser->context_mark.column + 1;
68
+
69
+ return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6,
70
+ path,
71
+ INT2NUM(line),
72
+ INT2NUM(column),
73
+ INT2NUM(parser->problem_offset),
74
+ parser->problem ? rb_usascii_str_new2(parser->problem) : Qnil,
75
+ parser->context ? rb_usascii_str_new2(parser->context) : Qnil);
76
+ }
77
+
78
+ #ifdef HAVE_RUBY_ENCODING_H
79
+ static VALUE transcode_string(VALUE src, int * parser_encoding)
80
+ {
81
+ int utf8 = rb_utf8_encindex();
82
+ int utf16le = rb_enc_find_index("UTF16_LE");
83
+ int utf16be = rb_enc_find_index("UTF16_BE");
84
+ int source_encoding = rb_enc_get_index(src);
85
+
86
+ if (source_encoding == utf8) {
87
+ *parser_encoding = YAML_UTF8_ENCODING;
88
+ return src;
89
+ }
90
+
91
+ if (source_encoding == utf16le) {
92
+ *parser_encoding = YAML_UTF16LE_ENCODING;
93
+ return src;
94
+ }
95
+
96
+ if (source_encoding == utf16be) {
97
+ *parser_encoding = YAML_UTF16BE_ENCODING;
98
+ return src;
99
+ }
100
+
101
+ src = rb_str_export_to_enc(src, rb_utf8_encoding());
102
+ RB_GC_GUARD(src);
103
+
104
+ *parser_encoding = YAML_UTF8_ENCODING;
105
+ return src;
106
+ }
107
+
108
+ static VALUE transcode_io(VALUE src, int * parser_encoding)
109
+ {
110
+ VALUE io_external_encoding;
111
+ int io_external_enc_index;
112
+
113
+ io_external_encoding = rb_funcall(src, rb_intern("external_encoding"), 0);
114
+
115
+ /* if no encoding is returned, assume ascii8bit. */
116
+ if (NIL_P(io_external_encoding)) {
117
+ io_external_enc_index = rb_ascii8bit_encindex();
118
+ } else {
119
+ io_external_enc_index = rb_to_encoding_index(io_external_encoding);
120
+ }
121
+
122
+ /* Treat US-ASCII as utf_8 */
123
+ if (io_external_enc_index == rb_usascii_encindex()) {
124
+ *parser_encoding = YAML_UTF8_ENCODING;
125
+ return src;
126
+ }
127
+
128
+ if (io_external_enc_index == rb_utf8_encindex()) {
129
+ *parser_encoding = YAML_UTF8_ENCODING;
130
+ return src;
131
+ }
132
+
133
+ if (io_external_enc_index == rb_enc_find_index("UTF-16LE")) {
134
+ *parser_encoding = YAML_UTF16LE_ENCODING;
135
+ return src;
136
+ }
137
+
138
+ if (io_external_enc_index == rb_enc_find_index("UTF-16BE")) {
139
+ *parser_encoding = YAML_UTF16BE_ENCODING;
140
+ return src;
141
+ }
142
+
143
+ /* Just guess on ASCII-8BIT */
144
+ if (io_external_enc_index == rb_ascii8bit_encindex()) {
145
+ *parser_encoding = YAML_ANY_ENCODING;
146
+ return src;
147
+ }
148
+
149
+ rb_raise(rb_eArgError, "YAML file must be UTF-8, UTF-16LE, or UTF-16BE, not %s",
150
+ rb_enc_name(rb_enc_from_index(io_external_enc_index)));
151
+
152
+ return Qnil;
153
+ }
154
+
155
+ #endif
156
+
157
+ static VALUE protected_start_stream(VALUE pointer)
158
+ {
159
+ VALUE *args = (VALUE *)pointer;
160
+ return rb_funcall(args[0], id_start_stream, 1, args[1]);
161
+ }
162
+
163
+ static VALUE protected_start_document(VALUE pointer)
164
+ {
165
+ VALUE *args = (VALUE *)pointer;
166
+ return rb_funcall3(args[0], id_start_document, 3, args + 1);
167
+ }
168
+
169
+ static VALUE protected_end_document(VALUE pointer)
170
+ {
171
+ VALUE *args = (VALUE *)pointer;
172
+ return rb_funcall(args[0], id_end_document, 1, args[1]);
173
+ }
174
+
175
+ static VALUE protected_alias(VALUE pointer)
176
+ {
177
+ VALUE *args = (VALUE *)pointer;
178
+ return rb_funcall(args[0], id_alias, 1, args[1]);
179
+ }
180
+
181
+ static VALUE protected_scalar(VALUE pointer)
182
+ {
183
+ VALUE *args = (VALUE *)pointer;
184
+ return rb_funcall3(args[0], id_scalar, 6, args + 1);
185
+ }
186
+
187
+ static VALUE protected_start_sequence(VALUE pointer)
188
+ {
189
+ VALUE *args = (VALUE *)pointer;
190
+ return rb_funcall3(args[0], id_start_sequence, 4, args + 1);
191
+ }
192
+
193
+ static VALUE protected_end_sequence(VALUE handler)
194
+ {
195
+ return rb_funcall(handler, id_end_sequence, 0);
196
+ }
197
+
198
+ static VALUE protected_start_mapping(VALUE pointer)
199
+ {
200
+ VALUE *args = (VALUE *)pointer;
201
+ return rb_funcall3(args[0], id_start_mapping, 4, args + 1);
202
+ }
203
+
204
+ static VALUE protected_end_mapping(VALUE handler)
205
+ {
206
+ return rb_funcall(handler, id_end_mapping, 0);
207
+ }
208
+
209
+ static VALUE protected_empty(VALUE handler)
210
+ {
211
+ return rb_funcall(handler, id_empty, 0);
212
+ }
213
+
214
+ static VALUE protected_end_stream(VALUE handler)
215
+ {
216
+ return rb_funcall(handler, id_end_stream, 0);
217
+ }
218
+
62
219
  /*
63
220
  * call-seq:
64
221
  * parser.parse(yaml)
@@ -68,27 +225,48 @@ static VALUE allocate(VALUE klass)
68
225
  *
69
226
  * See Psych::Parser and Psych::Parser#handler
70
227
  */
71
- static VALUE parse(VALUE self, VALUE yaml)
228
+ static VALUE parse(int argc, VALUE *argv, VALUE self)
72
229
  {
230
+ VALUE yaml, path;
73
231
  yaml_parser_t * parser;
74
232
  yaml_event_t event;
75
233
  int done = 0;
76
234
  int tainted = 0;
235
+ int state = 0;
236
+ int parser_encoding = YAML_ANY_ENCODING;
77
237
  #ifdef HAVE_RUBY_ENCODING_H
78
238
  int encoding = rb_utf8_encindex();
79
239
  rb_encoding * internal_enc = rb_default_internal_encoding();
80
240
  #endif
81
241
  VALUE handler = rb_iv_get(self, "@handler");
82
242
 
243
+ if (rb_scan_args(argc, argv, "11", &yaml, &path) == 1) {
244
+ if(rb_respond_to(yaml, id_path))
245
+ path = rb_funcall(yaml, id_path, 0);
246
+ else
247
+ path = rb_str_new2("<unknown>");
248
+ }
249
+
83
250
  Data_Get_Struct(self, yaml_parser_t, parser);
84
251
 
252
+ yaml_parser_delete(parser);
253
+ yaml_parser_initialize(parser);
254
+
85
255
  if (OBJ_TAINTED(yaml)) tainted = 1;
86
256
 
87
- if(rb_respond_to(yaml, id_read)) {
257
+ if (rb_respond_to(yaml, id_read)) {
258
+ #ifdef HAVE_RUBY_ENCODING_H
259
+ yaml = transcode_io(yaml, &parser_encoding);
260
+ yaml_parser_set_encoding(parser, parser_encoding);
261
+ #endif
88
262
  yaml_parser_set_input(parser, io_reader, (void *)yaml);
89
263
  if (RTEST(rb_obj_is_kind_of(yaml, rb_cIO))) tainted = 1;
90
264
  } else {
91
265
  StringValue(yaml);
266
+ #ifdef HAVE_RUBY_ENCODING_H
267
+ yaml = transcode_string(yaml, &parser_encoding);
268
+ yaml_parser_set_encoding(parser, parser_encoding);
269
+ #endif
92
270
  yaml_parser_set_input_string(
93
271
  parser,
94
272
  (const unsigned char *)RSTRING_PTR(yaml),
@@ -98,32 +276,28 @@ static VALUE parse(VALUE self, VALUE yaml)
98
276
 
99
277
  while(!done) {
100
278
  if(!yaml_parser_parse(parser, &event)) {
101
- VALUE path;
102
- size_t line = parser->mark.line;
103
- size_t column = parser->mark.column;
104
-
105
- if(rb_respond_to(yaml, id_path))
106
- path = rb_funcall(yaml, id_path, 0);
107
- else
108
- path = rb_str_new2("<unknown>");
279
+ VALUE exception;
109
280
 
281
+ exception = make_exception(parser, path);
110
282
  yaml_parser_delete(parser);
111
283
  yaml_parser_initialize(parser);
112
284
 
113
- rb_raise(ePsychSyntaxError, "(%s): couldn't parse YAML at line %d column %d",
114
- StringValuePtr(path),
115
- (int)line, (int)column);
285
+ rb_exc_raise(exception);
116
286
  }
117
287
 
118
288
  switch(event.type) {
119
- case YAML_STREAM_START_EVENT:
120
-
121
- rb_funcall(handler, id_start_stream, 1,
122
- INT2NUM((long)event.data.stream_start.encoding)
123
- );
124
- break;
289
+ case YAML_STREAM_START_EVENT:
290
+ {
291
+ VALUE args[2];
292
+
293
+ args[0] = handler;
294
+ args[1] = INT2NUM((long)event.data.stream_start.encoding);
295
+ rb_protect(protected_start_stream, (VALUE)args, &state);
296
+ }
297
+ break;
125
298
  case YAML_DOCUMENT_START_EVENT:
126
299
  {
300
+ VALUE args[4];
127
301
  /* Get a list of tag directives (if any) */
128
302
  VALUE tag_directives = rb_ary_new();
129
303
  /* Grab the document version */
@@ -161,19 +335,25 @@ static VALUE parse(VALUE self, VALUE yaml)
161
335
  rb_ary_push(tag_directives, rb_ary_new3((long)2, handle, prefix));
162
336
  }
163
337
  }
164
- rb_funcall(handler, id_start_document, 3,
165
- version, tag_directives,
166
- event.data.document_start.implicit == 1 ? Qtrue : Qfalse
167
- );
338
+ args[0] = handler;
339
+ args[1] = version;
340
+ args[2] = tag_directives;
341
+ args[3] = event.data.document_start.implicit == 1 ? Qtrue : Qfalse;
342
+ rb_protect(protected_start_document, (VALUE)args, &state);
168
343
  }
169
344
  break;
170
345
  case YAML_DOCUMENT_END_EVENT:
171
- rb_funcall(handler, id_end_document, 1,
172
- event.data.document_end.implicit == 1 ? Qtrue : Qfalse
173
- );
346
+ {
347
+ VALUE args[2];
348
+
349
+ args[0] = handler;
350
+ args[1] = event.data.document_end.implicit == 1 ? Qtrue : Qfalse;
351
+ rb_protect(protected_end_document, (VALUE)args, &state);
352
+ }
174
353
  break;
175
354
  case YAML_ALIAS_EVENT:
176
355
  {
356
+ VALUE args[2];
177
357
  VALUE alias = Qnil;
178
358
  if(event.data.alias.anchor) {
179
359
  alias = rb_str_new2((const char *)event.data.alias.anchor);
@@ -183,11 +363,14 @@ static VALUE parse(VALUE self, VALUE yaml)
183
363
  #endif
184
364
  }
185
365
 
186
- rb_funcall(handler, id_alias, 1, alias);
366
+ args[0] = handler;
367
+ args[1] = alias;
368
+ rb_protect(protected_alias, (VALUE)args, &state);
187
369
  }
188
370
  break;
189
371
  case YAML_SCALAR_EVENT:
190
372
  {
373
+ VALUE args[7];
191
374
  VALUE anchor = Qnil;
192
375
  VALUE tag = Qnil;
193
376
  VALUE plain_implicit, quoted_implicit, style;
@@ -225,12 +408,19 @@ static VALUE parse(VALUE self, VALUE yaml)
225
408
 
226
409
  style = INT2NUM((long)event.data.scalar.style);
227
410
 
228
- rb_funcall(handler, id_scalar, 6,
229
- val, anchor, tag, plain_implicit, quoted_implicit, style);
411
+ args[0] = handler;
412
+ args[1] = val;
413
+ args[2] = anchor;
414
+ args[3] = tag;
415
+ args[4] = plain_implicit;
416
+ args[5] = quoted_implicit;
417
+ args[6] = style;
418
+ rb_protect(protected_scalar, (VALUE)args, &state);
230
419
  }
231
420
  break;
232
421
  case YAML_SEQUENCE_START_EVENT:
233
422
  {
423
+ VALUE args[5];
234
424
  VALUE anchor = Qnil;
235
425
  VALUE tag = Qnil;
236
426
  VALUE implicit, style;
@@ -256,15 +446,21 @@ static VALUE parse(VALUE self, VALUE yaml)
256
446
 
257
447
  style = INT2NUM((long)event.data.sequence_start.style);
258
448
 
259
- rb_funcall(handler, id_start_sequence, 4,
260
- anchor, tag, implicit, style);
449
+ args[0] = handler;
450
+ args[1] = anchor;
451
+ args[2] = tag;
452
+ args[3] = implicit;
453
+ args[4] = style;
454
+
455
+ rb_protect(protected_start_sequence, (VALUE)args, &state);
261
456
  }
262
457
  break;
263
458
  case YAML_SEQUENCE_END_EVENT:
264
- rb_funcall(handler, id_end_sequence, 0);
459
+ rb_protect(protected_end_sequence, handler, &state);
265
460
  break;
266
461
  case YAML_MAPPING_START_EVENT:
267
462
  {
463
+ VALUE args[5];
268
464
  VALUE anchor = Qnil;
269
465
  VALUE tag = Qnil;
270
466
  VALUE implicit, style;
@@ -289,50 +485,33 @@ static VALUE parse(VALUE self, VALUE yaml)
289
485
 
290
486
  style = INT2NUM((long)event.data.mapping_start.style);
291
487
 
292
- rb_funcall(handler, id_start_mapping, 4,
293
- anchor, tag, implicit, style);
488
+ args[0] = handler;
489
+ args[1] = anchor;
490
+ args[2] = tag;
491
+ args[3] = implicit;
492
+ args[4] = style;
493
+
494
+ rb_protect(protected_start_mapping, (VALUE)args, &state);
294
495
  }
295
496
  break;
296
497
  case YAML_MAPPING_END_EVENT:
297
- rb_funcall(handler, id_end_mapping, 0);
498
+ rb_protect(protected_end_mapping, handler, &state);
298
499
  break;
299
500
  case YAML_NO_EVENT:
300
- rb_funcall(handler, id_empty, 0);
501
+ rb_protect(protected_empty, handler, &state);
301
502
  break;
302
503
  case YAML_STREAM_END_EVENT:
303
- rb_funcall(handler, id_end_stream, 0);
504
+ rb_protect(protected_end_stream, handler, &state);
304
505
  done = 1;
305
506
  break;
306
507
  }
307
508
  yaml_event_delete(&event);
509
+ if (state) rb_jump_tag(state);
308
510
  }
309
511
 
310
512
  return self;
311
513
  }
312
514
 
313
- /*
314
- * call-seq:
315
- * parser.external_encoding=(encoding)
316
- *
317
- * Set the encoding for this parser to +encoding+
318
- */
319
- static VALUE set_external_encoding(VALUE self, VALUE encoding)
320
- {
321
- yaml_parser_t * parser;
322
- VALUE exception;
323
-
324
- Data_Get_Struct(self, yaml_parser_t, parser);
325
-
326
- if(parser->encoding) {
327
- exception = rb_const_get_at(mPsych, rb_intern("Exception"));
328
- rb_raise(exception, "don't set the encoding twice!");
329
- }
330
-
331
- yaml_parser_set_encoding(parser, NUM2INT(encoding));
332
-
333
- return encoding;
334
- }
335
-
336
515
  /*
337
516
  * call-seq:
338
517
  * parser.mark # => #<Psych::Parser::Mark>
@@ -376,11 +555,11 @@ void Init_psych_parser()
376
555
  /* UTF-16-BE Encoding with BOM */
377
556
  rb_define_const(cPsychParser, "UTF16BE", INT2NUM(YAML_UTF16BE_ENCODING));
378
557
 
558
+ rb_require("psych/syntax_error");
379
559
  ePsychSyntaxError = rb_define_class_under(mPsych, "SyntaxError", rb_eSyntaxError);
380
560
 
381
- rb_define_method(cPsychParser, "parse", parse, 1);
561
+ rb_define_method(cPsychParser, "parse", parse, -1);
382
562
  rb_define_method(cPsychParser, "mark", mark, 0);
383
- rb_define_method(cPsychParser, "external_encoding=", set_external_encoding, 1);
384
563
 
385
564
  id_read = rb_intern("read");
386
565
  id_path = rb_intern("path");