| Class | JSON::Ext::Parser |
| In: |
ext/json/ext/parser/parser.c
|
| Parent: | Object |
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:
/*
* call-seq: new(source, opts => {})
*
* 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 19.
* * *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.
* * *create_additions*: If set to false, the Parser doesn't create
* additions even if a matchin class and create_id was found. This option
* defaults to true.
*/
static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
{
char *ptr;
long len;
VALUE source, opts;
GET_STRUCT;
rb_scan_args(argc, argv, "11", &source, &opts);
source = StringValue(source);
ptr = RSTRING_PTR(source);
len = RSTRING_LEN(source);
if (len < 2) {
rb_raise(eParserError, "A JSON text must at least contain two octets!");
}
if (!NIL_P(opts)) {
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 {
VALUE tmp = ID2SYM(i_max_nesting);
if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
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 = 19;
}
tmp = ID2SYM(i_allow_nan);
if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
VALUE allow_nan = rb_hash_aref(opts, tmp);
json->allow_nan = RTEST(allow_nan) ? 1 : 0;
} else {
json->allow_nan = 0;
}
tmp = ID2SYM(i_create_additions);
if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
VALUE create_additions = rb_hash_aref(opts, tmp);
if (RTEST(create_additions)) {
json->create_id = rb_funcall(mJSON, i_create_id, 0);
} else {
json->create_id = Qnil;
}
} else {
json->create_id = rb_funcall(mJSON, i_create_id, 0);
}
}
} else {
json->max_nesting = 19;
json->allow_nan = 0;
json->create_id = rb_funcall(mJSON, i_create_id, 0);
}
json->current_nesting = 0;
/*
Convert these?
if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
} else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
} else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
} else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
}
*/
json->len = len;
json->source = ptr;
json->Vsource = source;
return self;
}
Parses the current JSON text source and returns the complete data structure as a result.
/*
* call-seq: parse()
*
* 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_STRUCT;
#line 1545 "parser.c"
{
cs = JSON_start;
}
#line 569 "parser.rl"
p = json->source;
pe = p + json->len;
#line 1553 "parser.c"
{
if ( p == pe )
goto _out;
switch ( cs )
{
st1:
if ( ++p == pe )
goto _out1;
case 1:
switch( (*p) ) {
case 13: goto st1;
case 32: goto st1;
case 47: goto st2;
case 91: goto tr3;
case 123: goto tr4;
}
if ( 9 <= (*p) && (*p) <= 10 )
goto st1;
goto st0;
st0:
goto _out0;
st2:
if ( ++p == pe )
goto _out2;
case 2:
switch( (*p) ) {
case 42: goto st3;
case 47: goto st5;
}
goto st0;
st3:
if ( ++p == pe )
goto _out3;
case 3:
if ( (*p) == 42 )
goto st4;
goto st3;
st4:
if ( ++p == pe )
goto _out4;
case 4:
switch( (*p) ) {
case 42: goto st4;
case 47: goto st1;
}
goto st3;
st5:
if ( ++p == pe )
goto _out5;
case 5:
if ( (*p) == 10 )
goto st1;
goto st5;
tr3:
#line 436 "parser.rl"
{
char *np;
json->current_nesting = 1;
np = JSON_parse_array(json, p, pe, &result);
if (np == NULL) goto _out10; else {p = (( np))-1;}
}
goto st10;
tr4:
#line 429 "parser.rl"
{
char *np;
json->current_nesting = 1;
np = JSON_parse_object(json, p, pe, &result);
if (np == NULL) goto _out10; else {p = (( np))-1;}
}
goto st10;
st10:
if ( ++p == pe )
goto _out10;
case 10:
#line 1629 "parser.c"
switch( (*p) ) {
case 13: goto st10;
case 32: goto st10;
case 47: goto st6;
}
if ( 9 <= (*p) && (*p) <= 10 )
goto st10;
goto st0;
st6:
if ( ++p == pe )
goto _out6;
case 6:
switch( (*p) ) {
case 42: goto st7;
case 47: goto st9;
}
goto st0;
st7:
if ( ++p == pe )
goto _out7;
case 7:
if ( (*p) == 42 )
goto st8;
goto st7;
st8:
if ( ++p == pe )
goto _out8;
case 8:
switch( (*p) ) {
case 42: goto st8;
case 47: goto st10;
}
goto st7;
st9:
if ( ++p == pe )
goto _out9;
case 9:
if ( (*p) == 10 )
goto st10;
goto st9;
}
_out1: cs = 1; goto _out;
_out0: cs = 0; goto _out;
_out2: cs = 2; goto _out;
_out3: cs = 3; goto _out;
_out4: cs = 4; goto _out;
_out5: cs = 5; goto _out;
_out10: cs = 10; goto _out;
_out6: cs = 6; goto _out;
_out7: cs = 7; goto _out;
_out8: cs = 8; goto _out;
_out9: cs = 9; goto _out;
_out: {}
}
#line 572 "parser.rl"
if (cs >= JSON_first_final && p == pe) {
return result;
} else {
rb_raise(eParserError, "unexpected token at '%s'", p);
}
}