ext/json/ext/parser/parser.rl in json_pure-2.3.1 vs ext/json/ext/parser/parser.rl in json_pure-2.4.0

- old
+ new

@@ -93,11 +93,11 @@ 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_decimal_class, i_key_p, i_deep_const_get, i_match, i_match_string, i_aset, i_aref, - i_leftshift, i_new, i_BigDecimal; + i_leftshift, i_new, i_BigDecimal, i_freeze, i_uminus; %%{ machine JSON_common; cr = '\n'; @@ -288,10 +288,14 @@ int cs = EVIL; %% write init; %% write exec; + if (json->freeze) { + OBJ_FREEZE(*result); + } + if (cs >= JSON_value_first_final) { return p; } else { return NULL; } @@ -571,11 +575,26 @@ } 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 { return NULL; @@ -679,10 +698,16 @@ 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; @@ -884,9 +909,11 @@ i_aset = rb_intern("[]="); i_aref = rb_intern("[]"); i_leftshift = rb_intern("<<"); i_new = rb_intern("new"); i_BigDecimal = rb_intern("BigDecimal"); + i_freeze = rb_intern("freeze"); + i_uminus = rb_intern("-@"); } /* * Local variables: * mode: c