diff options
Diffstat (limited to 'ext/json/parser/parser.c')
-rw-r--r-- | ext/json/parser/parser.c | 428 |
1 files changed, 230 insertions, 198 deletions
diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c index 29b5674d96..57f87432b6 100644 --- a/ext/json/parser/parser.c +++ b/ext/json/parser/parser.c @@ -99,11 +99,11 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions, i_leftshift, i_new, i_try_convert, i_freeze, i_uminus; -#line 126 "parser.rl" +#line 125 "parser.rl" -#line 108 "parser.c" +#line 107 "parser.c" enum {JSON_object_start = 1}; enum {JSON_object_first_final = 27}; enum {JSON_object_error = 0}; @@ -111,7 +111,7 @@ enum {JSON_object_error = 0}; enum {JSON_object_en_main = 1}; -#line 168 "parser.rl" +#line 167 "parser.rl" static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) @@ -127,14 +127,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class); -#line 132 "parser.c" +#line 131 "parser.c" { cs = JSON_object_start; } -#line 183 "parser.rl" +#line 182 "parser.rl" -#line 139 "parser.c" +#line 138 "parser.c" { if ( p == pe ) goto _test_eof; @@ -162,7 +162,7 @@ case 2: goto st2; goto st0; tr2: -#line 150 "parser.rl" +#line 149 "parser.rl" { char *np; json->parsing_name = 1; @@ -175,7 +175,7 @@ st3: if ( ++p == pe ) goto _test_eof3; case 3: -#line 180 "parser.c" +#line 179 "parser.c" switch( (*p) ) { case 13: goto st3; case 32: goto st3; @@ -242,7 +242,7 @@ case 8: goto st8; goto st0; tr11: -#line 134 "parser.rl" +#line 133 "parser.rl" { VALUE v = Qnil; char *np = JSON_parse_value(json, p, pe, &v, current_nesting); @@ -263,7 +263,7 @@ st9: if ( ++p == pe ) goto _test_eof9; case 9: -#line 268 "parser.c" +#line 267 "parser.c" switch( (*p) ) { case 13: goto st9; case 32: goto st9; @@ -352,14 +352,14 @@ case 18: goto st9; goto st18; tr4: -#line 158 "parser.rl" +#line 157 "parser.rl" { p--; {p++; cs = 27; goto _out;} } goto st27; st27: if ( ++p == pe ) goto _test_eof27; case 27: -#line 364 "parser.c" +#line 363 "parser.c" goto st0; st19: if ( ++p == pe ) @@ -457,7 +457,7 @@ case 26: _out: {} } -#line 184 "parser.rl" +#line 183 "parser.rl" if (cs >= JSON_object_first_final) { if (json->create_additions) { @@ -482,7 +482,7 @@ case 26: -#line 487 "parser.c" +#line 486 "parser.c" enum {JSON_value_start = 1}; enum {JSON_value_first_final = 29}; enum {JSON_value_error = 0}; @@ -490,7 +490,7 @@ enum {JSON_value_error = 0}; enum {JSON_value_en_main = 1}; -#line 284 "parser.rl" +#line 283 "parser.rl" static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) @@ -498,14 +498,14 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul int cs = EVIL; -#line 503 "parser.c" +#line 502 "parser.c" { cs = JSON_value_start; } -#line 291 "parser.rl" +#line 290 "parser.rl" -#line 510 "parser.c" +#line 509 "parser.c" { if ( p == pe ) goto _test_eof; @@ -539,14 +539,14 @@ st0: cs = 0; goto _out; tr2: -#line 236 "parser.rl" +#line 235 "parser.rl" { char *np = JSON_parse_string(json, p, pe, result); if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;} } goto st29; tr3: -#line 241 "parser.rl" +#line 240 "parser.rl" { char *np; if(pe > p + 8 && !strncmp(MinusInfinity, p, 9)) { @@ -555,7 +555,7 @@ tr3: {p = (( p + 10))-1;} p--; {p++; cs = 29; goto _out;} } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p); + rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p); } } np = JSON_parse_float(json, p, pe, result); @@ -566,7 +566,7 @@ tr3: } goto st29; tr7: -#line 259 "parser.rl" +#line 258 "parser.rl" { char *np; np = JSON_parse_array(json, p, pe, result, current_nesting + 1); @@ -574,7 +574,7 @@ tr7: } goto st29; tr11: -#line 265 "parser.rl" +#line 264 "parser.rl" { char *np; np = JSON_parse_object(json, p, pe, result, current_nesting + 1); @@ -582,39 +582,39 @@ tr11: } goto st29; tr25: -#line 229 "parser.rl" +#line 228 "parser.rl" { if (json->allow_nan) { *result = CInfinity; } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8); + rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 7); } } goto st29; tr27: -#line 222 "parser.rl" +#line 221 "parser.rl" { if (json->allow_nan) { *result = CNaN; } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2); + rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 2); } } goto st29; tr31: -#line 216 "parser.rl" +#line 215 "parser.rl" { *result = Qfalse; } goto st29; tr34: -#line 213 "parser.rl" +#line 212 "parser.rl" { *result = Qnil; } goto st29; tr37: -#line 219 "parser.rl" +#line 218 "parser.rl" { *result = Qtrue; } @@ -623,9 +623,9 @@ st29: if ( ++p == pe ) goto _test_eof29; case 29: -#line 271 "parser.rl" +#line 270 "parser.rl" { p--; {p++; cs = 29; goto _out;} } -#line 630 "parser.c" +#line 629 "parser.c" switch( (*p) ) { case 13: goto st29; case 32: goto st29; @@ -866,7 +866,7 @@ case 28: _out: {} } -#line 292 "parser.rl" +#line 291 "parser.rl" if (json->freeze) { OBJ_FREEZE(*result); @@ -880,7 +880,7 @@ case 28: } -#line 885 "parser.c" +#line 884 "parser.c" enum {JSON_integer_start = 1}; enum {JSON_integer_first_final = 3}; enum {JSON_integer_error = 0}; @@ -888,7 +888,7 @@ enum {JSON_integer_error = 0}; enum {JSON_integer_en_main = 1}; -#line 312 "parser.rl" +#line 311 "parser.rl" static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result) @@ -896,15 +896,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res int cs = EVIL; -#line 901 "parser.c" +#line 900 "parser.c" { cs = JSON_integer_start; } -#line 319 "parser.rl" +#line 318 "parser.rl" json->memo = p; -#line 909 "parser.c" +#line 908 "parser.c" { if ( p == pe ) goto _test_eof; @@ -938,14 +938,14 @@ case 3: goto st0; goto tr4; tr4: -#line 309 "parser.rl" +#line 308 "parser.rl" { p--; {p++; cs = 4; goto _out;} } goto st4; st4: if ( ++p == pe ) goto _test_eof4; case 4: -#line 950 "parser.c" +#line 949 "parser.c" goto st0; st5: if ( ++p == pe ) @@ -964,7 +964,7 @@ case 5: _out: {} } -#line 321 "parser.rl" +#line 320 "parser.rl" if (cs >= JSON_integer_first_final) { long len = p - json->memo; @@ -979,7 +979,7 @@ case 5: } -#line 984 "parser.c" +#line 983 "parser.c" enum {JSON_float_start = 1}; enum {JSON_float_first_final = 8}; enum {JSON_float_error = 0}; @@ -987,7 +987,7 @@ enum {JSON_float_error = 0}; enum {JSON_float_en_main = 1}; -#line 346 "parser.rl" +#line 345 "parser.rl" static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result) @@ -995,15 +995,15 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul int cs = EVIL; -#line 1013 "parser.c" +#line 999 "parser.c" { cs = JSON_float_start; } -#line 366 "parser.rl" +#line 352 "parser.rl" json->memo = p; -#line 1021 "parser.c" +#line 1007 "parser.c" { if ( p == pe ) goto _test_eof; @@ -1061,14 +1061,14 @@ case 8: goto st0; goto tr9; tr9: -#line 340 "parser.rl" +#line 339 "parser.rl" { p--; {p++; cs = 9; goto _out;} } goto st9; st9: if ( ++p == pe ) goto _test_eof9; case 9: -#line 1086 "parser.c" +#line 1072 "parser.c" goto st0; st5: if ( ++p == pe ) @@ -1129,7 +1129,7 @@ case 7: _out: {} } -#line 368 "parser.rl" +#line 354 "parser.rl" if (cs >= JSON_float_first_final) { VALUE mod = Qnil; @@ -1180,7 +1180,7 @@ case 7: -#line 1173 "parser.c" +#line 1184 "parser.c" enum {JSON_array_start = 1}; enum {JSON_array_first_final = 17}; enum {JSON_array_error = 0}; @@ -1188,7 +1188,7 @@ enum {JSON_array_error = 0}; enum {JSON_array_en_main = 1}; -#line 421 "parser.rl" +#line 432 "parser.rl" static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) @@ -1202,14 +1202,14 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class); -#line 1195 "parser.c" +#line 1206 "parser.c" { cs = JSON_array_start; } -#line 434 "parser.rl" +#line 445 "parser.rl" -#line 1202 "parser.c" +#line 1213 "parser.c" { if ( p == pe ) goto _test_eof; @@ -1248,7 +1248,7 @@ case 2: goto st2; goto st0; tr2: -#line 398 "parser.rl" +#line 409 "parser.rl" { VALUE v = Qnil; char *np = JSON_parse_value(json, p, pe, &v, current_nesting); @@ -1268,7 +1268,7 @@ st3: if ( ++p == pe ) goto _test_eof3; case 3: -#line 1261 "parser.c" +#line 1272 "parser.c" switch( (*p) ) { case 13: goto st3; case 32: goto st3; @@ -1368,14 +1368,14 @@ case 12: goto st3; goto st12; tr4: -#line 413 "parser.rl" +#line 424 "parser.rl" { p--; {p++; cs = 17; goto _out;} } goto st17; st17: if ( ++p == pe ) goto _test_eof17; case 17: -#line 1368 "parser.c" +#line 1379 "parser.c" goto st0; st13: if ( ++p == pe ) @@ -1431,27 +1431,47 @@ case 16: _out: {} } -#line 435 "parser.rl" +#line 446 "parser.rl" if(cs >= JSON_array_first_final) { return p + 1; } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p); + rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p); return NULL; } } -static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) +static const size_t MAX_STACK_BUFFER_SIZE = 128; +static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize) { - char *p = string, *pe = string, *unescape; + VALUE result = Qnil; + size_t bufferSize = stringEnd - string; + char *p = string, *pe = string, *unescape, *bufferStart, *buffer; int unescape_len; char buf[4]; + if (bufferSize > MAX_STACK_BUFFER_SIZE) { +# ifdef HAVE_RB_ENC_INTERNED_STR + bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1); +# else + bufferStart = buffer = ALLOC_N(char, bufferSize); +# endif + } else { +# ifdef HAVE_RB_ENC_INTERNED_STR + bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1); +# else + bufferStart = buffer = ALLOCA_N(char, bufferSize); +# endif + } + while (pe < stringEnd) { if (*pe == '\\') { unescape = (char *) "?"; unescape_len = 1; - if (pe > p) rb_str_buf_cat(result, p, pe - p); + if (pe > p) { + MEMCPY(buffer, p, char, pe - p); + buffer += pe - p; + } switch (*++pe) { case 'n': unescape = (char *) "\n"; @@ -1476,9 +1496,12 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) break; case 'u': if (pe > stringEnd - 4) { + if (bufferSize > MAX_STACK_BUFFER_SIZE) { + ruby_xfree(bufferStart); + } rb_enc_raise( EXC_ENCODING eParserError, - "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p + "incomplete unicode character escape sequence at '%s'", p ); } else { UTF32 ch = unescape_unicode((unsigned char *) ++pe); @@ -1486,9 +1509,12 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) if (UNI_SUR_HIGH_START == (ch & 0xFC00)) { pe++; if (pe > stringEnd - 6) { + if (bufferSize > MAX_STACK_BUFFER_SIZE) { + ruby_xfree(bufferStart); + } rb_enc_raise( EXC_ENCODING eParserError, - "%u: incomplete surrogate pair at '%s'", __LINE__, p + "incomplete surrogate pair at '%s'", p ); } if (pe[0] == '\\' && pe[1] == 'u') { @@ -1509,18 +1535,60 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) p = pe; continue; } - rb_str_buf_cat(result, unescape, unescape_len); + MEMCPY(buffer, unescape, char, unescape_len); + buffer += unescape_len; p = ++pe; } else { pe++; } } - rb_str_buf_cat(result, p, pe - p); + + if (pe > p) { + MEMCPY(buffer, p, char, pe - p); + buffer += pe - p; + } + +# ifdef HAVE_RB_ENC_INTERNED_STR + if (intern) { + result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding()); + } else { + result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); + } + if (bufferSize > MAX_STACK_BUFFER_SIZE) { + ruby_xfree(bufferStart); + } +# else + result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); + + if (bufferSize > MAX_STACK_BUFFER_SIZE) { + ruby_xfree(bufferStart); + } + + if (intern) { + # if STR_UMINUS_DEDUPE_FROZEN + // Starting from MRI 2.8 it is preferable to freeze the string + // before deduplication so that it can be interned directly + // otherwise it would be duplicated first which is wasteful. + result = rb_funcall(rb_str_freeze(result), i_uminus, 0); + # elif STR_UMINUS_DEDUPE + // MRI 2.5 and older do not deduplicate strings that are already + // frozen. + result = rb_funcall(result, i_uminus, 0); + # else + result = rb_str_freeze(result); + # endif + } +# endif + + if (symbolize) { + result = rb_str_intern(result); + } + return result; } -#line 1513 "parser.c" +#line 1592 "parser.c" enum {JSON_string_start = 1}; enum {JSON_string_first_final = 8}; enum {JSON_string_error = 0}; @@ -1528,7 +1596,7 @@ enum {JSON_string_error = 0}; enum {JSON_string_en_main = 1}; -#line 542 "parser.rl" +#line 620 "parser.rl" static int @@ -1548,17 +1616,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu int cs = EVIL; VALUE match_string; - *result = rb_str_buf_new(0); -#line 1543 "parser.c" +#line 1621 "parser.c" { cs = JSON_string_start; } -#line 563 "parser.rl" +#line 640 "parser.rl" json->memo = p; -#line 1551 "parser.c" +#line 1629 "parser.c" { if ( p == pe ) goto _test_eof; @@ -1579,29 +1646,28 @@ case 2: case 34: goto tr2; case 92: goto st3; } - if ( 0 <= (signed char)(*p) && (*p) <= 31 ) + if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 ) goto st0; goto st2; tr2: -#line 528 "parser.rl" +#line 607 "parser.rl" { - *result = json_string_unescape(*result, json->memo + 1, p); + *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names); if (NIL_P(*result)) { p--; {p++; cs = 8; goto _out;} } else { - FORCE_UTF8(*result); {p = (( p + 1))-1;} } } -#line 539 "parser.rl" +#line 617 "parser.rl" { p--; {p++; cs = 8; goto _out;} } goto st8; st8: if ( ++p == pe ) goto _test_eof8; case 8: -#line 1594 "parser.c" +#line 1671 "parser.c" goto st0; st3: if ( ++p == pe ) @@ -1609,7 +1675,7 @@ st3: case 3: if ( (*p) == 117 ) goto st4; - if ( 0 <= (signed char)(*p) && (*p) <= 31 ) + if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 ) goto st0; goto st2; st4: @@ -1677,7 +1743,7 @@ case 7: _out: {} } -#line 565 "parser.rl" +#line 642 "parser.rl" if (json->create_additions && RTEST(match_string = json->match_string)) { VALUE klass; @@ -1690,26 +1756,6 @@ case 7: } } - if (json->symbolize_names && json->parsing_name) { - *result = rb_str_intern(*result); - } else if (RB_TYPE_P(*result, T_STRING)) { -# if STR_UMINUS_DEDUPE_FROZEN - if (json->freeze) { - // Starting from MRI 2.8 it is preferable to freeze the string - // before deduplication so that it can be interned directly - // otherwise it would be duplicated first which is wasteful. - *result = rb_funcall(rb_str_freeze(*result), i_uminus, 0); - } -# elif STR_UMINUS_DEDUPE - if (json->freeze) { - // MRI 2.5 and older do not deduplicate strings that are already - // frozen. - *result = rb_funcall(*result, i_uminus, 0); - } -# else - rb_str_resize(*result, RSTRING_LEN(*result)); -# endif - } if (cs >= JSON_string_first_final) { return p + 1; } else { @@ -1750,8 +1796,6 @@ static VALUE convert_encoding(VALUE 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: * @@ -1780,98 +1824,85 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) 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 + 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; + } } else { json->max_nesting = 100; json->allow_nan = 0; json->create_additions = 0; - json->create_id = rb_funcall(mJSON, i_create_id, 0); + json->create_id = Qnil; json->object_class = Qnil; json->array_class = Qnil; json->decimal_class = Qnil; @@ -1885,7 +1916,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) } -#line 1878 "parser.c" +#line 1920 "parser.c" enum {JSON_start = 1}; enum {JSON_first_final = 10}; enum {JSON_error = 0}; @@ -1893,7 +1924,7 @@ enum {JSON_error = 0}; enum {JSON_en_main = 1}; -#line 786 "parser.rl" +#line 828 "parser.rl" /* @@ -1901,6 +1932,7 @@ enum {JSON_en_main = 1}; * * Parses the current JSON text _source_ and returns the complete data * structure as a result. + * It raises JSON::ParserError if fail to parse. */ static VALUE cParser_parse(VALUE self) { @@ -1910,16 +1942,16 @@ static VALUE cParser_parse(VALUE self) GET_PARSER; -#line 1903 "parser.c" +#line 1946 "parser.c" { cs = JSON_start; } -#line 802 "parser.rl" +#line 845 "parser.rl" p = json->source; pe = p + json->len; -#line 1912 "parser.c" +#line 1955 "parser.c" { if ( p == pe ) goto _test_eof; @@ -1953,7 +1985,7 @@ st0: cs = 0; goto _out; tr2: -#line 778 "parser.rl" +#line 820 "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;} @@ -1963,7 +1995,7 @@ st10: if ( ++p == pe ) goto _test_eof10; case 10: -#line 1956 "parser.c" +#line 1999 "parser.c" switch( (*p) ) { case 13: goto st10; case 32: goto st10; @@ -2052,12 +2084,12 @@ case 9: _out: {} } -#line 805 "parser.rl" +#line 848 "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); + rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p); return Qnil; } } |