vendor/json_pure/ext/json/ext/parser/parser.c in scout-5.6.7 vs vendor/json_pure/ext/json/ext/parser/parser.c in scout-5.6.8.pre

- old
+ new

@@ -1,12 +1,13 @@ #line 1 "parser.rl" +#include "../fbuffer/fbuffer.h" #include "parser.h" /* unicode */ -static const char digit_values[256] = { +static const char digit_values[256] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -38,11 +39,11 @@ result = (result << 4) | b; if (b < 0) return UNI_REPLACEMENT_CHAR; return result; } -static int convert_UTF32_to_UTF8(char *buf, UTF32 ch) +static int convert_UTF32_to_UTF8(char *buf, UTF32 ch) { int len = 1; if (ch <= 0x7F) { buf[0] = (char) ch; } else if (ch <= 0x07FF) { @@ -67,36 +68,37 @@ } #ifdef HAVE_RUBY_ENCODING_H static VALUE CEncoding_ASCII_8BIT, CEncoding_UTF_8, CEncoding_UTF_16BE, CEncoding_UTF_16LE, CEncoding_UTF_32BE, CEncoding_UTF_32LE; -static ID i_encoding, i_encode, i_encode_bang, i_force_encoding; +static ID i_encoding, i_encode; #else static ID i_iconv; #endif static VALUE mJSON, mExt, cParser, eParserError, eNestingError; static VALUE CNaN, CInfinity, CMinusInfinity; static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions, - i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_object_class, - i_array_class, i_key_p, i_deep_const_get; + i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_quirks_mode, + i_object_class, i_array_class, i_key_p, i_deep_const_get, i_match, + i_match_string, i_aset, i_aref, i_leftshift; -#line 108 "parser.rl" +#line 110 "parser.rl" -#line 90 "parser.c" +#line 92 "parser.c" static const int JSON_object_start = 1; static const int JSON_object_first_final = 27; static const int JSON_object_error = 0; static const int JSON_object_en_main = 1; -#line 143 "parser.rl" +#line 151 "parser.rl" static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result) { int cs = EVIL; @@ -107,19 +109,19 @@ rb_raise(eNestingError, "nesting of %d is too deep", json->current_nesting); } *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class); - -#line 114 "parser.c" + +#line 116 "parser.c" { cs = JSON_object_start; } -#line 158 "parser.rl" - -#line 121 "parser.c" +#line 166 "parser.rl" + +#line 123 "parser.c" { if ( p == pe ) goto _test_eof; switch ( cs ) { @@ -143,11 +145,11 @@ } if ( 9 <= (*p) && (*p) <= 10 ) goto st2; goto st0; tr2: -#line 127 "parser.rl" +#line 133 "parser.rl" { char *np; json->parsing_name = 1; np = JSON_parse_string(json, p, pe, &last_name); json->parsing_name = 0; @@ -156,11 +158,11 @@ goto st3; st3: if ( ++p == pe ) goto _test_eof3; case 3: -#line 161 "parser.c" +#line 164 "parser.c" switch( (*p) ) { case 13: goto st3; case 32: goto st3; case 47: goto st4; case 58: goto st8; @@ -223,27 +225,31 @@ goto tr11; } else if ( (*p) >= 9 ) goto st8; goto st0; tr11: -#line 116 "parser.rl" +#line 118 "parser.rl" { VALUE v = Qnil; - char *np = JSON_parse_value(json, p, pe, &v); + char *np = JSON_parse_value(json, p, pe, &v); if (np == NULL) { p--; {p++; cs = 9; goto _out;} } else { - rb_hash_aset(*result, last_name, v); + if (NIL_P(json->object_class)) { + rb_hash_aset(*result, last_name, v); + } else { + rb_funcall(*result, i_aset, 2, last_name, v); + } {p = (( np))-1;} } } goto st9; st9: if ( ++p == pe ) goto _test_eof9; case 9: -#line 244 "parser.c" +#line 251 "parser.c" switch( (*p) ) { case 13: goto st9; case 32: goto st9; case 44: goto st10; case 47: goto st15; @@ -328,18 +334,18 @@ case 18: if ( (*p) == 10 ) goto st9; goto st18; tr4: -#line 134 "parser.rl" +#line 141 "parser.rl" { p--; {p++; cs = 27; goto _out;} } goto st27; st27: if ( ++p == pe ) goto _test_eof27; case 27: -#line 340 "parser.c" +#line 347 "parser.c" goto st0; st19: if ( ++p == pe ) goto _test_eof19; case 19: @@ -402,49 +408,54 @@ case 26: if ( (*p) == 10 ) goto st2; goto st26; } - _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_eof10: cs = 10; goto _test_eof; - _test_eof11: cs = 11; goto _test_eof; - _test_eof12: cs = 12; goto _test_eof; - _test_eof13: cs = 13; goto _test_eof; - _test_eof14: cs = 14; goto _test_eof; - _test_eof15: cs = 15; goto _test_eof; - _test_eof16: cs = 16; goto _test_eof; - _test_eof17: cs = 17; goto _test_eof; - _test_eof18: cs = 18; goto _test_eof; - _test_eof27: cs = 27; goto _test_eof; - _test_eof19: cs = 19; goto _test_eof; - _test_eof20: cs = 20; goto _test_eof; - _test_eof21: cs = 21; goto _test_eof; - _test_eof22: cs = 22; goto _test_eof; - _test_eof23: cs = 23; goto _test_eof; - _test_eof24: cs = 24; goto _test_eof; - _test_eof25: cs = 25; goto _test_eof; - _test_eof26: cs = 26; 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_eof10: cs = 10; goto _test_eof; + _test_eof11: cs = 11; goto _test_eof; + _test_eof12: cs = 12; goto _test_eof; + _test_eof13: cs = 13; goto _test_eof; + _test_eof14: cs = 14; goto _test_eof; + _test_eof15: cs = 15; goto _test_eof; + _test_eof16: cs = 16; goto _test_eof; + _test_eof17: cs = 17; goto _test_eof; + _test_eof18: cs = 18; goto _test_eof; + _test_eof27: cs = 27; goto _test_eof; + _test_eof19: cs = 19; goto _test_eof; + _test_eof20: cs = 20; goto _test_eof; + _test_eof21: cs = 21; goto _test_eof; + _test_eof22: cs = 22; goto _test_eof; + _test_eof23: cs = 23; goto _test_eof; + _test_eof24: cs = 24; goto _test_eof; + _test_eof25: cs = 25; goto _test_eof; + _test_eof26: cs = 26; goto _test_eof; _test_eof: {} _out: {} } -#line 159 "parser.rl" +#line 167 "parser.rl" if (cs >= JSON_object_first_final) { - if (RTEST(json->create_id)) { - VALUE klassname = rb_hash_aref(*result, json->create_id); + if (json->create_additions) { + VALUE klassname; + if (NIL_P(json->object_class)) { + klassname = rb_hash_aref(*result, json->create_id); + } else { + klassname = rb_funcall(*result, i_aref, 1, json->create_id); + } if (!NIL_P(klassname)) { VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname); - if RTEST(rb_funcall(klass, i_json_creatable_p, 0)) { + if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) { *result = rb_funcall(klass, i_json_create, 1, *result); } } } return p + 1; @@ -452,34 +463,35 @@ return NULL; } } -#line 457 "parser.c" + +#line 470 "parser.c" static const int JSON_value_start = 1; static const int JSON_value_first_final = 21; static const int JSON_value_error = 0; static const int JSON_value_en_main = 1; -#line 257 "parser.rl" +#line 271 "parser.rl" static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result) { int cs = EVIL; - -#line 473 "parser.c" + +#line 486 "parser.c" { cs = JSON_value_start; } -#line 264 "parser.rl" - -#line 480 "parser.c" +#line 278 "parser.rl" + +#line 493 "parser.c" { if ( p == pe ) goto _test_eof; switch ( cs ) { @@ -500,21 +512,21 @@ goto st0; st0: cs = 0; goto _out; tr0: -#line 205 "parser.rl" +#line 219 "parser.rl" { char *np = JSON_parse_string(json, p, pe, result); if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;} } goto st21; tr2: -#line 210 "parser.rl" +#line 224 "parser.rl" { char *np; - if(pe > p + 9 && !strncmp(MinusInfinity, p, 9)) { + if(pe > p + 9 - json->quirks_mode && !strncmp(MinusInfinity, p, 9)) { if (json->allow_nan) { *result = CMinusInfinity; {p = (( p + 10))-1;} p--; {p++; cs = 21; goto _out;} } else { @@ -527,74 +539,74 @@ if (np != NULL) {p = (( np))-1;} p--; {p++; cs = 21; goto _out;} } goto st21; tr5: -#line 228 "parser.rl" - { +#line 242 "parser.rl" + { char *np; json->current_nesting++; np = JSON_parse_array(json, p, pe, result); json->current_nesting--; if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;} } goto st21; tr9: -#line 236 "parser.rl" - { +#line 250 "parser.rl" + { char *np; json->current_nesting++; np = JSON_parse_object(json, p, pe, result); json->current_nesting--; if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;} } goto st21; tr16: -#line 198 "parser.rl" +#line 212 "parser.rl" { if (json->allow_nan) { *result = CInfinity; } else { rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8); } } goto st21; tr18: -#line 191 "parser.rl" +#line 205 "parser.rl" { if (json->allow_nan) { *result = CNaN; } else { rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2); } } goto st21; tr22: -#line 185 "parser.rl" +#line 199 "parser.rl" { *result = Qfalse; } goto st21; tr25: -#line 182 "parser.rl" +#line 196 "parser.rl" { *result = Qnil; } goto st21; tr28: -#line 188 "parser.rl" +#line 202 "parser.rl" { *result = Qtrue; } goto st21; st21: if ( ++p == pe ) goto _test_eof21; case 21: -#line 244 "parser.rl" +#line 258 "parser.rl" { p--; {p++; cs = 21; goto _out;} } -#line 595 "parser.c" +#line 608 "parser.c" goto st0; st2: if ( ++p == pe ) goto _test_eof2; case 2: @@ -726,70 +738,70 @@ case 20: if ( (*p) == 101 ) goto tr28; goto st0; } - _test_eof21: cs = 21; 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_eof10: cs = 10; goto _test_eof; - _test_eof11: cs = 11; goto _test_eof; - _test_eof12: cs = 12; goto _test_eof; - _test_eof13: cs = 13; goto _test_eof; - _test_eof14: cs = 14; goto _test_eof; - _test_eof15: cs = 15; goto _test_eof; - _test_eof16: cs = 16; goto _test_eof; - _test_eof17: cs = 17; goto _test_eof; - _test_eof18: cs = 18; goto _test_eof; - _test_eof19: cs = 19; goto _test_eof; - _test_eof20: cs = 20; goto _test_eof; + _test_eof21: cs = 21; 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_eof10: cs = 10; goto _test_eof; + _test_eof11: cs = 11; goto _test_eof; + _test_eof12: cs = 12; goto _test_eof; + _test_eof13: cs = 13; goto _test_eof; + _test_eof14: cs = 14; goto _test_eof; + _test_eof15: cs = 15; goto _test_eof; + _test_eof16: cs = 16; goto _test_eof; + _test_eof17: cs = 17; goto _test_eof; + _test_eof18: cs = 18; goto _test_eof; + _test_eof19: cs = 19; goto _test_eof; + _test_eof20: cs = 20; goto _test_eof; _test_eof: {} _out: {} } -#line 265 "parser.rl" +#line 279 "parser.rl" if (cs >= JSON_value_first_final) { return p; } else { return NULL; } } -#line 766 "parser.c" +#line 779 "parser.c" static const int JSON_integer_start = 1; -static const int JSON_integer_first_final = 5; +static const int JSON_integer_first_final = 3; static const int JSON_integer_error = 0; static const int JSON_integer_en_main = 1; -#line 281 "parser.rl" +#line 295 "parser.rl" static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result) { int cs = EVIL; - -#line 782 "parser.c" + +#line 795 "parser.c" { cs = JSON_integer_start; } -#line 288 "parser.rl" +#line 302 "parser.rl" json->memo = p; - -#line 790 "parser.c" + +#line 803 "parser.c" { if ( p == pe ) goto _test_eof; switch ( cs ) { @@ -797,11 +809,11 @@ switch( (*p) ) { case 45: goto st2; case 48: goto st3; } if ( 49 <= (*p) && (*p) <= 57 ) - goto st4; + goto st5; goto st0; st0: cs = 0; goto _out; st2: @@ -809,83 +821,86 @@ goto _test_eof2; case 2: if ( (*p) == 48 ) goto st3; if ( 49 <= (*p) && (*p) <= 57 ) - goto st4; + goto st5; goto st0; st3: if ( ++p == pe ) goto _test_eof3; case 3: if ( 48 <= (*p) && (*p) <= 57 ) goto st0; goto tr4; tr4: -#line 278 "parser.rl" - { p--; {p++; cs = 5; goto _out;} } - goto st5; -st5: - if ( ++p == pe ) - goto _test_eof5; -case 5: -#line 831 "parser.c" - goto st0; +#line 292 "parser.rl" + { p--; {p++; cs = 4; goto _out;} } + goto st4; st4: if ( ++p == pe ) goto _test_eof4; case 4: +#line 844 "parser.c" + goto st0; +st5: + if ( ++p == pe ) + goto _test_eof5; +case 5: if ( 48 <= (*p) && (*p) <= 57 ) - goto st4; + goto st5; goto tr4; } - _test_eof2: cs = 2; goto _test_eof; - _test_eof3: cs = 3; goto _test_eof; - _test_eof5: cs = 5; goto _test_eof; - _test_eof4: cs = 4; 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_eof: {} _out: {} } -#line 290 "parser.rl" +#line 304 "parser.rl" if (cs >= JSON_integer_first_final) { long len = p - json->memo; - *result = rb_Integer(rb_str_new(json->memo, len)); + fbuffer_clear(json->fbuffer); + fbuffer_append(json->fbuffer, json->memo, len); + fbuffer_append_char(json->fbuffer, '\0'); + *result = rb_cstr2inum(FBUFFER_PTR(json->fbuffer), 10); return p + 1; } else { return NULL; } } -#line 862 "parser.c" +#line 878 "parser.c" static const int JSON_float_start = 1; -static const int JSON_float_first_final = 10; +static const int JSON_float_first_final = 8; static const int JSON_float_error = 0; static const int JSON_float_en_main = 1; -#line 312 "parser.rl" +#line 329 "parser.rl" static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result) { int cs = EVIL; - -#line 878 "parser.c" + +#line 894 "parser.c" { cs = JSON_float_start; } -#line 319 "parser.rl" +#line 336 "parser.rl" json->memo = p; - -#line 886 "parser.c" + +#line 902 "parser.c" { if ( p == pe ) goto _test_eof; switch ( cs ) { @@ -893,11 +908,11 @@ switch( (*p) ) { case 45: goto st2; case 48: goto st3; } if ( 49 <= (*p) && (*p) <= 57 ) - goto st9; + goto st7; goto st0; st0: cs = 0; goto _out; st2: @@ -905,134 +920,137 @@ goto _test_eof2; case 2: if ( (*p) == 48 ) goto st3; if ( 49 <= (*p) && (*p) <= 57 ) - goto st9; + goto st7; goto st0; st3: if ( ++p == pe ) goto _test_eof3; case 3: switch( (*p) ) { case 46: goto st4; - case 69: goto st6; - case 101: goto st6; + case 69: goto st5; + case 101: goto st5; } goto st0; st4: if ( ++p == pe ) goto _test_eof4; case 4: if ( 48 <= (*p) && (*p) <= 57 ) - goto st5; + goto st8; goto st0; -st5: +st8: if ( ++p == pe ) - goto _test_eof5; -case 5: + goto _test_eof8; +case 8: switch( (*p) ) { - case 69: goto st6; - case 101: goto st6; + case 69: goto st5; + case 101: goto st5; } if ( (*p) > 46 ) { if ( 48 <= (*p) && (*p) <= 57 ) - goto st5; + goto st8; } else if ( (*p) >= 45 ) goto st0; - goto tr7; -tr7: -#line 306 "parser.rl" - { p--; {p++; cs = 10; goto _out;} } - goto st10; -st10: + goto tr9; +tr9: +#line 323 "parser.rl" + { p--; {p++; cs = 9; goto _out;} } + goto st9; +st9: if ( ++p == pe ) - goto _test_eof10; -case 10: -#line 951 "parser.c" + goto _test_eof9; +case 9: +#line 967 "parser.c" goto st0; -st6: +st5: if ( ++p == pe ) - goto _test_eof6; -case 6: + goto _test_eof5; +case 5: switch( (*p) ) { - case 43: goto st7; - case 45: goto st7; + case 43: goto st6; + case 45: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) - goto st8; + goto st10; goto st0; -st7: +st6: if ( ++p == pe ) - goto _test_eof7; -case 7: + goto _test_eof6; +case 6: if ( 48 <= (*p) && (*p) <= 57 ) - goto st8; + goto st10; goto st0; -st8: +st10: if ( ++p == pe ) - goto _test_eof8; -case 8: + goto _test_eof10; +case 10: switch( (*p) ) { case 69: goto st0; case 101: goto st0; } if ( (*p) > 46 ) { if ( 48 <= (*p) && (*p) <= 57 ) - goto st8; + goto st10; } else if ( (*p) >= 45 ) goto st0; - goto tr7; -st9: + goto tr9; +st7: if ( ++p == pe ) - goto _test_eof9; -case 9: + goto _test_eof7; +case 7: switch( (*p) ) { case 46: goto st4; - case 69: goto st6; - case 101: goto st6; + case 69: goto st5; + case 101: goto st5; } if ( 48 <= (*p) && (*p) <= 57 ) - goto st9; + goto st7; goto st0; } - _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_eof10: cs = 10; 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_eof2: cs = 2; goto _test_eof; + _test_eof3: cs = 3; goto _test_eof; + _test_eof4: cs = 4; goto _test_eof; + _test_eof8: cs = 8; goto _test_eof; + _test_eof9: cs = 9; goto _test_eof; + _test_eof5: cs = 5; goto _test_eof; + _test_eof6: cs = 6; goto _test_eof; + _test_eof10: cs = 10; goto _test_eof; + _test_eof7: cs = 7; goto _test_eof; _test_eof: {} _out: {} } -#line 321 "parser.rl" +#line 338 "parser.rl" if (cs >= JSON_float_first_final) { long len = p - json->memo; - *result = rb_Float(rb_str_new(json->memo, len)); + fbuffer_clear(json->fbuffer); + fbuffer_append(json->fbuffer, json->memo, len); + fbuffer_append_char(json->fbuffer, '\0'); + *result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1)); return p + 1; } else { return NULL; } } -#line 1025 "parser.c" +#line 1044 "parser.c" static const int JSON_array_start = 1; static const int JSON_array_first_final = 17; static const int JSON_array_error = 0; static const int JSON_array_en_main = 1; -#line 357 "parser.rl" +#line 381 "parser.rl" static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result) { int cs = EVIL; @@ -1041,19 +1059,19 @@ if (json->max_nesting && json->current_nesting > json->max_nesting) { rb_raise(eNestingError, "nesting of %d is too deep", json->current_nesting); } *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class); - -#line 1047 "parser.c" + +#line 1066 "parser.c" { cs = JSON_array_start; } -#line 370 "parser.rl" - -#line 1054 "parser.c" +#line 394 "parser.rl" + +#line 1073 "parser.c" { if ( p == pe ) goto _test_eof; switch ( cs ) { @@ -1088,27 +1106,31 @@ goto tr2; } else if ( (*p) >= 9 ) goto st2; goto st0; tr2: -#line 338 "parser.rl" +#line 358 "parser.rl" { VALUE v = Qnil; - char *np = JSON_parse_value(json, p, pe, &v); + char *np = JSON_parse_value(json, p, pe, &v); if (np == NULL) { p--; {p++; cs = 3; goto _out;} } else { - rb_ary_push(*result, v); + if (NIL_P(json->array_class)) { + rb_ary_push(*result, v); + } else { + rb_funcall(*result, i_leftshift, 1, v); + } {p = (( np))-1;} } } goto st3; st3: if ( ++p == pe ) goto _test_eof3; case 3: -#line 1109 "parser.c" +#line 1132 "parser.c" switch( (*p) ) { case 13: goto st3; case 32: goto st3; case 44: goto st4; case 47: goto st9; @@ -1204,18 +1226,18 @@ case 12: if ( (*p) == 10 ) goto st3; goto st12; tr4: -#line 349 "parser.rl" +#line 373 "parser.rl" { p--; {p++; cs = 17; goto _out;} } goto st17; st17: if ( ++p == pe ) goto _test_eof17; case 17: -#line 1216 "parser.c" +#line 1239 "parser.c" goto st0; st13: if ( ++p == pe ) goto _test_eof13; case 13: @@ -1246,32 +1268,32 @@ case 16: if ( (*p) == 10 ) goto st2; goto st16; } - _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_eof10: cs = 10; goto _test_eof; - _test_eof11: cs = 11; goto _test_eof; - _test_eof12: cs = 12; goto _test_eof; - _test_eof17: cs = 17; goto _test_eof; - _test_eof13: cs = 13; goto _test_eof; - _test_eof14: cs = 14; goto _test_eof; - _test_eof15: cs = 15; goto _test_eof; - _test_eof16: cs = 16; 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_eof10: cs = 10; goto _test_eof; + _test_eof11: cs = 11; goto _test_eof; + _test_eof12: cs = 12; goto _test_eof; + _test_eof17: cs = 17; goto _test_eof; + _test_eof13: cs = 13; goto _test_eof; + _test_eof14: cs = 14; goto _test_eof; + _test_eof15: cs = 15; goto _test_eof; + _test_eof16: cs = 16; goto _test_eof; _test_eof: {} _out: {} } -#line 371 "parser.rl" +#line 395 "parser.rl" if(cs >= JSON_array_first_final) { return p + 1; } else { rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p); @@ -1281,10 +1303,11 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) { char *p = string, *pe = string, *unescape; int unescape_len; + char buf[4]; while (pe < stringEnd) { if (*pe == '\\') { unescape = (char *) "?"; unescape_len = 1; @@ -1310,14 +1333,13 @@ break; case 'f': unescape = (char *) "\f"; break; case 'u': - if (pe > stringEnd - 4) { + if (pe > stringEnd - 4) { return Qnil; } else { - char buf[4]; UTF32 ch = unescape_unicode((unsigned char *) ++pe); pe += 3; if (UNI_SUR_HIGH_START == (ch & 0xFC00)) { pe++; if (pe > stringEnd - 6) return Qnil; @@ -1348,36 +1370,49 @@ rb_str_buf_cat(result, p, pe - p); return result; } -#line 1353 "parser.c" +#line 1376 "parser.c" static const int JSON_string_start = 1; static const int JSON_string_first_final = 8; static const int JSON_string_error = 0; static const int JSON_string_en_main = 1; -#line 470 "parser.rl" +#line 494 "parser.rl" +static int +match_i(VALUE regexp, VALUE klass, VALUE memo) +{ + if (regexp == Qundef) return ST_STOP; + if (RTEST(rb_funcall(klass, i_json_creatable_p, 0)) && + RTEST(rb_funcall(regexp, i_match, 1, rb_ary_entry(memo, 0)))) { + rb_ary_push(memo, klass); + return ST_STOP; + } + return ST_CONTINUE; +} + static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result) { int cs = EVIL; + VALUE match_string; *result = rb_str_buf_new(0); - -#line 1370 "parser.c" + +#line 1406 "parser.c" { cs = JSON_string_start; } -#line 478 "parser.rl" +#line 515 "parser.rl" json->memo = p; - -#line 1378 "parser.c" + +#line 1414 "parser.c" { if ( p == pe ) goto _test_eof; switch ( cs ) { @@ -1398,29 +1433,29 @@ } if ( 0 <= (*p) && (*p) <= 31 ) goto st0; goto st2; tr2: -#line 456 "parser.rl" +#line 480 "parser.rl" { *result = json_string_unescape(*result, json->memo + 1, p); if (NIL_P(*result)) { - p--; - {p++; cs = 8; goto _out;} - } else { - FORCE_UTF8(*result); - {p = (( p + 1))-1;} - } - } -#line 467 "parser.rl" + p--; + {p++; cs = 8; goto _out;} + } else { + FORCE_UTF8(*result); + {p = (( p + 1))-1;} + } + } +#line 491 "parser.rl" { p--; {p++; cs = 8; goto _out;} } goto st8; st8: if ( ++p == pe ) goto _test_eof8; case 8: -#line 1421 "parser.c" +#line 1457 "parser.c" goto st0; st3: if ( ++p == pe ) goto _test_eof3; case 3: @@ -1480,48 +1515,46 @@ goto st2; } else goto st2; goto st0; } - _test_eof2: cs = 2; goto _test_eof; - _test_eof8: cs = 8; 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_eof2: cs = 2; goto _test_eof; + _test_eof8: cs = 8; 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_eof: {} _out: {} } -#line 480 "parser.rl" +#line 517 "parser.rl" + if (json->create_additions && RTEST(match_string = json->match_string)) { + VALUE klass; + VALUE memo = rb_ary_new2(2); + rb_ary_push(memo, *result); + rb_hash_foreach(match_string, match_i, memo); + klass = rb_ary_entry(memo, 1); + if (RTEST(klass)) { + *result = rb_funcall(klass, i_json_create, 1, *result); + } + } + if (json->symbolize_names && json->parsing_name) { *result = rb_str_intern(*result); } if (cs >= JSON_string_first_final) { return p + 1; } else { return NULL; } } - - -#line 1511 "parser.c" -static const int JSON_start = 1; -static const int JSON_first_final = 10; -static const int JSON_error = 0; - -static const int JSON_en_main = 1; - - -#line 517 "parser.rl" - - -/* +/* * Document-class: JSON::Ext::Parser * * This is the JSON parser implemented as a C extension. It can be configured * to be used by setting * @@ -1541,26 +1574,19 @@ #ifdef HAVE_RUBY_ENCODING_H { VALUE encoding = rb_funcall(source, i_encoding, 0); if (encoding == CEncoding_ASCII_8BIT) { if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) { - source = rb_str_dup(source); - rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_32BE); - source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8); + source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_32BE); } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) { - source = rb_str_dup(source); - rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_16BE); - source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8); + source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_16BE); } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) { - source = rb_str_dup(source); - rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_32LE); - source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8); + source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_32LE); } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) { - source = rb_str_dup(source); - rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_16LE); - source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8); + source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_16LE); } else { + source = rb_str_dup(source); FORCE_UTF8(source); } } else { source = rb_funcall(source, i_encode, 1, CEncoding_UTF_8); } @@ -1590,11 +1616,11 @@ * 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. + * 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 @@ -1605,18 +1631,17 @@ * * *object_class*: Defaults to Hash * * *array_class*: Defaults to Array */ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) { - char *ptr; - long len; VALUE source, opts; - GET_PARSER; + GET_PARSER_INIT; + + if (json->Vsource) { + rb_raise(rb_eTypeError, "already initialized instance"); + } rb_scan_args(argc, argv, "11", &source, &opts); - source = convert_encoding(StringValue(source)); - ptr = RSTRING_PTR(source); - len = RSTRING_LEN(source); 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 { @@ -1628,35 +1653,41 @@ json->max_nesting = FIX2INT(max_nesting); } else { json->max_nesting = 0; } } else { - json->max_nesting = 19; + json->max_nesting = 100; } tmp = ID2SYM(i_allow_nan); if (option_given_p(opts, tmp)) { - VALUE allow_nan = rb_hash_aref(opts, tmp); - json->allow_nan = RTEST(allow_nan) ? 1 : 0; + 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)) { - VALUE symbolize_names = rb_hash_aref(opts, tmp); - json->symbolize_names = RTEST(symbolize_names) ? 1 : 0; + json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; } else { json->symbolize_names = 0; } + tmp = ID2SYM(i_quirks_mode); + if (option_given_p(opts, tmp)) { + VALUE quirks_mode = rb_hash_aref(opts, tmp); + json->quirks_mode = RTEST(quirks_mode) ? 1 : 0; + } else { + json->quirks_mode = 0; + } tmp = ID2SYM(i_create_additions); if (option_given_p(opts, tmp)) { - 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; - } + json->create_additions = RTEST(rb_hash_aref(opts, tmp)); } else { + json->create_additions = 0; + } + 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); @@ -1667,49 +1698,68 @@ if (option_given_p(opts, tmp)) { json->array_class = rb_hash_aref(opts, tmp); } else { json->array_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 = 19; + json->max_nesting = 100; json->allow_nan = 0; + json->create_additions = 1; json->create_id = rb_funcall(mJSON, i_create_id, 0); json->object_class = Qnil; json->array_class = Qnil; } + source = rb_convert_type(source, T_STRING, "String", "to_str"); + if (!json->quirks_mode) { + source = convert_encoding(StringValue(source)); + } json->current_nesting = 0; - json->len = len; - json->source = ptr; + StringValue(source); + json->len = RSTRING_LEN(source); + json->source = RSTRING_PTR(source);; json->Vsource = source; return self; } -/* - * call-seq: parse() - * - * Parses the current JSON text _source_ and returns the complete data - * structure as a result. - */ -static VALUE cParser_parse(VALUE self) + +#line 1733 "parser.c" +static const int JSON_start = 1; +static const int JSON_first_final = 10; +static const int JSON_error = 0; + +static const int JSON_en_main = 1; + + +#line 740 "parser.rl" + + +static VALUE cParser_parse_strict(VALUE self) { char *p, *pe; int cs = EVIL; VALUE result = Qnil; GET_PARSER; - -#line 1701 "parser.c" + +#line 1752 "parser.c" { cs = JSON_start; } -#line 698 "parser.rl" +#line 750 "parser.rl" p = json->source; pe = p + json->len; - -#line 1710 "parser.c" + +#line 1761 "parser.c" { if ( p == pe ) goto _test_eof; switch ( cs ) { @@ -1761,20 +1811,20 @@ case 5: if ( (*p) == 10 ) goto st1; goto st5; tr3: -#line 506 "parser.rl" +#line 729 "parser.rl" { char *np; json->current_nesting = 1; np = JSON_parse_array(json, p, pe, &result); if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;} } goto st10; tr4: -#line 499 "parser.rl" +#line 722 "parser.rl" { char *np; json->current_nesting = 1; np = JSON_parse_object(json, p, pe, &result); if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;} @@ -1782,11 +1832,11 @@ goto st10; st10: if ( ++p == pe ) goto _test_eof10; case 10: -#line 1787 "parser.c" +#line 1838 "parser.c" switch( (*p) ) { case 13: goto st10; case 32: goto st10; case 47: goto st6; } @@ -1824,52 +1874,246 @@ case 9: if ( (*p) == 10 ) goto st10; goto st9; } - _test_eof1: cs = 1; 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_eof10: cs = 10; 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_eof1: cs = 1; 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_eof10: cs = 10; 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 701 "parser.rl" +#line 753 "parser.rl" if (cs >= JSON_first_final && p == pe) { return result; } else { rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p); return Qnil; } } + + +#line 1907 "parser.c" +static const int JSON_quirks_mode_start = 1; +static const int JSON_quirks_mode_first_final = 10; +static const int JSON_quirks_mode_error = 0; + +static const int JSON_quirks_mode_en_main = 1; + + +#line 778 "parser.rl" + + +static VALUE cParser_parse_quirks_mode(VALUE self) +{ + char *p, *pe; + int cs = EVIL; + VALUE result = Qnil; + GET_PARSER; + + +#line 1926 "parser.c" + { + cs = JSON_quirks_mode_start; + } + +#line 788 "parser.rl" + p = json->source; + pe = p + json->len; + +#line 1935 "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 770 "parser.rl" + { + char *np = JSON_parse_value(json, p, pe, &result); + 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 1979 "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 791 "parser.rl" + + if (cs >= JSON_quirks_mode_first_final && p == pe) { + return result; + } else { + rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p); + return Qnil; + } +} + +/* + * call-seq: parse() + * + * Parses the current JSON text _source_ and returns the complete data + * structure as a result. + */ +static VALUE cParser_parse(VALUE self) +{ + GET_PARSER; + + if (json->quirks_mode) { + return cParser_parse_quirks_mode(self); + } else { + return cParser_parse_strict(self); + } +} + + static JSON_Parser *JSON_allocate() { JSON_Parser *json = ALLOC(JSON_Parser); MEMZERO(json, JSON_Parser, 1); + json->fbuffer = fbuffer_alloc(0); return json; } static void JSON_mark(JSON_Parser *json) { rb_gc_mark_maybe(json->Vsource); rb_gc_mark_maybe(json->create_id); rb_gc_mark_maybe(json->object_class); rb_gc_mark_maybe(json->array_class); + rb_gc_mark_maybe(json->match_string); } static void JSON_free(JSON_Parser *json) { + fbuffer_free(json->fbuffer); ruby_xfree(json); } static VALUE cJSON_parser_s_allocate(VALUE klass) { @@ -1887,10 +2131,22 @@ { GET_PARSER; return rb_str_dup(json->Vsource); } +/* + * call-seq: quirks_mode?() + * + * Returns a true, if this parser is in quirks_mode, false otherwise. + */ +static VALUE cParser_quirks_mode_p(VALUE self) +{ + GET_PARSER; + return json->quirks_mode ? Qtrue : Qfalse; +} + + void Init_parser() { rb_require("json/common"); mJSON = rb_define_module("JSON"); mExt = rb_define_module_under(mJSON, "Ext"); @@ -1899,10 +2155,11 @@ eNestingError = rb_path2class("JSON::NestingError"); rb_define_alloc_func(cParser, cJSON_parser_s_allocate); rb_define_method(cParser, "initialize", cParser_initialize, -1); rb_define_method(cParser, "parse", cParser_parse, 0); rb_define_method(cParser, "source", cParser_source, 0); + rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0); CNaN = rb_const_get(mJSON, rb_intern("NaN")); CInfinity = rb_const_get(mJSON, rb_intern("Infinity")); CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity")); @@ -1912,24 +2169,36 @@ i_create_additions = rb_intern("create_additions"); i_chr = rb_intern("chr"); i_max_nesting = rb_intern("max_nesting"); i_allow_nan = rb_intern("allow_nan"); i_symbolize_names = rb_intern("symbolize_names"); + i_quirks_mode = rb_intern("quirks_mode"); i_object_class = rb_intern("object_class"); i_array_class = rb_intern("array_class"); + i_match = rb_intern("match"); + i_match_string = rb_intern("match_string"); i_key_p = rb_intern("key?"); i_deep_const_get = rb_intern("deep_const_get"); + i_aset = rb_intern("[]="); + i_aref = rb_intern("[]"); + i_leftshift = rb_intern("<<"); #ifdef HAVE_RUBY_ENCODING_H CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8")); CEncoding_UTF_16BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16be")); CEncoding_UTF_16LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16le")); CEncoding_UTF_32BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32be")); CEncoding_UTF_32LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32le")); CEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit")); i_encoding = rb_intern("encoding"); i_encode = rb_intern("encode"); - i_encode_bang = rb_intern("encode!"); - i_force_encoding = rb_intern("force_encoding"); #else i_iconv = rb_intern("iconv"); #endif } + +/* + * Local variables: + * mode: c + * c-file-style: ruby + * indent-tabs-mode: nil + * End: + */