Skip to content

Commit 314d117

Browse files
committed
parser.c: Pass the JSON_ParserConfig pointer
Doesn't make a measurable performance difference but is a bit clearer.
1 parent dd9c46c commit 314d117

File tree

1 file changed

+44
-47
lines changed

1 file changed

+44
-47
lines changed

ext/json/ext/parser/parser.c

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,6 @@ typedef struct JSON_ParserStruct {
424424
} JSON_ParserConfig;
425425

426426
typedef struct JSON_ParserStateStruct {
427-
JSON_ParserConfig *config;
428427
VALUE stack_handle;
429428
const char *cursor;
430429
const char *end;
@@ -728,7 +727,7 @@ static VALUE json_decode_large_integer(const char *start, long len)
728727
}
729728

730729
static inline VALUE
731-
json_decode_integer(JSON_ParserState *state, const char *start, const char *end)
730+
json_decode_integer(const char *start, const char *end)
732731
{
733732
long len = end - start;
734733
if (RB_LIKELY(len < MAX_FAST_INTEGER_SIZE)) {
@@ -748,11 +747,10 @@ static VALUE json_decode_large_float(const char *start, long len)
748747
return number;
749748
}
750749

751-
static VALUE json_decode_float(JSON_ParserState *state, const char *start, const char *end)
750+
static VALUE json_decode_float(JSON_ParserConfig *config, const char *start, const char *end)
752751
{
753752
VALUE mod = Qnil;
754753
ID method_id = 0;
755-
JSON_ParserConfig *config = state->config;
756754
if (RB_UNLIKELY(config->decimal_class)) {
757755
// TODO: we should move this to the constructor
758756
if (rb_respond_to(config->decimal_class, i_try_convert)) {
@@ -797,11 +795,11 @@ static VALUE json_decode_float(JSON_ParserState *state, const char *start, const
797795
}
798796
}
799797

800-
static inline VALUE json_decode_array(JSON_ParserState *state, long count)
798+
static inline VALUE json_decode_array(JSON_ParserState *state, JSON_ParserConfig *config, long count)
801799
{
802800
VALUE array;
803-
if (RB_UNLIKELY(state->config->array_class)) {
804-
array = rb_class_new_instance(0, 0, state->config->array_class);
801+
if (RB_UNLIKELY(config->array_class)) {
802+
array = rb_class_new_instance(0, 0, config->array_class);
805803
VALUE *items = rvalue_stack_peek(state->stack, count);
806804
long index;
807805
for (index = 0; index < count; index++) {
@@ -813,18 +811,18 @@ static inline VALUE json_decode_array(JSON_ParserState *state, long count)
813811

814812
rvalue_stack_pop(state->stack, count);
815813

816-
if (state->config->freeze) {
814+
if (config->freeze) {
817815
RB_OBJ_FREEZE(array);
818816
}
819817

820818
return array;
821819
}
822820

823-
static inline VALUE json_decode_object(JSON_ParserState *state, long count)
821+
static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfig *config, long count)
824822
{
825823
VALUE object;
826-
if (RB_UNLIKELY(state->config->object_class)) {
827-
object = rb_class_new_instance(0, 0, state->config->object_class);
824+
if (RB_UNLIKELY(config->object_class)) {
825+
object = rb_class_new_instance(0, 0, config->object_class);
828826
long index = 0;
829827
VALUE *items = rvalue_stack_peek(state->stack, count);
830828
while (index < count) {
@@ -839,25 +837,25 @@ static inline VALUE json_decode_object(JSON_ParserState *state, long count)
839837

840838
rvalue_stack_pop(state->stack, count);
841839

842-
if (RB_UNLIKELY(state->config->create_additions)) {
840+
if (RB_UNLIKELY(config->create_additions)) {
843841
VALUE klassname;
844-
if (state->config->object_class) {
845-
klassname = rb_funcall(object, i_aref, 1, state->config->create_id);
842+
if (config->object_class) {
843+
klassname = rb_funcall(object, i_aref, 1, config->create_id);
846844
} else {
847-
klassname = rb_hash_aref(object, state->config->create_id);
845+
klassname = rb_hash_aref(object, config->create_id);
848846
}
849847
if (!NIL_P(klassname)) {
850848
VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname);
851849
if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) {
852-
if (state->config->deprecated_create_additions) {
850+
if (config->deprecated_create_additions) {
853851
json_deprecated(deprecated_create_additions_warning);
854852
}
855853
object = rb_funcall(klass, i_json_create, 1, object);
856854
}
857855
}
858856
}
859857

860-
if (state->config->freeze) {
858+
if (config->freeze) {
861859
RB_OBJ_FREEZE(object);
862860
}
863861

@@ -875,22 +873,22 @@ static int match_i(VALUE regexp, VALUE klass, VALUE memo)
875873
return ST_CONTINUE;
876874
}
877875

878-
static inline VALUE json_decode_string(JSON_ParserState *state, const char *start, const char *end, bool escaped, bool is_name)
876+
static inline VALUE json_decode_string(JSON_ParserState *state, JSON_ParserConfig *config, const char *start, const char *end, bool escaped, bool is_name)
879877
{
880878
VALUE string;
881-
bool intern = is_name || state->config->freeze;
882-
bool symbolize = is_name && state->config->symbolize_names;
879+
bool intern = is_name || config->freeze;
880+
bool symbolize = is_name && config->symbolize_names;
883881
if (escaped) {
884882
string = json_string_unescape(state, start, end, is_name, intern, symbolize);
885883
} else {
886884
string = json_string_fastpath(state, start, end, is_name, intern, symbolize);
887885
}
888886

889-
if (RB_UNLIKELY(state->config->create_additions && RTEST(state->config->match_string))) {
887+
if (RB_UNLIKELY(config->create_additions && RTEST(config->match_string))) {
890888
VALUE klass;
891889
VALUE memo = rb_ary_new2(2);
892890
rb_ary_push(memo, string);
893-
rb_hash_foreach(state->config->match_string, match_i, memo);
891+
rb_hash_foreach(config->match_string, match_i, memo);
894892
klass = rb_ary_entry(memo, 1);
895893
if (RTEST(klass)) {
896894
string = rb_funcall(klass, i_json_create, 1, string);
@@ -915,7 +913,7 @@ static const bool string_scan[256] = {
915913
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
916914
};
917915

918-
static inline VALUE json_parse_string(JSON_ParserState *state, bool is_name)
916+
static inline VALUE json_parse_string(JSON_ParserState *state, JSON_ParserConfig *config, bool is_name)
919917
{
920918
state->cursor++;
921919
const char *start = state->cursor;
@@ -925,7 +923,7 @@ static inline VALUE json_parse_string(JSON_ParserState *state, bool is_name)
925923
if (RB_UNLIKELY(string_scan[(unsigned char)*state->cursor])) {
926924
switch (*state->cursor) {
927925
case '"': {
928-
VALUE string = json_decode_string(state, start, state->cursor, escaped, is_name);
926+
VALUE string = json_decode_string(state, config, start, state->cursor, escaped, is_name);
929927
state->cursor++;
930928
return PUSH(string);
931929
}
@@ -950,7 +948,7 @@ static inline VALUE json_parse_string(JSON_ParserState *state, bool is_name)
950948
return Qfalse;
951949
}
952950

953-
static VALUE json_parse_any(JSON_ParserState *state)
951+
static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
954952
{
955953
json_eat_whitespace(state);
956954
if (state->cursor >= state->end) {
@@ -985,15 +983,15 @@ static VALUE json_parse_any(JSON_ParserState *state)
985983
break;
986984
case 'N':
987985
// Note: memcmp with a small power of two compile to an integer comparison
988-
if (state->config->allow_nan && (state->end - state->cursor >= 3) && (memcmp(state->cursor + 1, "aN", 2) == 0)) {
986+
if (config->allow_nan && (state->end - state->cursor >= 3) && (memcmp(state->cursor + 1, "aN", 2) == 0)) {
989987
state->cursor += 3;
990988
return PUSH(CNaN);
991989
}
992990

993991
raise_parse_error("unexpected token at '%s'", state->cursor);
994992
break;
995993
case 'I':
996-
if (state->config->allow_nan && (state->end - state->cursor >= 8) && (memcmp(state->cursor, "Infinity", 8) == 0)) {
994+
if (config->allow_nan && (state->end - state->cursor >= 8) && (memcmp(state->cursor, "Infinity", 8) == 0)) {
997995
state->cursor += 8;
998996
return PUSH(CInfinity);
999997
}
@@ -1003,7 +1001,7 @@ static VALUE json_parse_any(JSON_ParserState *state)
10031001
case '-':
10041002
// Note: memcmp with a small power of two compile to an integer comparison
10051003
if ((state->end - state->cursor >= 9) && (memcmp(state->cursor + 1, "Infinity", 8) == 0)) {
1006-
if (state->config->allow_nan) {
1004+
if (config->allow_nan) {
10071005
state->cursor += 9;
10081006
return PUSH(CMinusInfinity);
10091007
} else {
@@ -1060,13 +1058,13 @@ static VALUE json_parse_any(JSON_ParserState *state)
10601058
}
10611059

10621060
if (integer) {
1063-
return PUSH(json_decode_integer(state, start, state->cursor));
1061+
return PUSH(json_decode_integer(start, state->cursor));
10641062
}
1065-
return PUSH(json_decode_float(state, start, state->cursor));
1063+
return PUSH(json_decode_float(config, start, state->cursor));
10661064
}
10671065
case '"': {
10681066
// %r{\A"[^"\\\t\n\x00]*(?:\\[bfnrtu\\/"][^"\\]*)*"}
1069-
return json_parse_string(state, false);
1067+
return json_parse_string(state, config, false);
10701068
break;
10711069
}
10721070
case '[': {
@@ -1076,14 +1074,14 @@ static VALUE json_parse_any(JSON_ParserState *state)
10761074

10771075
if ((state->cursor < state->end) && (*state->cursor == ']')) {
10781076
state->cursor++;
1079-
return PUSH(json_decode_array(state, 0));
1077+
return PUSH(json_decode_array(state, config, 0));
10801078
} else {
10811079
state->current_nesting++;
1082-
if (RB_UNLIKELY(state->config->max_nesting && (state->config->max_nesting < state->current_nesting))) {
1080+
if (RB_UNLIKELY(config->max_nesting && (config->max_nesting < state->current_nesting))) {
10831081
rb_raise(eNestingError, "nesting of %d is too deep", state->current_nesting);
10841082
}
10851083
state->in_array++;
1086-
json_parse_any(state);
1084+
json_parse_any(state, config);
10871085
}
10881086

10891087
while (true) {
@@ -1095,18 +1093,18 @@ static VALUE json_parse_any(JSON_ParserState *state)
10951093
long count = state->stack->head - stack_head;
10961094
state->current_nesting--;
10971095
state->in_array--;
1098-
return PUSH(json_decode_array(state, count));
1096+
return PUSH(json_decode_array(state, config, count));
10991097
}
11001098

11011099
if (*state->cursor == ',') {
11021100
state->cursor++;
1103-
if (state->config->allow_trailing_comma) {
1101+
if (config->allow_trailing_comma) {
11041102
json_eat_whitespace(state);
11051103
if ((state->cursor < state->end) && (*state->cursor == ']')) {
11061104
continue;
11071105
}
11081106
}
1109-
json_parse_any(state);
1107+
json_parse_any(state, config);
11101108
continue;
11111109
}
11121110
}
@@ -1122,25 +1120,25 @@ static VALUE json_parse_any(JSON_ParserState *state)
11221120

11231121
if ((state->cursor < state->end) && (*state->cursor == '}')) {
11241122
state->cursor++;
1125-
return PUSH(json_decode_object(state, 0));
1123+
return PUSH(json_decode_object(state, config, 0));
11261124
} else {
11271125
state->current_nesting++;
1128-
if (RB_UNLIKELY(state->config->max_nesting && (state->config->max_nesting < state->current_nesting))) {
1126+
if (RB_UNLIKELY(config->max_nesting && (config->max_nesting < state->current_nesting))) {
11291127
rb_raise(eNestingError, "nesting of %d is too deep", state->current_nesting);
11301128
}
11311129

11321130
if (*state->cursor != '"') {
11331131
raise_parse_error("expected object key, got '%s", state->cursor);
11341132
}
1135-
json_parse_string(state, true);
1133+
json_parse_string(state, config, true);
11361134

11371135
json_eat_whitespace(state);
11381136
if ((state->cursor >= state->end) || (*state->cursor != ':')) {
11391137
raise_parse_error("expected ':' after object key", state->cursor);
11401138
}
11411139
state->cursor++;
11421140

1143-
json_parse_any(state);
1141+
json_parse_any(state, config);
11441142
}
11451143

11461144
while (true) {
@@ -1151,14 +1149,14 @@ static VALUE json_parse_any(JSON_ParserState *state)
11511149
state->cursor++;
11521150
state->current_nesting--;
11531151
long count = state->stack->head - stack_head;
1154-
return PUSH(json_decode_object(state, count));
1152+
return PUSH(json_decode_object(state, config, count));
11551153
}
11561154

11571155
if (*state->cursor == ',') {
11581156
state->cursor++;
11591157
json_eat_whitespace(state);
11601158

1161-
if (state->config->allow_trailing_comma) {
1159+
if (config->allow_trailing_comma) {
11621160
if ((state->cursor < state->end) && (*state->cursor == '}')) {
11631161
continue;
11641162
}
@@ -1167,15 +1165,15 @@ static VALUE json_parse_any(JSON_ParserState *state)
11671165
if (*state->cursor != '"') {
11681166
raise_parse_error("expected object key, got: '%s'", state->cursor);
11691167
}
1170-
json_parse_string(state, true);
1168+
json_parse_string(state, config, true);
11711169

11721170
json_eat_whitespace(state);
11731171
if ((state->cursor >= state->end) || (*state->cursor != ':')) {
11741172
raise_parse_error("expected ':' after object key, got: '%s", state->cursor);
11751173
}
11761174
state->cursor++;
11771175

1178-
json_parse_any(state);
1176+
json_parse_any(state, config);
11791177

11801178
continue;
11811179
}
@@ -1342,14 +1340,13 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
13421340
};
13431341

13441342
JSON_ParserState _state = {
1345-
.config = config,
13461343
.cursor = RSTRING_PTR(Vsource),
13471344
.end = RSTRING_END(Vsource),
13481345
.stack = &stack,
13491346
};
13501347
JSON_ParserState *state = &_state;
13511348

1352-
VALUE result = json_parse_any(state);
1349+
VALUE result = json_parse_any(state, config);
13531350

13541351
// This may be skipped in case of exception, but
13551352
// it won't cause a leak.

0 commit comments

Comments
 (0)