diff options
author | Florian Frank <flori@ping.de> | 2010-10-05 11:00:09 +0200 |
---|---|---|
committer | Florian Frank <flori@ping.de> | 2011-01-02 21:13:46 +0100 |
commit | 8714f0a88ccee67ea7ca1a9d5a40d9cf1c6dd5fb (patch) | |
tree | 9f1d194336debc54896944b80bbf3bbea44eb4dd /ext | |
parent | 02b20b1ec02513b7452e8585c6d45cbe565418d2 (diff) | |
download | json-8714f0a88ccee67ea7ca1a9d5a40d9cf1c6dd5fb.tar.gz |
Added matching in pure/ext parser
Diffstat (limited to 'ext')
-rw-r--r-- | ext/json/ext/parser/parser.c | 103 | ||||
-rw-r--r-- | ext/json/ext/parser/parser.h | 3 | ||||
-rw-r--r-- | ext/json/ext/parser/parser.rl | 75 |
3 files changed, 135 insertions, 46 deletions
diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c index a2f4601..43a1426 100644 --- a/ext/json/ext/parser/parser.c +++ b/ext/json/ext/parser/parser.c @@ -79,7 +79,7 @@ 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_array_class, i_key_p, i_deep_const_get, i_match; #line 108 "parser.rl" @@ -1361,21 +1361,34 @@ static const int JSON_string_en_main = 1; #line 471 "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, memo; *result = rb_str_buf_new(0); -#line 1371 "parser.c" +#line 1384 "parser.c" { cs = JSON_string_start; } -#line 479 "parser.rl" +#line 492 "parser.rl" json->memo = p; -#line 1379 "parser.c" +#line 1392 "parser.c" { if ( p == pe ) goto _test_eof; @@ -1404,13 +1417,13 @@ tr2: { *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;} - } - } + p--; + {p++; cs = 8; goto _out;} + } else { + FORCE_UTF8(*result); + {p = (( p + 1))-1;} + } + } #line 468 "parser.rl" { p--; {p++; cs = 8; goto _out;} } goto st8; @@ -1418,7 +1431,7 @@ st8: if ( ++p == pe ) goto _test_eof8; case 8: -#line 1422 "parser.c" +#line 1435 "parser.c" goto st0; st3: if ( ++p == pe ) @@ -1494,7 +1507,21 @@ case 7: _out: {} } -#line 481 "parser.rl" +#line 494 "parser.rl" + + if (json->create_additions) { + match = json->match; + memo = rb_ary_new2(2); + rb_ary_push(memo, *result); + if (RTEST(match)) { + VALUE klass; + rb_hash_foreach(match, 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); @@ -1508,7 +1535,7 @@ case 7: -#line 1512 "parser.c" +#line 1539 "parser.c" static const int JSON_start = 1; static const int JSON_first_final = 10; static const int JSON_error = 0; @@ -1516,7 +1543,7 @@ static const int JSON_error = 0; static const int JSON_en_main = 1; -#line 518 "parser.rl" +#line 545 "parser.rl" /* @@ -1649,14 +1676,17 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) 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; - } - } else { - json->create_id = rb_funcall(mJSON, i_create_id, 0); - } + json->create_additions = RTEST(create_additions); + } else { + json->create_additions = 1; + } + tmp = ID2SYM(i_create_id); + if (option_given_p(opts, tmp)) { + VALUE create_id = rb_hash_aref(opts, tmp); + json->create_id = create_id; + } 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); @@ -1669,6 +1699,17 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) } else { json->array_class = Qnil; } + tmp = ID2SYM(i_match); + if (option_given_p(opts, tmp)) { + VALUE match = rb_hash_aref(opts, tmp); + if (RTEST(match)) { + json->match = match; + } else { + json->match = Qnil; + } + } else { + json->match = Qnil; + } } } else { json->max_nesting = 19; @@ -1698,16 +1739,16 @@ static VALUE cParser_parse(VALUE self) GET_PARSER; -#line 1702 "parser.c" +#line 1743 "parser.c" { cs = JSON_start; } -#line 699 "parser.rl" +#line 740 "parser.rl" p = json->source; pe = p + json->len; -#line 1711 "parser.c" +#line 1752 "parser.c" { if ( p == pe ) goto _test_eof; @@ -1763,7 +1804,7 @@ case 5: goto st1; goto st5; tr3: -#line 507 "parser.rl" +#line 534 "parser.rl" { char *np; json->current_nesting = 1; @@ -1772,7 +1813,7 @@ tr3: } goto st10; tr4: -#line 500 "parser.rl" +#line 527 "parser.rl" { char *np; json->current_nesting = 1; @@ -1784,7 +1825,7 @@ st10: if ( ++p == pe ) goto _test_eof10; case 10: -#line 1788 "parser.c" +#line 1829 "parser.c" switch( (*p) ) { case 13: goto st10; case 32: goto st10; @@ -1841,7 +1882,7 @@ case 9: _out: {} } -#line 702 "parser.rl" +#line 743 "parser.rl" if (cs >= JSON_first_final && p == pe) { return result; @@ -1864,6 +1905,7 @@ static void JSON_mark(JSON_Parser *json) 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); } static void JSON_free(JSON_Parser *json) @@ -1916,6 +1958,7 @@ void Init_parser() i_symbolize_names = rb_intern("symbolize_names"); i_object_class = rb_intern("object_class"); i_array_class = rb_intern("array_class"); + i_match = rb_intern("match"); i_key_p = rb_intern("key?"); i_deep_const_get = rb_intern("deep_const_get"); #ifdef HAVE_RUBY_ENCODING_H diff --git a/ext/json/ext/parser/parser.h b/ext/json/ext/parser/parser.h index 688ffda..ab02b51 100644 --- a/ext/json/ext/parser/parser.h +++ b/ext/json/ext/parser/parser.h @@ -13,6 +13,7 @@ #else #define FORCE_UTF8(obj) #endif +#include "ruby/st.h" #define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key)) @@ -41,6 +42,8 @@ typedef struct JSON_ParserStruct { int symbolize_names; VALUE object_class; VALUE array_class; + int create_additions; + VALUE match; } JSON_Parser; #define GET_PARSER \ diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl index dd07485..f59038b 100644 --- a/ext/json/ext/parser/parser.rl +++ b/ext/json/ext/parser/parser.rl @@ -77,7 +77,7 @@ 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_array_class, i_key_p, i_deep_const_get, i_match; %%{ machine JSON_common; @@ -457,28 +457,55 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) action parse_string { *result = json_string_unescape(*result, json->memo + 1, p); if (NIL_P(*result)) { - fhold; - fbreak; - } else { - FORCE_UTF8(*result); - fexec p + 1; - } - } + fhold; + fbreak; + } else { + FORCE_UTF8(*result); + fexec p + 1; + } + } action exit { fhold; fbreak; } main := '"' ((^(["\\] | 0..0x1f) | '\\'["\\/bfnrt] | '\\u'[0-9a-fA-F]{4} | '\\'^(["\\/bfnrtu]|0..0x1f))* %parse_string) '"' @exit; }%% +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, memo; *result = rb_str_buf_new(0); %% write init; json->memo = p; %% write exec; + if (json->create_additions) { + match = json->match; + memo = rb_ary_new2(2); + rb_ary_push(memo, *result); + if (RTEST(match)) { + VALUE klass; + rb_hash_foreach(match, 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); } @@ -647,14 +674,17 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) 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; - } - } else { - json->create_id = rb_funcall(mJSON, i_create_id, 0); - } + json->create_additions = RTEST(create_additions); + } else { + json->create_additions = 1; + } + tmp = ID2SYM(i_create_id); + if (option_given_p(opts, tmp)) { + VALUE create_id = rb_hash_aref(opts, tmp); + json->create_id = create_id; + } 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); @@ -667,6 +697,17 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) } else { json->array_class = Qnil; } + tmp = ID2SYM(i_match); + if (option_given_p(opts, tmp)) { + VALUE match = rb_hash_aref(opts, tmp); + if (RTEST(match)) { + json->match = match; + } else { + json->match = Qnil; + } + } else { + json->match = Qnil; + } } } else { json->max_nesting = 19; @@ -721,6 +762,7 @@ static void JSON_mark(JSON_Parser *json) 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); } static void JSON_free(JSON_Parser *json) @@ -773,6 +815,7 @@ void Init_parser() i_symbolize_names = rb_intern("symbolize_names"); i_object_class = rb_intern("object_class"); i_array_class = rb_intern("array_class"); + i_match = rb_intern("match"); i_key_p = rb_intern("key?"); i_deep_const_get = rb_intern("deep_const_get"); #ifdef HAVE_RUBY_ENCODING_H |