json 2.10.2 → 2.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -31,28 +31,15 @@ typedef unsigned char _Bool;
31
31
  static VALUE mJSON, eNestingError, Encoding_UTF_8;
32
32
  static VALUE CNaN, CInfinity, CMinusInfinity;
33
33
 
34
- static ID i_json_creatable_p, i_json_create, i_create_id,
35
- i_chr, i_deep_const_get, i_match, i_aset, i_aref,
34
+ static ID i_chr, i_aset, i_aref,
36
35
  i_leftshift, i_new, i_try_convert, i_uminus, i_encode;
37
36
 
38
37
  static VALUE sym_max_nesting, sym_allow_nan, sym_allow_trailing_comma, sym_symbolize_names, sym_freeze,
39
- sym_create_additions, sym_create_id, sym_object_class, sym_array_class,
40
- sym_decimal_class, sym_match_string;
38
+ sym_decimal_class, sym_on_load;
41
39
 
42
40
  static int binary_encindex;
43
41
  static int utf8_encindex;
44
42
 
45
- #ifdef HAVE_RB_CATEGORY_WARN
46
- # define json_deprecated(message) rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, message)
47
- #else
48
- # define json_deprecated(message) rb_warn(message)
49
- #endif
50
-
51
- static const char deprecated_create_additions_warning[] =
52
- "JSON.load implicit support for `create_additions: true` is deprecated "
53
- "and will be removed in 3.0, use JSON.unsafe_load or explicitly "
54
- "pass `create_additions: true`";
55
-
56
43
  #ifndef HAVE_RB_HASH_BULK_INSERT
57
44
  // For TruffleRuby
58
45
  void
@@ -350,33 +337,128 @@ static size_t strnlen(const char *s, size_t maxlen)
350
337
  }
351
338
  #endif
352
339
 
340
+ static int convert_UTF32_to_UTF8(char *buf, uint32_t ch)
341
+ {
342
+ int len = 1;
343
+ if (ch <= 0x7F) {
344
+ buf[0] = (char) ch;
345
+ } else if (ch <= 0x07FF) {
346
+ buf[0] = (char) ((ch >> 6) | 0xC0);
347
+ buf[1] = (char) ((ch & 0x3F) | 0x80);
348
+ len++;
349
+ } else if (ch <= 0xFFFF) {
350
+ buf[0] = (char) ((ch >> 12) | 0xE0);
351
+ buf[1] = (char) (((ch >> 6) & 0x3F) | 0x80);
352
+ buf[2] = (char) ((ch & 0x3F) | 0x80);
353
+ len += 2;
354
+ } else if (ch <= 0x1fffff) {
355
+ buf[0] =(char) ((ch >> 18) | 0xF0);
356
+ buf[1] =(char) (((ch >> 12) & 0x3F) | 0x80);
357
+ buf[2] =(char) (((ch >> 6) & 0x3F) | 0x80);
358
+ buf[3] =(char) ((ch & 0x3F) | 0x80);
359
+ len += 3;
360
+ } else {
361
+ buf[0] = '?';
362
+ }
363
+ return len;
364
+ }
365
+
366
+ typedef struct JSON_ParserStruct {
367
+ VALUE on_load_proc;
368
+ VALUE decimal_class;
369
+ ID decimal_method_id;
370
+ int max_nesting;
371
+ bool allow_nan;
372
+ bool allow_trailing_comma;
373
+ bool parsing_name;
374
+ bool symbolize_names;
375
+ bool freeze;
376
+ } JSON_ParserConfig;
377
+
378
+ typedef struct JSON_ParserStateStruct {
379
+ VALUE stack_handle;
380
+ const char *start;
381
+ const char *cursor;
382
+ const char *end;
383
+ rvalue_stack *stack;
384
+ rvalue_cache name_cache;
385
+ int in_array;
386
+ int current_nesting;
387
+ } JSON_ParserState;
388
+
389
+
353
390
  #define PARSE_ERROR_FRAGMENT_LEN 32
354
391
  #ifdef RBIMPL_ATTR_NORETURN
355
392
  RBIMPL_ATTR_NORETURN()
356
393
  #endif
357
- static void raise_parse_error(const char *format, const char *start)
394
+ static void raise_parse_error(const char *format, JSON_ParserState *state)
358
395
  {
359
- unsigned char buffer[PARSE_ERROR_FRAGMENT_LEN + 1];
396
+ unsigned char buffer[PARSE_ERROR_FRAGMENT_LEN + 3];
360
397
 
361
- size_t len = start ? strnlen(start, PARSE_ERROR_FRAGMENT_LEN) : 0;
362
- const char *ptr = start;
398
+ const char *cursor = state->cursor;
399
+ long column = 0;
400
+ long line = 1;
363
401
 
364
- if (len == PARSE_ERROR_FRAGMENT_LEN) {
365
- MEMCPY(buffer, start, char, PARSE_ERROR_FRAGMENT_LEN);
402
+ while (cursor >= state->start) {
403
+ if (*cursor-- == '\n') {
404
+ break;
405
+ }
406
+ column++;
407
+ }
366
408
 
367
- while (buffer[len - 1] >= 0x80 && buffer[len - 1] < 0xC0) { // Is continuation byte
368
- len--;
409
+ while (cursor >= state->start) {
410
+ if (*cursor-- == '\n') {
411
+ line++;
369
412
  }
413
+ }
370
414
 
371
- if (buffer[len - 1] >= 0xC0) { // multibyte character start
372
- len--;
415
+ const char *ptr = "EOF";
416
+ if (state->cursor && state->cursor < state->end) {
417
+ ptr = state->cursor;
418
+ size_t len = 0;
419
+ while (len < PARSE_ERROR_FRAGMENT_LEN) {
420
+ char ch = ptr[len];
421
+ if (!ch || ch == '\n' || ch == ' ' || ch == '\t' || ch == '\r') {
422
+ break;
423
+ }
424
+ len++;
373
425
  }
374
426
 
375
- buffer[len] = '\0';
376
- ptr = (const char *)buffer;
427
+ if (len) {
428
+ buffer[0] = '\'';
429
+ MEMCPY(buffer + 1, ptr, char, len);
430
+
431
+ while (buffer[len] >= 0x80 && buffer[len] < 0xC0) { // Is continuation byte
432
+ len--;
433
+ }
434
+
435
+ if (buffer[len] >= 0xC0) { // multibyte character start
436
+ len--;
437
+ }
438
+
439
+ buffer[len + 1] = '\'';
440
+ buffer[len + 2] = '\0';
441
+ ptr = (const char *)buffer;
442
+ }
377
443
  }
378
444
 
379
- rb_enc_raise(enc_utf8, rb_path2class("JSON::ParserError"), format, ptr);
445
+ VALUE msg = rb_sprintf(format, ptr);
446
+ VALUE message = rb_enc_sprintf(enc_utf8, "%s at line %ld column %ld", RSTRING_PTR(msg), line, column);
447
+ RB_GC_GUARD(msg);
448
+
449
+ VALUE exc = rb_exc_new_str(rb_path2class("JSON::ParserError"), message);
450
+ rb_ivar_set(exc, rb_intern("@line"), LONG2NUM(line));
451
+ rb_ivar_set(exc, rb_intern("@column"), LONG2NUM(column));
452
+ rb_exc_raise(exc);
453
+ }
454
+
455
+ #ifdef RBIMPL_ATTR_NORETURN
456
+ RBIMPL_ATTR_NORETURN()
457
+ #endif
458
+ static void raise_parse_error_at(const char *format, JSON_ParserState *state, const char *at)
459
+ {
460
+ state->cursor = at;
461
+ raise_parse_error(format, state);
380
462
  }
381
463
 
382
464
  /* unicode */
@@ -398,78 +480,25 @@ static const signed char digit_values[256] = {
398
480
  -1, -1, -1, -1, -1, -1, -1
399
481
  };
400
482
 
401
- static uint32_t unescape_unicode(const unsigned char *p)
483
+ static uint32_t unescape_unicode(JSON_ParserState *state, const unsigned char *p)
402
484
  {
403
485
  signed char b;
404
486
  uint32_t result = 0;
405
487
  b = digit_values[p[0]];
406
- if (b < 0) raise_parse_error("incomplete unicode character escape sequence at '%s'", (char *)p - 2);
488
+ if (b < 0) raise_parse_error_at("incomplete unicode character escape sequence at %s", state, (char *)p - 2);
407
489
  result = (result << 4) | (unsigned char)b;
408
490
  b = digit_values[p[1]];
409
- if (b < 0) raise_parse_error("incomplete unicode character escape sequence at '%s'", (char *)p - 2);
491
+ if (b < 0) raise_parse_error_at("incomplete unicode character escape sequence at %s", state, (char *)p - 2);
410
492
  result = (result << 4) | (unsigned char)b;
411
493
  b = digit_values[p[2]];
412
- if (b < 0) raise_parse_error("incomplete unicode character escape sequence at '%s'", (char *)p - 2);
494
+ if (b < 0) raise_parse_error_at("incomplete unicode character escape sequence at %s", state, (char *)p - 2);
413
495
  result = (result << 4) | (unsigned char)b;
414
496
  b = digit_values[p[3]];
415
- if (b < 0) raise_parse_error("incomplete unicode character escape sequence at '%s'", (char *)p - 2);
497
+ if (b < 0) raise_parse_error_at("incomplete unicode character escape sequence at %s", state, (char *)p - 2);
416
498
  result = (result << 4) | (unsigned char)b;
417
499
  return result;
418
500
  }
419
501
 
420
- static int convert_UTF32_to_UTF8(char *buf, uint32_t ch)
421
- {
422
- int len = 1;
423
- if (ch <= 0x7F) {
424
- buf[0] = (char) ch;
425
- } else if (ch <= 0x07FF) {
426
- buf[0] = (char) ((ch >> 6) | 0xC0);
427
- buf[1] = (char) ((ch & 0x3F) | 0x80);
428
- len++;
429
- } else if (ch <= 0xFFFF) {
430
- buf[0] = (char) ((ch >> 12) | 0xE0);
431
- buf[1] = (char) (((ch >> 6) & 0x3F) | 0x80);
432
- buf[2] = (char) ((ch & 0x3F) | 0x80);
433
- len += 2;
434
- } else if (ch <= 0x1fffff) {
435
- buf[0] =(char) ((ch >> 18) | 0xF0);
436
- buf[1] =(char) (((ch >> 12) & 0x3F) | 0x80);
437
- buf[2] =(char) (((ch >> 6) & 0x3F) | 0x80);
438
- buf[3] =(char) ((ch & 0x3F) | 0x80);
439
- len += 3;
440
- } else {
441
- buf[0] = '?';
442
- }
443
- return len;
444
- }
445
-
446
- typedef struct JSON_ParserStruct {
447
- VALUE create_id;
448
- VALUE object_class;
449
- VALUE array_class;
450
- VALUE decimal_class;
451
- ID decimal_method_id;
452
- VALUE match_string;
453
- int max_nesting;
454
- bool allow_nan;
455
- bool allow_trailing_comma;
456
- bool parsing_name;
457
- bool symbolize_names;
458
- bool freeze;
459
- bool create_additions;
460
- bool deprecated_create_additions;
461
- } JSON_ParserConfig;
462
-
463
- typedef struct JSON_ParserStateStruct {
464
- VALUE stack_handle;
465
- const char *cursor;
466
- const char *end;
467
- rvalue_stack *stack;
468
- rvalue_cache name_cache;
469
- int in_array;
470
- int current_nesting;
471
- } JSON_ParserState;
472
-
473
502
  #define GET_PARSER_CONFIG \
474
503
  JSON_ParserConfig *config; \
475
504
  TypedData_Get_Struct(self, JSON_ParserConfig, &JSON_ParserConfig_type, config)
@@ -503,8 +532,7 @@ json_eat_comments(JSON_ParserState *state)
503
532
  while (true) {
504
533
  state->cursor = memchr(state->cursor, '*', state->end - state->cursor);
505
534
  if (!state->cursor) {
506
- state->cursor = state->end;
507
- raise_parse_error("unexpected end of input, expected closing '*/'", state->cursor);
535
+ raise_parse_error_at("unexpected end of input, expected closing '*/'", state, state->end);
508
536
  } else {
509
537
  state->cursor++;
510
538
  if (state->cursor < state->end && *state->cursor == '/') {
@@ -516,11 +544,11 @@ json_eat_comments(JSON_ParserState *state)
516
544
  break;
517
545
  }
518
546
  default:
519
- raise_parse_error("unexpected token at '%s'", state->cursor);
547
+ raise_parse_error("unexpected token %s", state);
520
548
  break;
521
549
  }
522
550
  } else {
523
- raise_parse_error("unexpected token at '%s'", state->cursor);
551
+ raise_parse_error("unexpected token %s", state);
524
552
  }
525
553
  }
526
554
 
@@ -639,9 +667,9 @@ static VALUE json_string_unescape(JSON_ParserState *state, const char *string, c
639
667
  break;
640
668
  case 'u':
641
669
  if (pe > stringEnd - 5) {
642
- raise_parse_error("incomplete unicode character escape sequence at '%s'", p);
670
+ raise_parse_error_at("incomplete unicode character escape sequence at %s", state, p);
643
671
  } else {
644
- uint32_t ch = unescape_unicode((unsigned char *) ++pe);
672
+ uint32_t ch = unescape_unicode(state, (unsigned char *) ++pe);
645
673
  pe += 3;
646
674
  /* To handle values above U+FFFF, we take a sequence of
647
675
  * \uXXXX escapes in the U+D800..U+DBFF then
@@ -656,10 +684,10 @@ static VALUE json_string_unescape(JSON_ParserState *state, const char *string, c
656
684
  if ((ch & 0xFC00) == 0xD800) {
657
685
  pe++;
658
686
  if (pe > stringEnd - 6) {
659
- raise_parse_error("incomplete surrogate pair at '%s'", p);
687
+ raise_parse_error_at("incomplete surrogate pair at %s", state, p);
660
688
  }
661
689
  if (pe[0] == '\\' && pe[1] == 'u') {
662
- uint32_t sur = unescape_unicode((unsigned char *) pe + 2);
690
+ uint32_t sur = unescape_unicode(state, (unsigned char *) pe + 2);
663
691
  ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
664
692
  | (sur & 0x3FF));
665
693
  pe += 5;
@@ -769,18 +797,7 @@ static VALUE json_decode_float(JSON_ParserConfig *config, const char *start, con
769
797
 
770
798
  static inline VALUE json_decode_array(JSON_ParserState *state, JSON_ParserConfig *config, long count)
771
799
  {
772
- VALUE array;
773
- if (RB_UNLIKELY(config->array_class)) {
774
- array = rb_class_new_instance(0, 0, config->array_class);
775
- VALUE *items = rvalue_stack_peek(state->stack, count);
776
- long index;
777
- for (index = 0; index < count; index++) {
778
- rb_funcall(array, i_leftshift, 1, items[index]);
779
- }
780
- } else {
781
- array = rb_ary_new_from_values(count, rvalue_stack_peek(state->stack, count));
782
- }
783
-
800
+ VALUE array = rb_ary_new_from_values(count, rvalue_stack_peek(state->stack, count));
784
801
  rvalue_stack_pop(state->stack, count);
785
802
 
786
803
  if (config->freeze) {
@@ -792,41 +809,11 @@ static inline VALUE json_decode_array(JSON_ParserState *state, JSON_ParserConfig
792
809
 
793
810
  static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfig *config, long count)
794
811
  {
795
- VALUE object;
796
- if (RB_UNLIKELY(config->object_class)) {
797
- object = rb_class_new_instance(0, 0, config->object_class);
798
- long index = 0;
799
- VALUE *items = rvalue_stack_peek(state->stack, count);
800
- while (index < count) {
801
- VALUE name = items[index++];
802
- VALUE value = items[index++];
803
- rb_funcall(object, i_aset, 2, name, value);
804
- }
805
- } else {
806
- object = rb_hash_new_capa(count);
807
- rb_hash_bulk_insert(count, rvalue_stack_peek(state->stack, count), object);
808
- }
812
+ VALUE object = rb_hash_new_capa(count);
813
+ rb_hash_bulk_insert(count, rvalue_stack_peek(state->stack, count), object);
809
814
 
810
815
  rvalue_stack_pop(state->stack, count);
811
816
 
812
- if (RB_UNLIKELY(config->create_additions)) {
813
- VALUE klassname;
814
- if (config->object_class) {
815
- klassname = rb_funcall(object, i_aref, 1, config->create_id);
816
- } else {
817
- klassname = rb_hash_aref(object, config->create_id);
818
- }
819
- if (!NIL_P(klassname)) {
820
- VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname);
821
- if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) {
822
- if (config->deprecated_create_additions) {
823
- json_deprecated(deprecated_create_additions_warning);
824
- }
825
- object = rb_funcall(klass, i_json_create, 1, object);
826
- }
827
- }
828
- }
829
-
830
817
  if (config->freeze) {
831
818
  RB_OBJ_FREEZE(object);
832
819
  }
@@ -834,17 +821,6 @@ static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfi
834
821
  return object;
835
822
  }
836
823
 
837
- static int match_i(VALUE regexp, VALUE klass, VALUE memo)
838
- {
839
- if (regexp == Qundef) return ST_STOP;
840
- if (RTEST(rb_funcall(klass, i_json_creatable_p, 0)) &&
841
- RTEST(rb_funcall(regexp, i_match, 1, rb_ary_entry(memo, 0)))) {
842
- rb_ary_push(memo, klass);
843
- return ST_STOP;
844
- }
845
- return ST_CONTINUE;
846
- }
847
-
848
824
  static inline VALUE json_decode_string(JSON_ParserState *state, JSON_ParserConfig *config, const char *start, const char *end, bool escaped, bool is_name)
849
825
  {
850
826
  VALUE string;
@@ -856,21 +832,17 @@ static inline VALUE json_decode_string(JSON_ParserState *state, JSON_ParserConfi
856
832
  string = json_string_fastpath(state, start, end, is_name, intern, symbolize);
857
833
  }
858
834
 
859
- if (RB_UNLIKELY(config->create_additions && RTEST(config->match_string))) {
860
- VALUE klass;
861
- VALUE memo = rb_ary_new2(2);
862
- rb_ary_push(memo, string);
863
- rb_hash_foreach(config->match_string, match_i, memo);
864
- klass = rb_ary_entry(memo, 1);
865
- if (RTEST(klass)) {
866
- string = rb_funcall(klass, i_json_create, 1, string);
867
- }
868
- }
869
-
870
835
  return string;
871
836
  }
872
837
 
873
- #define PUSH(result) rvalue_stack_push(state->stack, result, &state->stack_handle, &state->stack)
838
+ static inline VALUE json_push_value(JSON_ParserState *state, JSON_ParserConfig *config, VALUE value)
839
+ {
840
+ if (RB_UNLIKELY(config->on_load_proc)) {
841
+ value = rb_proc_call_with_block(config->on_load_proc, 1, &value, Qnil);
842
+ }
843
+ rvalue_stack_push(state->stack, value, &state->stack_handle, &state->stack);
844
+ return value;
845
+ }
874
846
 
875
847
  static const bool string_scan[256] = {
876
848
  // ASCII Control Characters
@@ -897,18 +869,18 @@ static inline VALUE json_parse_string(JSON_ParserState *state, JSON_ParserConfig
897
869
  case '"': {
898
870
  VALUE string = json_decode_string(state, config, start, state->cursor, escaped, is_name);
899
871
  state->cursor++;
900
- return PUSH(string);
872
+ return json_push_value(state, config, string);
901
873
  }
902
874
  case '\\': {
903
875
  state->cursor++;
904
876
  escaped = true;
905
877
  if ((unsigned char)*state->cursor < 0x20) {
906
- raise_parse_error("invalid ASCII control character in string: %s", state->cursor);
878
+ raise_parse_error("invalid ASCII control character in string: %s", state);
907
879
  }
908
880
  break;
909
881
  }
910
882
  default:
911
- raise_parse_error("invalid ASCII control character in string: %s", state->cursor);
883
+ raise_parse_error("invalid ASCII control character in string: %s", state);
912
884
  break;
913
885
  }
914
886
  }
@@ -916,7 +888,7 @@ static inline VALUE json_parse_string(JSON_ParserState *state, JSON_ParserConfig
916
888
  state->cursor++;
917
889
  }
918
890
 
919
- raise_parse_error("unexpected end of input, expected closing \"", state->cursor);
891
+ raise_parse_error("unexpected end of input, expected closing \"", state);
920
892
  return Qfalse;
921
893
  }
922
894
 
@@ -924,60 +896,60 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
924
896
  {
925
897
  json_eat_whitespace(state);
926
898
  if (state->cursor >= state->end) {
927
- raise_parse_error("unexpected end of input", state->cursor);
899
+ raise_parse_error("unexpected end of input", state);
928
900
  }
929
901
 
930
902
  switch (*state->cursor) {
931
903
  case 'n':
932
904
  if ((state->end - state->cursor >= 4) && (memcmp(state->cursor, "null", 4) == 0)) {
933
905
  state->cursor += 4;
934
- return PUSH(Qnil);
906
+ return json_push_value(state, config, Qnil);
935
907
  }
936
908
 
937
- raise_parse_error("unexpected token at '%s'", state->cursor);
909
+ raise_parse_error("unexpected token %s", state);
938
910
  break;
939
911
  case 't':
940
912
  if ((state->end - state->cursor >= 4) && (memcmp(state->cursor, "true", 4) == 0)) {
941
913
  state->cursor += 4;
942
- return PUSH(Qtrue);
914
+ return json_push_value(state, config, Qtrue);
943
915
  }
944
916
 
945
- raise_parse_error("unexpected token at '%s'", state->cursor);
917
+ raise_parse_error("unexpected token %s", state);
946
918
  break;
947
919
  case 'f':
948
920
  // Note: memcmp with a small power of two compile to an integer comparison
949
921
  if ((state->end - state->cursor >= 5) && (memcmp(state->cursor + 1, "alse", 4) == 0)) {
950
922
  state->cursor += 5;
951
- return PUSH(Qfalse);
923
+ return json_push_value(state, config, Qfalse);
952
924
  }
953
925
 
954
- raise_parse_error("unexpected token at '%s'", state->cursor);
926
+ raise_parse_error("unexpected token %s", state);
955
927
  break;
956
928
  case 'N':
957
929
  // Note: memcmp with a small power of two compile to an integer comparison
958
930
  if (config->allow_nan && (state->end - state->cursor >= 3) && (memcmp(state->cursor + 1, "aN", 2) == 0)) {
959
931
  state->cursor += 3;
960
- return PUSH(CNaN);
932
+ return json_push_value(state, config, CNaN);
961
933
  }
962
934
 
963
- raise_parse_error("unexpected token at '%s'", state->cursor);
935
+ raise_parse_error("unexpected token %s", state);
964
936
  break;
965
937
  case 'I':
966
938
  if (config->allow_nan && (state->end - state->cursor >= 8) && (memcmp(state->cursor, "Infinity", 8) == 0)) {
967
939
  state->cursor += 8;
968
- return PUSH(CInfinity);
940
+ return json_push_value(state, config, CInfinity);
969
941
  }
970
942
 
971
- raise_parse_error("unexpected token at '%s'", state->cursor);
943
+ raise_parse_error("unexpected token %s", state);
972
944
  break;
973
945
  case '-':
974
946
  // Note: memcmp with a small power of two compile to an integer comparison
975
947
  if ((state->end - state->cursor >= 9) && (memcmp(state->cursor + 1, "Infinity", 8) == 0)) {
976
948
  if (config->allow_nan) {
977
949
  state->cursor += 9;
978
- return PUSH(CMinusInfinity);
950
+ return json_push_value(state, config, CMinusInfinity);
979
951
  } else {
980
- raise_parse_error("unexpected token at '%s'", state->cursor);
952
+ raise_parse_error("unexpected token %s", state);
981
953
  }
982
954
  }
983
955
  // Fallthrough
@@ -995,11 +967,11 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
995
967
  long integer_length = state->cursor - start;
996
968
 
997
969
  if (RB_UNLIKELY(start[0] == '0' && integer_length > 1)) {
998
- raise_parse_error("invalid number: %s", start);
970
+ raise_parse_error_at("invalid number: %s", state, start);
999
971
  } else if (RB_UNLIKELY(integer_length > 2 && start[0] == '-' && start[1] == '0')) {
1000
- raise_parse_error("invalid number: %s", start);
972
+ raise_parse_error_at("invalid number: %s", state, start);
1001
973
  } else if (RB_UNLIKELY(integer_length == 1 && start[0] == '-')) {
1002
- raise_parse_error("invalid number: %s", start);
974
+ raise_parse_error_at("invalid number: %s", state, start);
1003
975
  }
1004
976
 
1005
977
  if ((state->cursor < state->end) && (*state->cursor == '.')) {
@@ -1007,7 +979,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1007
979
  state->cursor++;
1008
980
 
1009
981
  if (state->cursor == state->end || *state->cursor < '0' || *state->cursor > '9') {
1010
- raise_parse_error("invalid number: %s", state->cursor);
982
+ raise_parse_error("invalid number: %s", state);
1011
983
  }
1012
984
 
1013
985
  while ((state->cursor < state->end) && (*state->cursor >= '0') && (*state->cursor <= '9')) {
@@ -1023,7 +995,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1023
995
  }
1024
996
 
1025
997
  if (state->cursor == state->end || *state->cursor < '0' || *state->cursor > '9') {
1026
- raise_parse_error("invalid number: %s", state->cursor);
998
+ raise_parse_error("invalid number: %s", state);
1027
999
  }
1028
1000
 
1029
1001
  while ((state->cursor < state->end) && (*state->cursor >= '0') && (*state->cursor <= '9')) {
@@ -1032,9 +1004,9 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1032
1004
  }
1033
1005
 
1034
1006
  if (integer) {
1035
- return PUSH(json_decode_integer(start, state->cursor));
1007
+ return json_push_value(state, config, json_decode_integer(start, state->cursor));
1036
1008
  }
1037
- return PUSH(json_decode_float(config, start, state->cursor));
1009
+ return json_push_value(state, config, json_decode_float(config, start, state->cursor));
1038
1010
  }
1039
1011
  case '"': {
1040
1012
  // %r{\A"[^"\\\t\n\x00]*(?:\\[bfnrtu\\/"][^"\\]*)*"}
@@ -1048,7 +1020,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1048
1020
 
1049
1021
  if ((state->cursor < state->end) && (*state->cursor == ']')) {
1050
1022
  state->cursor++;
1051
- return PUSH(json_decode_array(state, config, 0));
1023
+ return json_push_value(state, config, json_decode_array(state, config, 0));
1052
1024
  } else {
1053
1025
  state->current_nesting++;
1054
1026
  if (RB_UNLIKELY(config->max_nesting && (config->max_nesting < state->current_nesting))) {
@@ -1067,7 +1039,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1067
1039
  long count = state->stack->head - stack_head;
1068
1040
  state->current_nesting--;
1069
1041
  state->in_array--;
1070
- return PUSH(json_decode_array(state, config, count));
1042
+ return json_push_value(state, config, json_decode_array(state, config, count));
1071
1043
  }
1072
1044
 
1073
1045
  if (*state->cursor == ',') {
@@ -1083,7 +1055,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1083
1055
  }
1084
1056
  }
1085
1057
 
1086
- raise_parse_error("expected ',' or ']' after array value", state->cursor);
1058
+ raise_parse_error("expected ',' or ']' after array value", state);
1087
1059
  }
1088
1060
  break;
1089
1061
  }
@@ -1094,7 +1066,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1094
1066
 
1095
1067
  if ((state->cursor < state->end) && (*state->cursor == '}')) {
1096
1068
  state->cursor++;
1097
- return PUSH(json_decode_object(state, config, 0));
1069
+ return json_push_value(state, config, json_decode_object(state, config, 0));
1098
1070
  } else {
1099
1071
  state->current_nesting++;
1100
1072
  if (RB_UNLIKELY(config->max_nesting && (config->max_nesting < state->current_nesting))) {
@@ -1102,13 +1074,13 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1102
1074
  }
1103
1075
 
1104
1076
  if (*state->cursor != '"') {
1105
- raise_parse_error("expected object key, got '%s", state->cursor);
1077
+ raise_parse_error("expected object key, got %s", state);
1106
1078
  }
1107
1079
  json_parse_string(state, config, true);
1108
1080
 
1109
1081
  json_eat_whitespace(state);
1110
1082
  if ((state->cursor >= state->end) || (*state->cursor != ':')) {
1111
- raise_parse_error("expected ':' after object key", state->cursor);
1083
+ raise_parse_error("expected ':' after object key", state);
1112
1084
  }
1113
1085
  state->cursor++;
1114
1086
 
@@ -1123,7 +1095,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1123
1095
  state->cursor++;
1124
1096
  state->current_nesting--;
1125
1097
  long count = state->stack->head - stack_head;
1126
- return PUSH(json_decode_object(state, config, count));
1098
+ return json_push_value(state, config, json_decode_object(state, config, count));
1127
1099
  }
1128
1100
 
1129
1101
  if (*state->cursor == ',') {
@@ -1137,13 +1109,13 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1137
1109
  }
1138
1110
 
1139
1111
  if (*state->cursor != '"') {
1140
- raise_parse_error("expected object key, got: '%s'", state->cursor);
1112
+ raise_parse_error("expected object key, got: %s", state);
1141
1113
  }
1142
1114
  json_parse_string(state, config, true);
1143
1115
 
1144
1116
  json_eat_whitespace(state);
1145
1117
  if ((state->cursor >= state->end) || (*state->cursor != ':')) {
1146
- raise_parse_error("expected ':' after object key, got: '%s", state->cursor);
1118
+ raise_parse_error("expected ':' after object key, got: %s", state);
1147
1119
  }
1148
1120
  state->cursor++;
1149
1121
 
@@ -1153,24 +1125,24 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1153
1125
  }
1154
1126
  }
1155
1127
 
1156
- raise_parse_error("expected ',' or '}' after object value, got: '%s'", state->cursor);
1128
+ raise_parse_error("expected ',' or '}' after object value, got: %s", state);
1157
1129
  }
1158
1130
  break;
1159
1131
  }
1160
1132
 
1161
1133
  default:
1162
- raise_parse_error("unexpected character: '%s'", state->cursor);
1134
+ raise_parse_error("unexpected character: %s", state);
1163
1135
  break;
1164
1136
  }
1165
1137
 
1166
- raise_parse_error("unreacheable: '%s'", state->cursor);
1138
+ raise_parse_error("unreacheable: %s", state);
1167
1139
  }
1168
1140
 
1169
1141
  static void json_ensure_eof(JSON_ParserState *state)
1170
1142
  {
1171
1143
  json_eat_whitespace(state);
1172
1144
  if (state->cursor != state->end) {
1173
- raise_parse_error("unexpected token at end of stream '%s'", state->cursor);
1145
+ raise_parse_error("unexpected token at end of stream %s", state);
1174
1146
  }
1175
1147
  }
1176
1148
 
@@ -1211,10 +1183,7 @@ static int parser_config_init_i(VALUE key, VALUE val, VALUE data)
1211
1183
  else if (key == sym_allow_trailing_comma) { config->allow_trailing_comma = RTEST(val); }
1212
1184
  else if (key == sym_symbolize_names) { config->symbolize_names = RTEST(val); }
1213
1185
  else if (key == sym_freeze) { config->freeze = RTEST(val); }
1214
- else if (key == sym_create_id) { config->create_id = RTEST(val) ? val : Qfalse; }
1215
- else if (key == sym_object_class) { config->object_class = RTEST(val) ? val : Qfalse; }
1216
- else if (key == sym_array_class) { config->array_class = RTEST(val) ? val : Qfalse; }
1217
- else if (key == sym_match_string) { config->match_string = RTEST(val) ? val : Qfalse; }
1186
+ else if (key == sym_on_load) { config->on_load_proc = RTEST(val) ? val : Qfalse; }
1218
1187
  else if (key == sym_decimal_class) {
1219
1188
  if (RTEST(val)) {
1220
1189
  if (rb_respond_to(val, i_try_convert)) {
@@ -1244,15 +1213,6 @@ static int parser_config_init_i(VALUE key, VALUE val, VALUE data)
1244
1213
  }
1245
1214
  }
1246
1215
  }
1247
- else if (key == sym_create_additions) {
1248
- if (NIL_P(val)) {
1249
- config->create_additions = true;
1250
- config->deprecated_create_additions = true;
1251
- } else {
1252
- config->create_additions = RTEST(val);
1253
- config->deprecated_create_additions = false;
1254
- }
1255
- }
1256
1216
 
1257
1217
  return ST_CONTINUE;
1258
1218
  }
@@ -1267,16 +1227,6 @@ static void parser_config_init(JSON_ParserConfig *config, VALUE opts)
1267
1227
  // We assume in most cases few keys are set so it's faster to go over
1268
1228
  // the provided keys than to check all possible keys.
1269
1229
  rb_hash_foreach(opts, parser_config_init_i, (VALUE)config);
1270
-
1271
- if (config->symbolize_names && config->create_additions) {
1272
- rb_raise(rb_eArgError,
1273
- "options :symbolize_names and :create_additions cannot be "
1274
- " used in conjunction");
1275
- }
1276
-
1277
- if (config->create_additions && !config->create_id) {
1278
- config->create_id = rb_funcall(mJSON, i_create_id, 0);
1279
- }
1280
1230
  }
1281
1231
 
1282
1232
  }
@@ -1301,15 +1251,6 @@ static void parser_config_init(JSON_ParserConfig *config, VALUE opts)
1301
1251
  * (keys) in a JSON object. Otherwise strings are returned, which is
1302
1252
  * also the default. It's not possible to use this option in
1303
1253
  * conjunction with the *create_additions* option.
1304
- * * *create_additions*: If set to false, the Parser doesn't create
1305
- * additions even if a matching class and create_id was found. This option
1306
- * defaults to false.
1307
- * * *object_class*: Defaults to Hash. If another type is provided, it will be used
1308
- * instead of Hash to represent JSON objects. The type must respond to
1309
- * +new+ without arguments, and return an object that respond to +[]=+.
1310
- * * *array_class*: Defaults to Array If another type is provided, it will be used
1311
- * instead of Hash to represent JSON arrays. The type must respond to
1312
- * +new+ without arguments, and return an object that respond to +<<+.
1313
1254
  * * *decimal_class*: Specifies which class to use instead of the default
1314
1255
  * (Float) when parsing decimal numbers. This class must accept a single
1315
1256
  * string argument in its constructor.
@@ -1320,11 +1261,7 @@ static VALUE cParserConfig_initialize(VALUE self, VALUE opts)
1320
1261
 
1321
1262
  parser_config_init(config, opts);
1322
1263
 
1323
- RB_OBJ_WRITTEN(self, Qundef, config->create_id);
1324
- RB_OBJ_WRITTEN(self, Qundef, config->object_class);
1325
- RB_OBJ_WRITTEN(self, Qundef, config->array_class);
1326
1264
  RB_OBJ_WRITTEN(self, Qundef, config->decimal_class);
1327
- RB_OBJ_WRITTEN(self, Qundef, config->match_string);
1328
1265
 
1329
1266
  return self;
1330
1267
  }
@@ -1341,9 +1278,14 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
1341
1278
  .capa = RVALUE_STACK_INITIAL_CAPA,
1342
1279
  };
1343
1280
 
1281
+ long len;
1282
+ const char *start;
1283
+ RSTRING_GETMEM(Vsource, start, len);
1284
+
1344
1285
  JSON_ParserState _state = {
1345
- .cursor = RSTRING_PTR(Vsource),
1346
- .end = RSTRING_END(Vsource),
1286
+ .start = start,
1287
+ .cursor = start,
1288
+ .end = start + len,
1347
1289
  .stack = &stack,
1348
1290
  };
1349
1291
  JSON_ParserState *state = &_state;
@@ -1387,11 +1329,8 @@ static VALUE cParser_m_parse(VALUE klass, VALUE Vsource, VALUE opts)
1387
1329
  static void JSON_ParserConfig_mark(void *ptr)
1388
1330
  {
1389
1331
  JSON_ParserConfig *config = ptr;
1390
- rb_gc_mark(config->create_id);
1391
- rb_gc_mark(config->object_class);
1392
- rb_gc_mark(config->array_class);
1332
+ rb_gc_mark(config->on_load_proc);
1393
1333
  rb_gc_mark(config->decimal_class);
1394
- rb_gc_mark(config->match_string);
1395
1334
  }
1396
1335
 
1397
1336
  static void JSON_ParserConfig_free(void *ptr)
@@ -1459,19 +1398,10 @@ void Init_parser(void)
1459
1398
  sym_allow_trailing_comma = ID2SYM(rb_intern("allow_trailing_comma"));
1460
1399
  sym_symbolize_names = ID2SYM(rb_intern("symbolize_names"));
1461
1400
  sym_freeze = ID2SYM(rb_intern("freeze"));
1462
- sym_create_additions = ID2SYM(rb_intern("create_additions"));
1463
- sym_create_id = ID2SYM(rb_intern("create_id"));
1464
- sym_object_class = ID2SYM(rb_intern("object_class"));
1465
- sym_array_class = ID2SYM(rb_intern("array_class"));
1401
+ sym_on_load = ID2SYM(rb_intern("on_load"));
1466
1402
  sym_decimal_class = ID2SYM(rb_intern("decimal_class"));
1467
- sym_match_string = ID2SYM(rb_intern("match_string"));
1468
1403
 
1469
- i_create_id = rb_intern("create_id");
1470
- i_json_creatable_p = rb_intern("json_creatable?");
1471
- i_json_create = rb_intern("json_create");
1472
1404
  i_chr = rb_intern("chr");
1473
- i_match = rb_intern("match");
1474
- i_deep_const_get = rb_intern("deep_const_get");
1475
1405
  i_aset = rb_intern("[]=");
1476
1406
  i_aref = rb_intern("[]");
1477
1407
  i_leftshift = rb_intern("<<");