json 2.3.0 → 2.6.2

Sign up to get free protection for your applications and to get access to all the features.
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 +2979 -1768
  9. data/ext/json/ext/parser/parser.h +6 -1
  10. data/ext/json/ext/parser/parser.rl +128 -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,37 @@ 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
+ # ifdef HAVE_RB_ENC_INTERNED_STR
466
+ bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1);
467
+ # else
468
+ bufferStart = buffer = ALLOC_N(char, bufferSize);
469
+ # endif
470
+ } else {
471
+ # ifdef HAVE_RB_ENC_INTERNED_STR
472
+ bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1);
473
+ # else
474
+ bufferStart = buffer = ALLOCA_N(char, bufferSize);
475
+ # endif
476
+ }
477
+
445
478
  while (pe < stringEnd) {
446
479
  if (*pe == '\\') {
447
480
  unescape = (char *) "?";
448
481
  unescape_len = 1;
449
- if (pe > p) rb_str_buf_cat(result, p, pe - p);
482
+ if (pe > p) {
483
+ MEMCPY(buffer, p, char, pe - p);
484
+ buffer += pe - p;
485
+ }
450
486
  switch (*++pe) {
451
487
  case 'n':
452
488
  unescape = (char *) "\n";
@@ -471,6 +507,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
471
507
  break;
472
508
  case 'u':
473
509
  if (pe > stringEnd - 4) {
510
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
511
+ free(bufferStart);
512
+ }
474
513
  rb_enc_raise(
475
514
  EXC_ENCODING eParserError,
476
515
  "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
@@ -481,6 +520,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
481
520
  if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
482
521
  pe++;
483
522
  if (pe > stringEnd - 6) {
523
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
524
+ free(bufferStart);
525
+ }
484
526
  rb_enc_raise(
485
527
  EXC_ENCODING eParserError,
486
528
  "%u: incomplete surrogate pair at '%s'", __LINE__, p
@@ -504,13 +546,55 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
504
546
  p = pe;
505
547
  continue;
506
548
  }
507
- rb_str_buf_cat(result, unescape, unescape_len);
549
+ MEMCPY(buffer, unescape, char, unescape_len);
550
+ buffer += unescape_len;
508
551
  p = ++pe;
509
552
  } else {
510
553
  pe++;
511
554
  }
512
555
  }
513
- rb_str_buf_cat(result, p, pe - p);
556
+
557
+ if (pe > p) {
558
+ MEMCPY(buffer, p, char, pe - p);
559
+ buffer += pe - p;
560
+ }
561
+
562
+ # ifdef HAVE_RB_ENC_INTERNED_STR
563
+ if (intern) {
564
+ result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding());
565
+ } else {
566
+ result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
567
+ }
568
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
569
+ free(bufferStart);
570
+ }
571
+ # else
572
+ result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
573
+
574
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
575
+ free(bufferStart);
576
+ }
577
+
578
+ if (intern) {
579
+ # if STR_UMINUS_DEDUPE_FROZEN
580
+ // Starting from MRI 2.8 it is preferable to freeze the string
581
+ // before deduplication so that it can be interned directly
582
+ // otherwise it would be duplicated first which is wasteful.
583
+ result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
584
+ # elif STR_UMINUS_DEDUPE
585
+ // MRI 2.5 and older do not deduplicate strings that are already
586
+ // frozen.
587
+ result = rb_funcall(result, i_uminus, 0);
588
+ # else
589
+ result = rb_str_freeze(result);
590
+ # endif
591
+ }
592
+ # endif
593
+
594
+ if (symbolize) {
595
+ result = rb_str_intern(result);
596
+ }
597
+
514
598
  return result;
515
599
  }
516
600
 
@@ -521,12 +605,11 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
521
605
  write data;
522
606
 
523
607
  action parse_string {
524
- *result = json_string_unescape(*result, json->memo + 1, p);
608
+ *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
525
609
  if (NIL_P(*result)) {
526
610
  fhold;
527
611
  fbreak;
528
612
  } else {
529
- FORCE_UTF8(*result);
530
613
  fexec p + 1;
531
614
  }
532
615
  }
@@ -553,7 +636,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
553
636
  int cs = EVIL;
554
637
  VALUE match_string;
555
638
 
556
- *result = rb_str_buf_new(0);
557
639
  %% write init;
558
640
  json->memo = p;
559
641
  %% write exec;
@@ -569,11 +651,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
569
651
  }
570
652
  }
571
653
 
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
654
  if (cs >= JSON_string_first_final) {
578
655
  return p + 1;
579
656
  } else {
@@ -680,6 +757,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
680
757
  } else {
681
758
  json->symbolize_names = 0;
682
759
  }
760
+ tmp = ID2SYM(i_freeze);
761
+ if (option_given_p(opts, tmp)) {
762
+ json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
763
+ } else {
764
+ json->freeze = 0;
765
+ }
683
766
  tmp = ID2SYM(i_create_additions);
684
767
  if (option_given_p(opts, tmp)) {
685
768
  json->create_additions = RTEST(rb_hash_aref(opts, tmp));
@@ -764,6 +847,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
764
847
  *
765
848
  * Parses the current JSON text _source_ and returns the complete data
766
849
  * structure as a result.
850
+ * It raises JSON::ParseError if fail to parse.
767
851
  */
768
852
  static VALUE cParser_parse(VALUE self)
769
853
  {
@@ -842,6 +926,10 @@ static VALUE cParser_source(VALUE self)
842
926
 
843
927
  void Init_parser(void)
844
928
  {
929
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
930
+ rb_ext_ractor_safe(true);
931
+ #endif
932
+
845
933
  #undef rb_intern
846
934
  rb_require("json/common");
847
935
  mJSON = rb_define_module("JSON");
@@ -884,7 +972,9 @@ void Init_parser(void)
884
972
  i_aref = rb_intern("[]");
885
973
  i_leftshift = rb_intern("<<");
886
974
  i_new = rb_intern("new");
887
- i_BigDecimal = rb_intern("BigDecimal");
975
+ i_try_convert = rb_intern("try_convert");
976
+ i_freeze = rb_intern("freeze");
977
+ i_uminus = rb_intern("-@");
888
978
  }
889
979
 
890
980
  /*
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>,