~ubuntu-branches/ubuntu/quantal/ruby1.9.1/quantal

« back to all changes in this revision

Viewing changes to ext/psych/parser.c

  • Committer: Bazaar Package Importer
  • Author(s): Lucas Nussbaum
  • Date: 2011-09-24 19:16:17 UTC
  • mfrom: (1.1.8 upstream) (13.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20110924191617-o1qz4rcmqjot8zuy
Tags: 1.9.3~rc1-1
* New upstream release: 1.9.3 RC1.
  + Includes load.c fixes. Closes: #639959.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
VALUE ePsychSyntaxError;
5
5
 
6
6
static ID id_read;
 
7
static ID id_path;
7
8
static ID id_empty;
8
9
static ID id_start_stream;
9
10
static ID id_end_stream;
18
19
 
19
20
#define PSYCH_TRANSCODE(_str, _yaml_enc, _internal_enc) \
20
21
  do { \
21
 
    rb_enc_associate_index(_str, _yaml_enc); \
 
22
    rb_enc_associate_index((_str), (_yaml_enc)); \
22
23
    if(_internal_enc) \
23
 
      _str = rb_str_export_to_enc(_str, _internal_enc); \
 
24
      (_str) = rb_str_export_to_enc((_str), (_internal_enc)); \
24
25
  } while (0)
25
26
 
26
27
static int io_reader(void * data, unsigned char *buf, size_t size, size_t *read)
39
40
    return 1;
40
41
}
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
 
42
62
/*
43
63
 * call-seq:
44
64
 *    parser.parse(yaml)
50
70
 */
51
71
static VALUE parse(VALUE self, VALUE yaml)
52
72
{
53
 
    yaml_parser_t parser;
 
73
    yaml_parser_t * parser;
54
74
    yaml_event_t event;
55
75
    int done = 0;
56
76
    int tainted = 0;
57
77
#ifdef HAVE_RUBY_ENCODING_H
58
 
    int encoding = rb_enc_find_index("ASCII-8BIT");
59
 
    rb_encoding * internal_enc;
 
78
    int encoding = rb_utf8_encindex();
 
79
    rb_encoding * internal_enc = rb_default_internal_encoding();
60
80
#endif
61
81
    VALUE handler = rb_iv_get(self, "@handler");
62
82
 
63
 
 
64
 
    yaml_parser_initialize(&parser);
 
83
    Data_Get_Struct(self, yaml_parser_t, parser);
65
84
 
66
85
    if (OBJ_TAINTED(yaml)) tainted = 1;
67
86
 
68
87
    if(rb_respond_to(yaml, id_read)) {
69
 
        yaml_parser_set_input(&parser, io_reader, (void *)yaml);
 
88
        yaml_parser_set_input(parser, io_reader, (void *)yaml);
70
89
        if (RTEST(rb_obj_is_kind_of(yaml, rb_cIO))) tainted = 1;
71
90
    } else {
72
91
        StringValue(yaml);
73
92
        yaml_parser_set_input_string(
74
 
                &parser,
 
93
                parser,
75
94
                (const unsigned char *)RSTRING_PTR(yaml),
76
95
                (size_t)RSTRING_LEN(yaml)
77
96
                );
78
97
    }
79
98
 
80
99
    while(!done) {
81
 
        if(!yaml_parser_parse(&parser, &event)) {
82
 
            size_t line   = parser.mark.line + 1;
83
 
            size_t column = parser.mark.column;
84
 
 
85
 
            yaml_parser_delete(&parser);
86
 
            rb_raise(ePsychSyntaxError, "couldn't parse YAML at line %d column %d",
 
100
        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>");
 
109
 
 
110
            yaml_parser_delete(parser);
 
111
            yaml_parser_initialize(parser);
 
112
 
 
113
            rb_raise(ePsychSyntaxError, "(%s): couldn't parse YAML at line %d column %d",
 
114
                    StringValuePtr(path),
87
115
                    (int)line, (int)column);
88
116
        }
89
117
 
90
118
        switch(event.type) {
91
119
          case YAML_STREAM_START_EVENT:
92
120
 
93
 
#ifdef HAVE_RUBY_ENCODING_H
94
 
            switch(event.data.stream_start.encoding) {
95
 
              case YAML_ANY_ENCODING:
96
 
                break;
97
 
              case YAML_UTF8_ENCODING:
98
 
                encoding = rb_enc_find_index("UTF-8");
99
 
                break;
100
 
              case YAML_UTF16LE_ENCODING:
101
 
                encoding = rb_enc_find_index("UTF-16LE");
102
 
                break;
103
 
              case YAML_UTF16BE_ENCODING:
104
 
                encoding = rb_enc_find_index("UTF-16BE");
105
 
                break;
106
 
              default:
107
 
                break;
108
 
            }
109
 
            internal_enc = rb_default_internal_encoding();
110
 
#endif
111
 
 
112
121
            rb_funcall(handler, id_start_stream, 1,
113
122
                       INT2NUM((long)event.data.stream_start.encoding)
114
123
                );
301
310
    return self;
302
311
}
303
312
 
 
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
/*
 
337
 * call-seq:
 
338
 *    parser.mark # => #<Psych::Parser::Mark>
 
339
 *
 
340
 * Returns a Psych::Parser::Mark object that contains line, column, and index
 
341
 * information.
 
342
 */
 
343
static VALUE mark(VALUE self)
 
344
{
 
345
    VALUE mark_klass;
 
346
    VALUE args[3];
 
347
    yaml_parser_t * parser;
 
348
 
 
349
    Data_Get_Struct(self, yaml_parser_t, parser);
 
350
    mark_klass = rb_const_get_at(cPsychParser, rb_intern("Mark"));
 
351
    args[0] = INT2NUM(parser->mark.index);
 
352
    args[1] = INT2NUM(parser->mark.line);
 
353
    args[2] = INT2NUM(parser->mark.column);
 
354
 
 
355
    return rb_class_new_instance(3, args, mark_klass);
 
356
}
 
357
 
304
358
void Init_psych_parser()
305
359
{
306
360
#if 0
308
362
#endif
309
363
 
310
364
    cPsychParser = rb_define_class_under(mPsych, "Parser", rb_cObject);
 
365
    rb_define_alloc_func(cPsychParser, allocate);
311
366
 
312
367
    /* Any encoding: Let the parser choose the encoding */
313
368
    rb_define_const(cPsychParser, "ANY", INT2NUM(YAML_ANY_ENCODING));
324
379
    ePsychSyntaxError = rb_define_class_under(mPsych, "SyntaxError", rb_eSyntaxError);
325
380
 
326
381
    rb_define_method(cPsychParser, "parse", parse, 1);
 
382
    rb_define_method(cPsychParser, "mark", mark, 0);
 
383
    rb_define_method(cPsychParser, "external_encoding=", set_external_encoding, 1);
327
384
 
328
385
    id_read           = rb_intern("read");
 
386
    id_path           = rb_intern("path");
329
387
    id_empty          = rb_intern("empty");
330
388
    id_start_stream   = rb_intern("start_stream");
331
389
    id_end_stream     = rb_intern("end_stream");