json 2.3.0 → 2.6.1

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.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +71 -5
  3. data/README.md +19 -3
  4. data/VERSION +1 -1
  5. data/ext/json/ext/generator/generator.c +132 -23
  6. data/ext/json/ext/generator/generator.h +5 -2
  7. data/ext/json/ext/parser/extconf.rb +26 -0
  8. data/ext/json/ext/parser/parser.c +2970 -1768
  9. data/ext/json/ext/parser/parser.h +6 -1
  10. data/ext/json/ext/parser/parser.rl +119 -38
  11. data/ext/json/extconf.rb +1 -0
  12. data/json.gemspec +0 -0
  13. data/lib/json/add/complex.rb +0 -1
  14. data/lib/json/add/rational.rb +0 -1
  15. data/lib/json/common.rb +370 -123
  16. data/lib/json/pure/generator.rb +29 -9
  17. data/lib/json/pure/parser.rb +23 -5
  18. data/lib/json/version.rb +1 -1
  19. data/lib/json.rb +549 -29
  20. metadata +17 -109
  21. data/.gitignore +0 -18
  22. data/.travis.yml +0 -24
  23. data/Gemfile +0 -14
  24. data/README-json-jruby.md +0 -33
  25. data/Rakefile +0 -413
  26. data/diagrams/.keep +0 -0
  27. data/install.rb +0 -23
  28. data/java/src/json/ext/ByteListTranscoder.java +0 -166
  29. data/java/src/json/ext/Generator.java +0 -466
  30. data/java/src/json/ext/GeneratorMethods.java +0 -231
  31. data/java/src/json/ext/GeneratorService.java +0 -42
  32. data/java/src/json/ext/GeneratorState.java +0 -490
  33. data/java/src/json/ext/OptionsReader.java +0 -113
  34. data/java/src/json/ext/Parser.java +0 -2362
  35. data/java/src/json/ext/Parser.rl +0 -893
  36. data/java/src/json/ext/ParserService.java +0 -34
  37. data/java/src/json/ext/RuntimeInfo.java +0 -116
  38. data/java/src/json/ext/StringDecoder.java +0 -166
  39. data/java/src/json/ext/StringEncoder.java +0 -111
  40. data/java/src/json/ext/Utils.java +0 -88
  41. data/json-java.gemspec +0 -37
  42. data/json_pure.gemspec +0 -38
  43. data/lib/json/ext/.keep +0 -0
  44. data/references/rfc7159.txt +0 -899
  45. data/tests/fixtures/fail10.json +0 -1
  46. data/tests/fixtures/fail11.json +0 -1
  47. data/tests/fixtures/fail12.json +0 -1
  48. data/tests/fixtures/fail13.json +0 -1
  49. data/tests/fixtures/fail14.json +0 -1
  50. data/tests/fixtures/fail18.json +0 -1
  51. data/tests/fixtures/fail19.json +0 -1
  52. data/tests/fixtures/fail2.json +0 -1
  53. data/tests/fixtures/fail20.json +0 -1
  54. data/tests/fixtures/fail21.json +0 -1
  55. data/tests/fixtures/fail22.json +0 -1
  56. data/tests/fixtures/fail23.json +0 -1
  57. data/tests/fixtures/fail24.json +0 -1
  58. data/tests/fixtures/fail25.json +0 -1
  59. data/tests/fixtures/fail27.json +0 -2
  60. data/tests/fixtures/fail28.json +0 -2
  61. data/tests/fixtures/fail3.json +0 -1
  62. data/tests/fixtures/fail4.json +0 -1
  63. data/tests/fixtures/fail5.json +0 -1
  64. data/tests/fixtures/fail6.json +0 -1
  65. data/tests/fixtures/fail7.json +0 -1
  66. data/tests/fixtures/fail8.json +0 -1
  67. data/tests/fixtures/fail9.json +0 -1
  68. data/tests/fixtures/obsolete_fail1.json +0 -1
  69. data/tests/fixtures/pass1.json +0 -56
  70. data/tests/fixtures/pass15.json +0 -1
  71. data/tests/fixtures/pass16.json +0 -1
  72. data/tests/fixtures/pass17.json +0 -1
  73. data/tests/fixtures/pass2.json +0 -1
  74. data/tests/fixtures/pass26.json +0 -1
  75. data/tests/fixtures/pass3.json +0 -6
  76. data/tests/json_addition_test.rb +0 -203
  77. data/tests/json_common_interface_test.rb +0 -126
  78. data/tests/json_encoding_test.rb +0 -107
  79. data/tests/json_ext_parser_test.rb +0 -15
  80. data/tests/json_fixtures_test.rb +0 -32
  81. data/tests/json_generator_test.rb +0 -421
  82. data/tests/json_generic_object_test.rb +0 -82
  83. data/tests/json_parser_test.rb +0 -472
  84. data/tests/json_string_matching_test.rb +0 -38
  85. data/tests/test_helper.rb +0 -17
  86. data/tools/diff.sh +0 -18
  87. data/tools/fuzz.rb +0 -131
  88. data/tools/server.rb +0 -62
@@ -13,6 +13,10 @@
13
13
  #include "st.h"
14
14
  #endif
15
15
 
16
+ #ifndef MAYBE_UNUSED
17
+ # define MAYBE_UNUSED(x) x
18
+ #endif
19
+
16
20
  #define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key))
17
21
 
18
22
  /* unicode */
@@ -37,6 +41,7 @@ typedef struct JSON_ParserStruct {
37
41
  int allow_nan;
38
42
  int parsing_name;
39
43
  int symbolize_names;
44
+ int freeze;
40
45
  VALUE object_class;
41
46
  VALUE array_class;
42
47
  VALUE decimal_class;
@@ -62,7 +67,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
62
67
  static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
63
68
  static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
64
69
  static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
65
- static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd);
70
+ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize);
66
71
  static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
67
72
  static VALUE convert_encoding(VALUE source);
68
73
  static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self);
@@ -89,13 +89,12 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
89
89
 
90
90
  static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
91
91
  static VALUE CNaN, CInfinity, CMinusInfinity;
92
- static VALUE cBigDecimal = Qundef;
93
92
 
94
93
  static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
95
94
  i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
96
95
  i_object_class, i_array_class, i_decimal_class, i_key_p,
97
96
  i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
98
- i_leftshift, i_new, i_BigDecimal;
97
+ i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
99
98
 
100
99
  %%{
101
100
  machine JSON_common;
@@ -138,6 +137,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
138
137
  fhold; fbreak;
139
138
  } else {
140
139
  if (NIL_P(json->object_class)) {
140
+ OBJ_FREEZE(last_name);
141
141
  rb_hash_aset(*result, last_name, v);
142
142
  } else {
143
143
  rb_funcall(*result, i_aset, 2, last_name, v);
@@ -289,6 +289,10 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
289
289
  %% write init;
290
290
  %% write exec;
291
291
 
292
+ if (json->freeze) {
293
+ OBJ_FREEZE(*result);
294
+ }
295
+
292
296
  if (cs >= JSON_value_first_final) {
293
297
  return p;
294
298
  } else {
@@ -340,19 +344,6 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
340
344
  ) (^[0-9Ee.\-]? @exit );
341
345
  }%%
342
346
 
343
- static int is_bigdecimal_class(VALUE obj)
344
- {
345
- if (cBigDecimal == Qundef) {
346
- if (rb_const_defined(rb_cObject, i_BigDecimal)) {
347
- cBigDecimal = rb_const_get_at(rb_cObject, i_BigDecimal);
348
- }
349
- else {
350
- return 0;
351
- }
352
- }
353
- return obj == cBigDecimal;
354
- }
355
-
356
347
  static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
357
348
  {
358
349
  int cs = EVIL;
@@ -362,21 +353,46 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
362
353
  %% write exec;
363
354
 
364
355
  if (cs >= JSON_float_first_final) {
356
+ VALUE mod = Qnil;
357
+ ID method_id = 0;
358
+ if (rb_respond_to(json->decimal_class, i_try_convert)) {
359
+ mod = json->decimal_class;
360
+ method_id = i_try_convert;
361
+ } else if (rb_respond_to(json->decimal_class, i_new)) {
362
+ mod = json->decimal_class;
363
+ method_id = i_new;
364
+ } else if (RB_TYPE_P(json->decimal_class, T_CLASS)) {
365
+ VALUE name = rb_class_name(json->decimal_class);
366
+ const char *name_cstr = RSTRING_PTR(name);
367
+ const char *last_colon = strrchr(name_cstr, ':');
368
+ if (last_colon) {
369
+ const char *mod_path_end = last_colon - 1;
370
+ VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
371
+ mod = rb_path_to_class(mod_path);
372
+
373
+ const char *method_name_beg = last_colon + 1;
374
+ long before_len = method_name_beg - name_cstr;
375
+ long len = RSTRING_LEN(name) - before_len;
376
+ VALUE method_name = rb_str_substr(name, before_len, len);
377
+ method_id = SYM2ID(rb_str_intern(method_name));
378
+ } else {
379
+ mod = rb_mKernel;
380
+ method_id = SYM2ID(rb_str_intern(name));
381
+ }
382
+ }
383
+
365
384
  long len = p - json->memo;
366
385
  fbuffer_clear(json->fbuffer);
367
386
  fbuffer_append(json->fbuffer, json->memo, len);
368
387
  fbuffer_append_char(json->fbuffer, '\0');
369
- if (NIL_P(json->decimal_class)) {
370
- *result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
388
+
389
+ if (method_id) {
390
+ VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
391
+ *result = rb_funcallv(mod, method_id, 1, &text);
371
392
  } else {
372
- VALUE text;
373
- text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
374
- if (is_bigdecimal_class(json->decimal_class)) {
375
- *result = rb_funcall(Qnil, i_BigDecimal, 1, text);
376
- } else {
377
- *result = rb_funcall(json->decimal_class, i_new, 1, text);
378
- }
393
+ *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
379
394
  }
395
+
380
396
  return p + 1;
381
397
  } else {
382
398
  return NULL;
@@ -436,17 +452,29 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
436
452
  }
437
453
  }
438
454
 
439
- static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
455
+ static const size_t MAX_STACK_BUFFER_SIZE = 128;
456
+ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize)
440
457
  {
441
- char *p = string, *pe = string, *unescape;
458
+ VALUE result = Qnil;
459
+ size_t bufferSize = stringEnd - string;
460
+ char *p = string, *pe = string, *unescape, *bufferStart, *buffer;
442
461
  int unescape_len;
443
462
  char buf[4];
444
463
 
464
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
465
+ bufferStart = buffer = ALLOC_N(char, bufferSize);
466
+ } else {
467
+ bufferStart = buffer = ALLOCA_N(char, bufferSize);
468
+ }
469
+
445
470
  while (pe < stringEnd) {
446
471
  if (*pe == '\\') {
447
472
  unescape = (char *) "?";
448
473
  unescape_len = 1;
449
- if (pe > p) rb_str_buf_cat(result, p, pe - p);
474
+ if (pe > p) {
475
+ MEMCPY(buffer, p, char, pe - p);
476
+ buffer += pe - p;
477
+ }
450
478
  switch (*++pe) {
451
479
  case 'n':
452
480
  unescape = (char *) "\n";
@@ -471,6 +499,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
471
499
  break;
472
500
  case 'u':
473
501
  if (pe > stringEnd - 4) {
502
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
503
+ free(bufferStart);
504
+ }
474
505
  rb_enc_raise(
475
506
  EXC_ENCODING eParserError,
476
507
  "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
@@ -481,6 +512,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
481
512
  if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
482
513
  pe++;
483
514
  if (pe > stringEnd - 6) {
515
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
516
+ free(bufferStart);
517
+ }
484
518
  rb_enc_raise(
485
519
  EXC_ENCODING eParserError,
486
520
  "%u: incomplete surrogate pair at '%s'", __LINE__, p
@@ -504,13 +538,55 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
504
538
  p = pe;
505
539
  continue;
506
540
  }
507
- rb_str_buf_cat(result, unescape, unescape_len);
541
+ MEMCPY(buffer, unescape, char, unescape_len);
542
+ buffer += unescape_len;
508
543
  p = ++pe;
509
544
  } else {
510
545
  pe++;
511
546
  }
512
547
  }
513
- rb_str_buf_cat(result, p, pe - p);
548
+
549
+ if (pe > p) {
550
+ MEMCPY(buffer, p, char, pe - p);
551
+ buffer += pe - p;
552
+ }
553
+
554
+ # ifdef HAVE_RB_ENC_INTERNED_STR
555
+ if (intern) {
556
+ result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding());
557
+ } else {
558
+ result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
559
+ }
560
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
561
+ free(bufferStart);
562
+ }
563
+ # else
564
+ result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
565
+
566
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
567
+ free(bufferStart);
568
+ }
569
+
570
+ if (intern) {
571
+ # if STR_UMINUS_DEDUPE_FROZEN
572
+ // Starting from MRI 2.8 it is preferable to freeze the string
573
+ // before deduplication so that it can be interned directly
574
+ // otherwise it would be duplicated first which is wasteful.
575
+ result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
576
+ # elif STR_UMINUS_DEDUPE
577
+ // MRI 2.5 and older do not deduplicate strings that are already
578
+ // frozen.
579
+ result = rb_funcall(result, i_uminus, 0);
580
+ # else
581
+ result = rb_str_freeze(result);
582
+ # endif
583
+ }
584
+ # endif
585
+
586
+ if (symbolize) {
587
+ result = rb_str_intern(result);
588
+ }
589
+
514
590
  return result;
515
591
  }
516
592
 
@@ -521,12 +597,11 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
521
597
  write data;
522
598
 
523
599
  action parse_string {
524
- *result = json_string_unescape(*result, json->memo + 1, p);
600
+ *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
525
601
  if (NIL_P(*result)) {
526
602
  fhold;
527
603
  fbreak;
528
604
  } else {
529
- FORCE_UTF8(*result);
530
605
  fexec p + 1;
531
606
  }
532
607
  }
@@ -553,7 +628,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
553
628
  int cs = EVIL;
554
629
  VALUE match_string;
555
630
 
556
- *result = rb_str_buf_new(0);
557
631
  %% write init;
558
632
  json->memo = p;
559
633
  %% write exec;
@@ -569,11 +643,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
569
643
  }
570
644
  }
571
645
 
572
- if (json->symbolize_names && json->parsing_name) {
573
- *result = rb_str_intern(*result);
574
- } else if (RB_TYPE_P(*result, T_STRING)) {
575
- rb_str_resize(*result, RSTRING_LEN(*result));
576
- }
577
646
  if (cs >= JSON_string_first_final) {
578
647
  return p + 1;
579
648
  } else {
@@ -680,6 +749,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
680
749
  } else {
681
750
  json->symbolize_names = 0;
682
751
  }
752
+ tmp = ID2SYM(i_freeze);
753
+ if (option_given_p(opts, tmp)) {
754
+ json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
755
+ } else {
756
+ json->freeze = 0;
757
+ }
683
758
  tmp = ID2SYM(i_create_additions);
684
759
  if (option_given_p(opts, tmp)) {
685
760
  json->create_additions = RTEST(rb_hash_aref(opts, tmp));
@@ -842,6 +917,10 @@ static VALUE cParser_source(VALUE self)
842
917
 
843
918
  void Init_parser(void)
844
919
  {
920
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
921
+ rb_ext_ractor_safe(true);
922
+ #endif
923
+
845
924
  #undef rb_intern
846
925
  rb_require("json/common");
847
926
  mJSON = rb_define_module("JSON");
@@ -884,7 +963,9 @@ void Init_parser(void)
884
963
  i_aref = rb_intern("[]");
885
964
  i_leftshift = rb_intern("<<");
886
965
  i_new = rb_intern("new");
887
- i_BigDecimal = rb_intern("BigDecimal");
966
+ i_try_convert = rb_intern("try_convert");
967
+ i_freeze = rb_intern("freeze");
968
+ i_uminus = rb_intern("-@");
888
969
  }
889
970
 
890
971
  /*
data/ext/json/extconf.rb CHANGED
@@ -1,2 +1,3 @@
1
1
  require 'mkmf'
2
+
2
3
  create_makefile('json')
data/json.gemspec CHANGED
Binary file
@@ -2,7 +2,6 @@
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
5
- defined?(::Complex) or require 'complex'
6
5
 
7
6
  class Complex
8
7
 
@@ -2,7 +2,6 @@
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
5
- defined?(::Rational) or require 'rational'
6
5
 
7
6
  class Rational
8
7
  # Deserializes JSON string by converting numerator value <tt>n</tt>,