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
Source
static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) { GET_PARSER_INIT; rb_check_arity(argc, 1, 2); parser_init(json, argv[0], argc == 2 ? argv[1] : Qnil); return self; }
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
. If another type is provided, it will be used instead ofHash
to representJSON
objects. The type must respond tonew
without arguments, and return an object that respond to[]=
. -
array_class: Defaults to
Array
If another type is provided, it will be used instead ofHash
to representJSON
arrays. The type must respond tonew
without arguments, and return an object that respond to +<<+. -
decimal_class: Specifies which class to use instead of the default
(Float) when parsing decimal numbers. This class must accept a single string argument in its constructor.
Source
static VALUE cParser_m_parse(VALUE klass, VALUE source, VALUE opts) { char *p, *pe; int cs = EVIL; VALUE result = Qnil; JSON_Parser _parser = {0}; JSON_Parser *json = &_parser; parser_init(json, source, opts); char stack_buffer[FBUFFER_STACK_SIZE]; fbuffer_stack_init(&json->fbuffer, FBUFFER_INITIAL_LENGTH_DEFAULT, stack_buffer, FBUFFER_STACK_SIZE); VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA]; rvalue_stack stack = { .type = RVALUE_STACK_STACK_ALLOCATED, .ptr = rvalue_stack_buffer, .capa = RVALUE_STACK_INITIAL_CAPA, }; json->stack = &stack; #line 2959 "parser.c" { cs = JSON_start; } #line 1325 "parser.rl" p = json->source; pe = p + json->len; #line 2968 "parser.c" { if ( p == pe ) goto _test_eof; switch ( cs ) { st1: if ( ++p == pe ) goto _test_eof1; case 1: switch( (*p) ) { case 13: goto st1; case 32: goto st1; case 34: goto tr2; case 45: goto tr2; case 47: goto st6; case 73: goto tr2; case 78: goto tr2; case 91: goto tr2; case 102: goto tr2; case 110: goto tr2; case 116: goto tr2; case 123: goto tr2; } if ( (*p) > 10 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr2; } else if ( (*p) >= 9 ) goto st1; goto st0; st0: cs = 0; goto _out; tr2: #line 1251 "parser.rl" { char *np = JSON_parse_value(json, p, pe, &result, 0); if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;} } goto st10; st10: if ( ++p == pe ) goto _test_eof10; case 10: #line 3012 "parser.c" switch( (*p) ) { case 13: goto st10; case 32: goto st10; case 47: goto st2; } if ( 9 <= (*p) && (*p) <= 10 ) goto st10; goto st0; st2: if ( ++p == pe ) goto _test_eof2; case 2: switch( (*p) ) { case 42: goto st3; case 47: goto st5; } goto st0; st3: if ( ++p == pe ) goto _test_eof3; case 3: if ( (*p) == 42 ) goto st4; goto st3; st4: if ( ++p == pe ) goto _test_eof4; case 4: switch( (*p) ) { case 42: goto st4; case 47: goto st10; } goto st3; st5: if ( ++p == pe ) goto _test_eof5; case 5: if ( (*p) == 10 ) goto st10; goto st5; st6: if ( ++p == pe ) goto _test_eof6; case 6: switch( (*p) ) { case 42: goto st7; case 47: goto st9; } goto st0; st7: if ( ++p == pe ) goto _test_eof7; case 7: if ( (*p) == 42 ) goto st8; goto st7; st8: if ( ++p == pe ) goto _test_eof8; case 8: switch( (*p) ) { case 42: goto st8; case 47: goto st1; } goto st7; st9: if ( ++p == pe ) goto _test_eof9; case 9: if ( (*p) == 10 ) goto st1; goto st9; } _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 1328 "parser.rl" if (json->stack_handle) { rvalue_stack_eagerly_release(json->stack_handle); } if (cs >= JSON_first_final && p == pe) { return result; } else { raise_parse_error("unexpected token at '%s'", p); return Qnil; } }
Public Instance Methods
Source
static VALUE cParser_parse(VALUE self) { char *p, *pe; int cs = EVIL; VALUE result = Qnil; GET_PARSER; char stack_buffer[FBUFFER_STACK_SIZE]; fbuffer_stack_init(&json->fbuffer, FBUFFER_INITIAL_LENGTH_DEFAULT, stack_buffer, FBUFFER_STACK_SIZE); VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA]; rvalue_stack stack = { .type = RVALUE_STACK_STACK_ALLOCATED, .ptr = rvalue_stack_buffer, .capa = RVALUE_STACK_INITIAL_CAPA, }; json->stack = &stack; #line 2781 "parser.c" { cs = JSON_start; } #line 1287 "parser.rl" p = json->source; pe = p + json->len; #line 2790 "parser.c" { if ( p == pe ) goto _test_eof; switch ( cs ) { st1: if ( ++p == pe ) goto _test_eof1; case 1: switch( (*p) ) { case 13: goto st1; case 32: goto st1; case 34: goto tr2; case 45: goto tr2; case 47: goto st6; case 73: goto tr2; case 78: goto tr2; case 91: goto tr2; case 102: goto tr2; case 110: goto tr2; case 116: goto tr2; case 123: goto tr2; } if ( (*p) > 10 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr2; } else if ( (*p) >= 9 ) goto st1; goto st0; st0: cs = 0; goto _out; tr2: #line 1251 "parser.rl" { char *np = JSON_parse_value(json, p, pe, &result, 0); if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;} } goto st10; st10: if ( ++p == pe ) goto _test_eof10; case 10: #line 2834 "parser.c" switch( (*p) ) { case 13: goto st10; case 32: goto st10; case 47: goto st2; } if ( 9 <= (*p) && (*p) <= 10 ) goto st10; goto st0; st2: if ( ++p == pe ) goto _test_eof2; case 2: switch( (*p) ) { case 42: goto st3; case 47: goto st5; } goto st0; st3: if ( ++p == pe ) goto _test_eof3; case 3: if ( (*p) == 42 ) goto st4; goto st3; st4: if ( ++p == pe ) goto _test_eof4; case 4: switch( (*p) ) { case 42: goto st4; case 47: goto st10; } goto st3; st5: if ( ++p == pe ) goto _test_eof5; case 5: if ( (*p) == 10 ) goto st10; goto st5; st6: if ( ++p == pe ) goto _test_eof6; case 6: switch( (*p) ) { case 42: goto st7; case 47: goto st9; } goto st0; st7: if ( ++p == pe ) goto _test_eof7; case 7: if ( (*p) == 42 ) goto st8; goto st7; st8: if ( ++p == pe ) goto _test_eof8; case 8: switch( (*p) ) { case 42: goto st8; case 47: goto st1; } goto st7; st9: if ( ++p == pe ) goto _test_eof9; case 9: if ( (*p) == 10 ) goto st1; goto st9; } _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 1290 "parser.rl" if (json->stack_handle) { rvalue_stack_eagerly_release(json->stack_handle); } if (cs >= JSON_first_final && p == pe) { return result; } else { raise_parse_error("unexpected token at '%s'", p); return Qnil; } }
Parses the current JSON
text source and returns the complete data structure as a result. It raises JSON::ParserError
if fail to parse.