class JSON::Ext::Parser - RDoc Documentation

# class JSON::Ext::Parser

This is the `JSON` parser implemented as a C extension. It can be configured to be used by setting

    JSON.parser = JSON::Ext::Parser

with the method parser= in `JSON`.

### Public Class Methods

new(source, opts → {}) click to toggle source

Creates a new `JSON::Ext::Parser` instance for the string source.

Creates a new `JSON::Ext::Parser` instance for the string source.

It will be configured by the opts hash. opts can have the following keys:

opts can have the following keys:

- max_nesting: The maximum depth of nesting allowed in the parsed data structures. Disable depth checking with :max_nesting => false|nil|0, it defaults to 100.

- allow_nan: If set to true, allow NaN, Infinity and -Infinity in defiance of RFC 4627 to be parsed by the `Parser`. This option defaults to false.

- symbolize_names: If set to true, returns symbols for the names (keys) in a `JSON` object. Otherwise strings are returned, which is also the default. It’s not possible to use this option in conjunction with the create_additions option.

- create_additions: If set to false, the `Parser` doesn’t create additions even if a matching class and create_id was found. This option defaults to false.

- object_class: Defaults to `Hash`

- array_class: Defaults to `Array`

    static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
    {
            VALUE source, opts;
            GET_PARSER_INIT;

            if (json->Vsource) {
                    rb_raise(rb_eTypeError, "already initialized instance");
            }
            #ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
            rb_scan_args(argc, argv, "1:", &source, &opts);
            #else
            rb_scan_args(argc, argv, "11", &source, &opts);
            #endif
            if (!NIL_P(opts)) {
                    #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
                    opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
                    if (NIL_P(opts)) {
                            rb_raise(rb_eArgError, "opts needs to be like a hash");
                    } else {
                            #endif
                            VALUE tmp = ID2SYM(i_max_nesting);
                            if (option_given_p(opts, tmp)) {
                                    VALUE max_nesting = rb_hash_aref(opts, tmp);
                                    if (RTEST(max_nesting)) {
                                            Check_Type(max_nesting, T_FIXNUM);
                                            json->max_nesting = FIX2INT(max_nesting);
                                    } else {
                                            json->max_nesting = 0;
                                    }
                            } else {
                                    json->max_nesting = 100;
                            }
                            tmp = ID2SYM(i_allow_nan);
                            if (option_given_p(opts, tmp)) {
                                    json->allow_nan = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
                            } else {
                                    json->allow_nan = 0;
                            }
                            tmp = ID2SYM(i_symbolize_names);
                            if (option_given_p(opts, tmp)) {
                                    json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
                            } else {
                                    json->symbolize_names = 0;
                            }
                            tmp = ID2SYM(i_freeze);
                            if (option_given_p(opts, tmp)) {
                                    json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
                            } else {
                                    json->freeze = 0;
                            }
                            tmp = ID2SYM(i_create_additions);
                            if (option_given_p(opts, tmp)) {
                                    json->create_additions = RTEST(rb_hash_aref(opts, tmp));
                            } else {
                                    json->create_additions = 0;
                            }
                            if (json->symbolize_names && json->create_additions) {
                                    rb_raise(rb_eArgError,
                                    "options :symbolize_names and :create_additions cannot be "
                                    " used in conjunction");
                            }
                            tmp = ID2SYM(i_create_id);
                            if (option_given_p(opts, tmp)) {
                                    json->create_id = rb_hash_aref(opts, tmp);
                            } else {
                                    json->create_id = rb_funcall(mJSON, i_create_id, 0);
                            }
                            tmp = ID2SYM(i_object_class);
                            if (option_given_p(opts, tmp)) {
                                    json->object_class = rb_hash_aref(opts, tmp);
                            } else {
                                    json->object_class = Qnil;
                            }
                            tmp = ID2SYM(i_array_class);
                            if (option_given_p(opts, tmp)) {
                                    json->array_class = rb_hash_aref(opts, tmp);
                            } else {
                                    json->array_class = Qnil;
                            }
                            tmp = ID2SYM(i_decimal_class);
                            if (option_given_p(opts, tmp)) {
                                    json->decimal_class = rb_hash_aref(opts, tmp);
                            } else {
                                    json->decimal_class = Qnil;
                            }
                            tmp = ID2SYM(i_match_string);
                            if (option_given_p(opts, tmp)) {
                                    VALUE match_string = rb_hash_aref(opts, tmp);
                                    json->match_string = RTEST(match_string) ? match_string : Qnil;
                            } else {
                                    json->match_string = Qnil;
                            }
                            #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
                    }
                    #endif
            } else {
                    json->max_nesting = 100;
                    json->allow_nan = 0;
                    json->create_additions = 0;
                    json->create_id = rb_funcall(mJSON, i_create_id, 0);
                    json->object_class = Qnil;
                    json->array_class = Qnil;
                    json->decimal_class = Qnil;
            }
            source = convert_encoding(StringValue(source));
            StringValue(source);
            json->len = RSTRING_LEN(source);
            json->source = RSTRING_PTR(source);;
            json->Vsource = source;
            return self;
    }

### Public Instance Methods

parse() click to toggle source

Parses the current `JSON` text source and returns the complete data structure as a result.

    static VALUE cParser_parse(VALUE self)
    {
            char *p, *pe;
            int cs = EVIL;
            VALUE result = Qnil;
            GET_PARSER;

            {
                    cs = (int)JSON_start;
            }

            #line 851 "parser.rl"

            p = json->source;
            pe = p + json->len;

            {
                    if ( p == pe )
                    goto _test_eof;
                    switch ( cs )
                    {
                            case 1:
                            goto st_case_1;
                            case 0:
                            goto st_case_0;
                            case 10:
                            goto st_case_10;
                            case 2:
                            goto st_case_2;
                            case 3:
                            goto st_case_3;
                            case 4:
                            goto st_case_4;
                            case 5:
                            goto st_case_5;
                            case 6:
                            goto st_case_6;
                            case 7:
                            goto st_case_7;
                            case 8:
                            goto st_case_8;
                            case 9:
                            goto st_case_9;
                    }
                    goto st_out;
                    st1:
                    p+= 1;
                    if ( p == pe )
                    goto _test_eof1;
                    st_case_1:
                    switch( ( (*( p))) ) {
                            case 13: {
                                    goto st1;
                            }
                            case 32: {
                                    goto st1;
                            }
                            case 34: {
                                    goto ctr2;
                            }
                            case 45: {
                                    goto ctr2;
                            }
                            case 47: {
                                    goto st6;
                            }
                            case 73: {
                                    goto ctr2;
                            }
                            case 78: {
                                    goto ctr2;
                            }
                            case 91: {
                                    goto ctr2;
                            }
                            case 102: {
                                    goto ctr2;
                            }
                            case 110: {
                                    goto ctr2;
                            }
                            case 116: {
                                    goto ctr2;
                            }
                            case 123: {
                                    goto ctr2;
                            }
                    }
                    if ( ( (*( p))) > 10 ) {
                            if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
                                    goto ctr2;
                            }
                    } else if ( ( (*( p))) >= 9 ) {
                            goto st1;
                    }
                    {
                            goto st0;
                    }
                    st_case_0:
                    st0:
                    cs = 0;
                    goto _out;
                    ctr2:
                    {
                            #line 827 "parser.rl"

                            char *np = JSON_parse_value(json, p, pe, &result, 0);
                            if (np == NULL) { {p = p - 1; } {p+= 1; cs = 10; goto _out;} } else {p = (( np))-1;}

                    }

                    goto st10;
                    st10:
                    p+= 1;
                    if ( p == pe )
                    goto _test_eof10;
                    st_case_10:
                    switch( ( (*( p))) ) {
                            case 13: {
                                    goto st10;
                            }
                            case 32: {
                                    goto st10;
                            }
                            case 47: {
                                    goto st2;
                            }
                    }
                    if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) {
                            goto st10;
                    }
                    {
                            goto st0;
                    }
                    st2:
                    p+= 1;
                    if ( p == pe )
                    goto _test_eof2;
                    st_case_2:
                    switch( ( (*( p))) ) {
                            case 42: {
                                    goto st3;
                            }
                            case 47: {
                                    goto st5;
                            }
                    }
                    {
                            goto st0;
                    }
                    st3:
                    p+= 1;
                    if ( p == pe )
                    goto _test_eof3;
                    st_case_3:
                    if ( ( (*( p))) == 42 ) {
                            goto st4;
                    }
                    {
                            goto st3;
                    }
                    st4:
                    p+= 1;
                    if ( p == pe )
                    goto _test_eof4;
                    st_case_4:
                    switch( ( (*( p))) ) {
                            case 42: {
                                    goto st4;
                            }
                            case 47: {
                                    goto st10;
                            }
                    }
                    {
                            goto st3;
                    }
                    st5:
                    p+= 1;
                    if ( p == pe )
                    goto _test_eof5;
                    st_case_5:
                    if ( ( (*( p))) == 10 ) {
                            goto st10;
                    }
                    {
                            goto st5;
                    }
                    st6:
                    p+= 1;
                    if ( p == pe )
                    goto _test_eof6;
                    st_case_6:
                    switch( ( (*( p))) ) {
                            case 42: {
                                    goto st7;
                            }
                            case 47: {
                                    goto st9;
                            }
                    }
                    {
                            goto st0;
                    }
                    st7:
                    p+= 1;
                    if ( p == pe )
                    goto _test_eof7;
                    st_case_7:
                    if ( ( (*( p))) == 42 ) {
                            goto st8;
                    }
                    {
                            goto st7;
                    }
                    st8:
                    p+= 1;
                    if ( p == pe )
                    goto _test_eof8;
                    st_case_8:
                    switch( ( (*( p))) ) {
                            case 42: {
                                    goto st8;
                            }
                            case 47: {
                                    goto st1;
                            }
                    }
                    {
                            goto st7;
                    }
                    st9:
                    p+= 1;
                    if ( p == pe )
                    goto _test_eof9;
                    st_case_9:
                    if ( ( (*( p))) == 10 ) {
                            goto st1;
                    }
                    {
                            goto st9;
                    }
                    st_out:
                    _test_eof1: cs = 1; goto _test_eof;
                    _test_eof10: cs = 10; goto _test_eof;
                    _test_eof2: cs = 2; goto _test_eof;
                    _test_eof3: cs = 3; goto _test_eof;
                    _test_eof4: cs = 4; goto _test_eof;
                    _test_eof5: cs = 5; goto _test_eof;
                    _test_eof6: cs = 6; goto _test_eof;
                    _test_eof7: cs = 7; goto _test_eof;
                    _test_eof8: cs = 8; goto _test_eof;
                    _test_eof9: cs = 9; goto _test_eof;

                    _test_eof: {}
                    _out: {}
            }

            #line 854 "parser.rl"

            if (cs >= JSON_first_final && p == pe) {
                    return result;
            } else {
                    rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
                    return Qnil;
            }
    }

source() click to toggle source

Returns a copy of the current source string, that was used to construct this `Parser`.

    static VALUE cParser_source(VALUE self)
    {
            GET_PARSER;
            return rb_str_dup(json->Vsource);
    }