@@ -37,7 +37,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id,
37
37
38
38
static VALUE sym_max_nesting , sym_allow_nan , sym_allow_trailing_comma , sym_symbolize_names , sym_freeze ,
39
39
sym_create_additions , sym_create_id , sym_object_class , sym_array_class ,
40
- sym_decimal_class , sym_match_string ;
40
+ sym_decimal_class , sym_match_string , sym_on_load ;
41
41
42
42
static int binary_encindex ;
43
43
static int utf8_encindex ;
@@ -444,6 +444,7 @@ static int convert_UTF32_to_UTF8(char *buf, uint32_t ch)
444
444
}
445
445
446
446
typedef struct JSON_ParserStruct {
447
+ VALUE on_load_proc ;
447
448
VALUE create_id ;
448
449
VALUE object_class ;
449
450
VALUE array_class ;
@@ -879,7 +880,14 @@ static inline VALUE json_decode_string(JSON_ParserState *state, JSON_ParserConfi
879
880
return string ;
880
881
}
881
882
882
- #define PUSH (result ) rvalue_stack_push(state->stack, result, &state->stack_handle, &state->stack)
883
+ static inline VALUE json_push_value (JSON_ParserState * state , JSON_ParserConfig * config , VALUE value )
884
+ {
885
+ if (RB_UNLIKELY (config -> on_load_proc )) {
886
+ value = rb_proc_call_with_block (config -> on_load_proc , 1 , & value , Qnil );
887
+ }
888
+ rvalue_stack_push (state -> stack , value , & state -> stack_handle , & state -> stack );
889
+ return value ;
890
+ }
883
891
884
892
static const bool string_scan [256 ] = {
885
893
// ASCII Control Characters
@@ -906,7 +914,7 @@ static inline VALUE json_parse_string(JSON_ParserState *state, JSON_ParserConfig
906
914
case '"' : {
907
915
VALUE string = json_decode_string (state , config , start , state -> cursor , escaped , is_name );
908
916
state -> cursor ++ ;
909
- return PUSH ( string );
917
+ return json_push_value ( state , config , string );
910
918
}
911
919
case '\\' : {
912
920
state -> cursor ++ ;
@@ -940,15 +948,15 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
940
948
case 'n' :
941
949
if ((state -> end - state -> cursor >= 4 ) && (memcmp (state -> cursor , "null" , 4 ) == 0 )) {
942
950
state -> cursor += 4 ;
943
- return PUSH ( Qnil );
951
+ return json_push_value ( state , config , Qnil );
944
952
}
945
953
946
954
raise_parse_error ("unexpected token at '%s'" , state -> cursor );
947
955
break ;
948
956
case 't' :
949
957
if ((state -> end - state -> cursor >= 4 ) && (memcmp (state -> cursor , "true" , 4 ) == 0 )) {
950
958
state -> cursor += 4 ;
951
- return PUSH ( Qtrue );
959
+ return json_push_value ( state , config , Qtrue );
952
960
}
953
961
954
962
raise_parse_error ("unexpected token at '%s'" , state -> cursor );
@@ -957,7 +965,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
957
965
// Note: memcmp with a small power of two compile to an integer comparison
958
966
if ((state -> end - state -> cursor >= 5 ) && (memcmp (state -> cursor + 1 , "alse" , 4 ) == 0 )) {
959
967
state -> cursor += 5 ;
960
- return PUSH ( Qfalse );
968
+ return json_push_value ( state , config , Qfalse );
961
969
}
962
970
963
971
raise_parse_error ("unexpected token at '%s'" , state -> cursor );
@@ -966,15 +974,15 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
966
974
// Note: memcmp with a small power of two compile to an integer comparison
967
975
if (config -> allow_nan && (state -> end - state -> cursor >= 3 ) && (memcmp (state -> cursor + 1 , "aN" , 2 ) == 0 )) {
968
976
state -> cursor += 3 ;
969
- return PUSH ( CNaN );
977
+ return json_push_value ( state , config , CNaN );
970
978
}
971
979
972
980
raise_parse_error ("unexpected token at '%s'" , state -> cursor );
973
981
break ;
974
982
case 'I' :
975
983
if (config -> allow_nan && (state -> end - state -> cursor >= 8 ) && (memcmp (state -> cursor , "Infinity" , 8 ) == 0 )) {
976
984
state -> cursor += 8 ;
977
- return PUSH ( CInfinity );
985
+ return json_push_value ( state , config , CInfinity );
978
986
}
979
987
980
988
raise_parse_error ("unexpected token at '%s'" , state -> cursor );
@@ -984,7 +992,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
984
992
if ((state -> end - state -> cursor >= 9 ) && (memcmp (state -> cursor + 1 , "Infinity" , 8 ) == 0 )) {
985
993
if (config -> allow_nan ) {
986
994
state -> cursor += 9 ;
987
- return PUSH ( CMinusInfinity );
995
+ return json_push_value ( state , config , CMinusInfinity );
988
996
} else {
989
997
raise_parse_error ("unexpected token at '%s'" , state -> cursor );
990
998
}
@@ -1041,9 +1049,9 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1041
1049
}
1042
1050
1043
1051
if (integer ) {
1044
- return PUSH ( json_decode_integer (start , state -> cursor ));
1052
+ return json_push_value ( state , config , json_decode_integer (start , state -> cursor ));
1045
1053
}
1046
- return PUSH ( json_decode_float (config , start , state -> cursor ));
1054
+ return json_push_value ( state , config , json_decode_float (config , start , state -> cursor ));
1047
1055
}
1048
1056
case '"' : {
1049
1057
// %r{\A"[^"\\\t\n\x00]*(?:\\[bfnrtu\\/"][^"\\]*)*"}
@@ -1057,7 +1065,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1057
1065
1058
1066
if ((state -> cursor < state -> end ) && (* state -> cursor == ']' )) {
1059
1067
state -> cursor ++ ;
1060
- return PUSH ( json_decode_array (state , config , 0 ));
1068
+ return json_push_value ( state , config , json_decode_array (state , config , 0 ));
1061
1069
} else {
1062
1070
state -> current_nesting ++ ;
1063
1071
if (RB_UNLIKELY (config -> max_nesting && (config -> max_nesting < state -> current_nesting ))) {
@@ -1076,7 +1084,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1076
1084
long count = state -> stack -> head - stack_head ;
1077
1085
state -> current_nesting -- ;
1078
1086
state -> in_array -- ;
1079
- return PUSH ( json_decode_array (state , config , count ));
1087
+ return json_push_value ( state , config , json_decode_array (state , config , count ));
1080
1088
}
1081
1089
1082
1090
if (* state -> cursor == ',' ) {
@@ -1103,7 +1111,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1103
1111
1104
1112
if ((state -> cursor < state -> end ) && (* state -> cursor == '}' )) {
1105
1113
state -> cursor ++ ;
1106
- return PUSH ( json_decode_object (state , config , 0 ));
1114
+ return json_push_value ( state , config , json_decode_object (state , config , 0 ));
1107
1115
} else {
1108
1116
state -> current_nesting ++ ;
1109
1117
if (RB_UNLIKELY (config -> max_nesting && (config -> max_nesting < state -> current_nesting ))) {
@@ -1132,7 +1140,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1132
1140
state -> cursor ++ ;
1133
1141
state -> current_nesting -- ;
1134
1142
long count = state -> stack -> head - stack_head ;
1135
- return PUSH ( json_decode_object (state , config , count ));
1143
+ return json_push_value ( state , config , json_decode_object (state , config , count ));
1136
1144
}
1137
1145
1138
1146
if (* state -> cursor == ',' ) {
@@ -1220,6 +1228,7 @@ static int parser_config_init_i(VALUE key, VALUE val, VALUE data)
1220
1228
else if (key == sym_allow_trailing_comma ) { config -> allow_trailing_comma = RTEST (val ); }
1221
1229
else if (key == sym_symbolize_names ) { config -> symbolize_names = RTEST (val ); }
1222
1230
else if (key == sym_freeze ) { config -> freeze = RTEST (val ); }
1231
+ else if (key == sym_on_load ) { config -> on_load_proc = RTEST (val ) ? val : Qfalse ; }
1223
1232
else if (key == sym_create_id ) { config -> create_id = RTEST (val ) ? val : Qfalse ; }
1224
1233
else if (key == sym_object_class ) { config -> object_class = RTEST (val ) ? val : Qfalse ; }
1225
1234
else if (key == sym_array_class ) { config -> array_class = RTEST (val ) ? val : Qfalse ; }
@@ -1396,6 +1405,7 @@ static VALUE cParser_m_parse(VALUE klass, VALUE Vsource, VALUE opts)
1396
1405
static void JSON_ParserConfig_mark (void * ptr )
1397
1406
{
1398
1407
JSON_ParserConfig * config = ptr ;
1408
+ rb_gc_mark (config -> on_load_proc );
1399
1409
rb_gc_mark (config -> create_id );
1400
1410
rb_gc_mark (config -> object_class );
1401
1411
rb_gc_mark (config -> array_class );
@@ -1468,6 +1478,7 @@ void Init_parser(void)
1468
1478
sym_allow_trailing_comma = ID2SYM (rb_intern ("allow_trailing_comma" ));
1469
1479
sym_symbolize_names = ID2SYM (rb_intern ("symbolize_names" ));
1470
1480
sym_freeze = ID2SYM (rb_intern ("freeze" ));
1481
+ sym_on_load = ID2SYM (rb_intern ("on_load" ));
1471
1482
sym_create_additions = ID2SYM (rb_intern ("create_additions" ));
1472
1483
sym_create_id = ID2SYM (rb_intern ("create_id" ));
1473
1484
sym_object_class = ID2SYM (rb_intern ("object_class" ));
0 commit comments