oj 3.13.23 → 3.16.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +81 -0
  3. data/README.md +2 -2
  4. data/ext/oj/buf.h +7 -6
  5. data/ext/oj/cache.c +29 -26
  6. data/ext/oj/cache.h +3 -2
  7. data/ext/oj/cache8.c +10 -9
  8. data/ext/oj/circarray.c +7 -5
  9. data/ext/oj/circarray.h +2 -2
  10. data/ext/oj/code.c +5 -12
  11. data/ext/oj/code.h +2 -2
  12. data/ext/oj/compat.c +20 -60
  13. data/ext/oj/custom.c +26 -59
  14. data/ext/oj/debug.c +3 -9
  15. data/ext/oj/dump.c +103 -53
  16. data/ext/oj/dump.h +1 -4
  17. data/ext/oj/dump_compat.c +557 -592
  18. data/ext/oj/dump_leaf.c +3 -5
  19. data/ext/oj/dump_object.c +42 -48
  20. data/ext/oj/dump_strict.c +10 -22
  21. data/ext/oj/encoder.c +1 -1
  22. data/ext/oj/err.c +2 -13
  23. data/ext/oj/err.h +9 -12
  24. data/ext/oj/extconf.rb +16 -7
  25. data/ext/oj/fast.c +60 -92
  26. data/ext/oj/intern.c +62 -47
  27. data/ext/oj/intern.h +3 -7
  28. data/ext/oj/mem.c +318 -0
  29. data/ext/oj/mem.h +53 -0
  30. data/ext/oj/mimic_json.c +51 -32
  31. data/ext/oj/object.c +33 -43
  32. data/ext/oj/odd.c +8 -6
  33. data/ext/oj/odd.h +4 -4
  34. data/ext/oj/oj.c +243 -212
  35. data/ext/oj/oj.h +83 -81
  36. data/ext/oj/parse.c +94 -148
  37. data/ext/oj/parse.h +21 -24
  38. data/ext/oj/parser.c +80 -67
  39. data/ext/oj/parser.h +7 -8
  40. data/ext/oj/rails.c +70 -92
  41. data/ext/oj/reader.c +9 -14
  42. data/ext/oj/reader.h +4 -2
  43. data/ext/oj/resolve.c +3 -4
  44. data/ext/oj/rxclass.c +6 -5
  45. data/ext/oj/rxclass.h +1 -1
  46. data/ext/oj/saj.c +10 -9
  47. data/ext/oj/saj2.c +37 -49
  48. data/ext/oj/saj2.h +1 -1
  49. data/ext/oj/scp.c +3 -14
  50. data/ext/oj/sparse.c +22 -70
  51. data/ext/oj/stream_writer.c +45 -41
  52. data/ext/oj/strict.c +20 -52
  53. data/ext/oj/string_writer.c +64 -38
  54. data/ext/oj/trace.h +31 -4
  55. data/ext/oj/usual.c +125 -114
  56. data/ext/oj/usual.h +7 -6
  57. data/ext/oj/util.h +1 -1
  58. data/ext/oj/val_stack.c +13 -2
  59. data/ext/oj/val_stack.h +8 -7
  60. data/ext/oj/wab.c +25 -57
  61. data/lib/oj/active_support_helper.rb +1 -3
  62. data/lib/oj/bag.rb +7 -1
  63. data/lib/oj/easy_hash.rb +4 -5
  64. data/lib/oj/error.rb +0 -1
  65. data/lib/oj/json.rb +162 -150
  66. data/lib/oj/mimic.rb +7 -7
  67. data/lib/oj/schandler.rb +5 -4
  68. data/lib/oj/state.rb +8 -5
  69. data/lib/oj/version.rb +1 -2
  70. data/lib/oj.rb +2 -0
  71. data/pages/InstallOptions.md +20 -0
  72. data/pages/Options.md +4 -0
  73. data/test/_test_active.rb +8 -9
  74. data/test/_test_active_mimic.rb +7 -8
  75. data/test/_test_mimic_rails.rb +17 -20
  76. data/test/activerecord/result_test.rb +5 -6
  77. data/test/activesupport6/encoding_test.rb +63 -28
  78. data/test/activesupport7/abstract_unit.rb +4 -1
  79. data/test/activesupport7/encoding_test.rb +72 -22
  80. data/test/files.rb +15 -15
  81. data/test/foo.rb +18 -69
  82. data/test/helper.rb +5 -8
  83. data/test/isolated/shared.rb +3 -2
  84. data/test/json_gem/json_addition_test.rb +2 -2
  85. data/test/json_gem/json_common_interface_test.rb +8 -6
  86. data/test/json_gem/json_encoding_test.rb +0 -0
  87. data/test/json_gem/json_ext_parser_test.rb +1 -0
  88. data/test/json_gem/json_fixtures_test.rb +3 -2
  89. data/test/json_gem/json_generator_test.rb +50 -33
  90. data/test/json_gem/json_generic_object_test.rb +11 -11
  91. data/test/json_gem/json_parser_test.rb +46 -46
  92. data/test/json_gem/json_string_matching_test.rb +9 -9
  93. data/test/mem.rb +13 -12
  94. data/test/perf.rb +21 -26
  95. data/test/perf_compat.rb +31 -33
  96. data/test/perf_dump.rb +28 -28
  97. data/test/perf_fast.rb +80 -82
  98. data/test/perf_file.rb +27 -29
  99. data/test/perf_object.rb +65 -69
  100. data/test/perf_once.rb +12 -11
  101. data/test/perf_parser.rb +42 -48
  102. data/test/perf_saj.rb +46 -54
  103. data/test/perf_scp.rb +57 -69
  104. data/test/perf_simple.rb +41 -39
  105. data/test/perf_strict.rb +68 -70
  106. data/test/perf_wab.rb +67 -69
  107. data/test/prec.rb +5 -5
  108. data/test/sample/change.rb +0 -1
  109. data/test/sample/dir.rb +0 -1
  110. data/test/sample/doc.rb +0 -1
  111. data/test/sample/file.rb +0 -1
  112. data/test/sample/group.rb +0 -1
  113. data/test/sample/hasprops.rb +0 -1
  114. data/test/sample/layer.rb +0 -1
  115. data/test/sample/rect.rb +0 -1
  116. data/test/sample/shape.rb +0 -1
  117. data/test/sample/text.rb +0 -1
  118. data/test/sample.rb +16 -16
  119. data/test/sample_json.rb +8 -8
  120. data/test/test_compat.rb +81 -54
  121. data/test/test_custom.rb +63 -52
  122. data/test/test_debian.rb +7 -10
  123. data/test/test_fast.rb +86 -90
  124. data/test/test_file.rb +24 -29
  125. data/test/test_gc.rb +5 -5
  126. data/test/test_generate.rb +5 -5
  127. data/test/test_hash.rb +4 -4
  128. data/test/test_integer_range.rb +9 -9
  129. data/test/test_null.rb +20 -20
  130. data/test/test_object.rb +92 -87
  131. data/test/test_parser.rb +4 -4
  132. data/test/test_parser_debug.rb +5 -5
  133. data/test/test_parser_saj.rb +27 -25
  134. data/test/test_parser_usual.rb +44 -6
  135. data/test/test_rails.rb +2 -2
  136. data/test/test_saj.rb +10 -8
  137. data/test/test_scp.rb +35 -35
  138. data/test/test_strict.rb +38 -32
  139. data/test/test_various.rb +146 -97
  140. data/test/test_wab.rb +46 -44
  141. data/test/test_writer.rb +63 -47
  142. data/test/tests.rb +7 -7
  143. data/test/tests_mimic.rb +6 -6
  144. data/test/tests_mimic_addition.rb +6 -6
  145. metadata +46 -26
  146. data/test/activesupport4/decoding_test.rb +0 -108
  147. data/test/activesupport4/encoding_test.rb +0 -531
  148. data/test/activesupport4/test_helper.rb +0 -41
  149. data/test/activesupport5/abstract_unit.rb +0 -45
  150. data/test/activesupport5/decoding_test.rb +0 -133
  151. data/test/activesupport5/encoding_test.rb +0 -500
  152. data/test/activesupport5/encoding_test_cases.rb +0 -98
  153. data/test/activesupport5/test_helper.rb +0 -72
  154. data/test/activesupport5/time_zone_test_helpers.rb +0 -39
  155. data/test/bar.rb +0 -11
  156. data/test/baz.rb +0 -16
  157. data/test/bug.rb +0 -16
  158. data/test/zoo.rb +0 -13
data/ext/oj/object.c CHANGED
@@ -83,8 +83,9 @@ static int parse_num(const char *str, const char *end, int cnt) {
83
83
 
84
84
  VALUE
85
85
  oj_parse_xml_time(const char *str, int len) {
86
- VALUE args[8];
87
- const char *end = str + len;
86
+ VALUE args[7];
87
+ const char *end = str + len;
88
+ const char *orig = str;
88
89
  int n;
89
90
 
90
91
  // year
@@ -144,7 +145,9 @@ oj_parse_xml_time(const char *str, int len) {
144
145
  char c = *str++;
145
146
 
146
147
  if ('.' == c) {
147
- long long nsec = 0;
148
+ unsigned long long num = 0;
149
+ unsigned long long den = 1;
150
+ const unsigned long long last_den_limit = ULLONG_MAX / 10;
148
151
 
149
152
  for (; str < end; str++) {
150
153
  c = *str;
@@ -152,9 +155,14 @@ oj_parse_xml_time(const char *str, int len) {
152
155
  str++;
153
156
  break;
154
157
  }
155
- nsec = nsec * 10 + (c - '0');
158
+ if (den > last_den_limit) {
159
+ // bail to Time.parse if there are more fractional digits than a ULLONG rational can hold
160
+ return rb_funcall(rb_cTime, oj_parse_id, 1, rb_str_new(orig, len));
161
+ }
162
+ num = num * 10 + (c - '0');
163
+ den *= 10;
156
164
  }
157
- args[5] = rb_float_new((double)n + ((double)nsec + 0.5) / 1000000000.0);
165
+ args[5] = rb_funcall(INT2NUM(n), oj_plus_id, 1, rb_rational_new(ULL2NUM(num), ULL2NUM(den)));
158
166
  } else {
159
167
  args[5] = rb_ll2inum(n);
160
168
  }
@@ -270,8 +278,8 @@ static int hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
270
278
  parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
271
279
  } else if (ni->has_exp) {
272
280
  struct timespec ts;
273
- ts.tv_sec = ni->i;
274
- ts.tv_nsec = nsec;
281
+ ts.tv_sec = ni->i;
282
+ ts.tv_nsec = nsec;
275
283
  parent->val = rb_time_timespec_new(&ts, (int)ni->exp);
276
284
  } else {
277
285
  parent->val = rb_time_nano_new(ni->i, (long)nsec);
@@ -308,7 +316,7 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
308
316
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
309
317
  return 1;
310
318
  }
311
- e1 = *RARRAY_PTR(value);
319
+ e1 = *RARRAY_CONST_PTR(value);
312
320
  // check for anonymous Struct
313
321
  if (T_ARRAY == rb_type(e1)) {
314
322
  VALUE args[1024];
@@ -322,17 +330,17 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
322
330
  sc = rb_funcall2(rb_cStruct, oj_new_id, cnt, args);
323
331
  } else {
324
332
  // If struct is not defined then we let this fail and raise an exception.
325
- sc = oj_name2struct(pi, *RARRAY_PTR(value), rb_eArgError);
333
+ sc = oj_name2struct(pi, *RARRAY_CONST_PTR(value), rb_eArgError);
326
334
  }
327
335
  if (sc == rb_cRange) {
328
- parent->val = rb_class_new_instance(len - 1, RARRAY_PTR(value) + 1, rb_cRange);
336
+ parent->val = rb_class_new_instance(len - 1, RARRAY_CONST_PTR(value) + 1, rb_cRange);
329
337
  } else {
330
338
  // Create a properly initialized struct instance without calling the initialize method.
331
339
  parent->val = rb_obj_alloc(sc);
332
340
  // If the JSON array has more entries than the struct class allows, we record an error.
333
341
  #ifdef RSTRUCT_LEN
334
342
  #if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
335
- slen = (int)NUM2LONG(RSTRUCT_LEN(parent->val));
343
+ slen = (int)NUM2LONG(RSTRUCT_LEN(parent->val));
336
344
  #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
337
345
  slen = (int)RSTRUCT_LEN(parent->val);
338
346
  #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
@@ -346,20 +354,20 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
346
354
  int i;
347
355
 
348
356
  for (i = 0; i < len - 1; i++) {
349
- rb_struct_aset(parent->val, INT2FIX(i), RARRAY_PTR(value)[i + 1]);
357
+ rb_struct_aset(parent->val, INT2FIX(i), RARRAY_CONST_PTR(value)[i + 1]);
350
358
  }
351
359
  }
352
360
  }
353
361
  return 1;
354
362
  } else if (3 <= klen && '#' == key[1]) {
355
- volatile VALUE *a;
363
+ volatile const VALUE *a;
356
364
 
357
365
  if (2 != len) {
358
366
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
359
367
  return 1;
360
368
  }
361
369
  parent->val = rb_hash_new();
362
- a = RARRAY_PTR(value);
370
+ a = RARRAY_CONST_PTR(value);
363
371
  rb_hash_aset(parent->val, *a, a[1]);
364
372
 
365
373
  return 1;
@@ -446,9 +454,7 @@ WHICH_TYPE:
446
454
  rb_class2name(rb_obj_class(parent->val)));
447
455
  return;
448
456
  }
449
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
450
- oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
451
- }
457
+ TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rval);
452
458
  }
453
459
 
454
460
  static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
@@ -517,9 +523,7 @@ WHICH_TYPE:
517
523
  rb_class2name(rb_obj_class(parent->val)));
518
524
  return;
519
525
  }
520
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
521
- oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, rval);
522
- }
526
+ TRACE_PARSE_CALL(pi->options.trace, "add_number", pi, rval);
523
527
  }
524
528
 
525
529
  static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
@@ -545,8 +549,8 @@ WHICH_TYPE:
545
549
  }
546
550
  } else {
547
551
  if (3 <= klen && '^' == *key && '#' == key[1] && T_ARRAY == rb_type(value)) {
548
- long len = RARRAY_LEN(value);
549
- volatile VALUE *a = RARRAY_PTR(value);
552
+ long len = RARRAY_LEN(value);
553
+ volatile const VALUE *a = RARRAY_CONST_PTR(value);
550
554
 
551
555
  if (2 != len) {
552
556
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
@@ -603,15 +607,11 @@ WHICH_TYPE:
603
607
  rb_class2name(rb_obj_class(parent->val)));
604
608
  return;
605
609
  }
606
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
607
- oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, value);
608
- }
610
+ TRACE_PARSE_CALL(pi->options.trace, "add_value", pi, value);
609
611
  }
610
612
 
611
613
  static VALUE start_hash(ParseInfo pi) {
612
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
613
- oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
614
- }
614
+ TRACE_PARSE_IN(pi->options.trace, "start_hash", pi);
615
615
  return Qnil;
616
616
  }
617
617
 
@@ -627,9 +627,7 @@ static void end_hash(ParseInfo pi) {
627
627
  oj_odd_free(oa);
628
628
  parent->odd_args = NULL;
629
629
  }
630
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
631
- oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
632
- }
630
+ TRACE_PARSE_HASH_END(pi->options.trace, pi);
633
631
  }
634
632
 
635
633
  static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
@@ -655,32 +653,24 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
655
653
  }
656
654
  rval = str_to_value(pi, str, len, orig);
657
655
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
658
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
659
- oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rval);
660
- }
656
+ TRACE_PARSE_CALL(pi->options.trace, "append_string", pi, rval);
661
657
  }
662
658
 
663
659
  static void array_append_num(ParseInfo pi, NumInfo ni) {
664
660
  volatile VALUE rval = oj_num_as_value(ni);
665
661
 
666
662
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
667
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
668
- oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
669
- }
663
+ TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, rval);
670
664
  }
671
665
 
672
666
  static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
673
667
  pi->stack.head->val = str_to_value(pi, str, len, orig);
674
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
675
- oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
676
- }
668
+ TRACE_PARSE_CALL(pi->options.trace, "add_string", pi, pi->stack.head->val);
677
669
  }
678
670
 
679
671
  static void add_num(ParseInfo pi, NumInfo ni) {
680
672
  pi->stack.head->val = oj_num_as_value(ni);
681
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
682
- oj_trace_parse_call("add_num", pi, __FILE__, __LINE__, pi->stack.head->val);
683
- }
673
+ TRACE_PARSE_CALL(pi->options.trace, "add_num", pi, pi->stack.head->val);
684
674
  }
685
675
 
686
676
  void oj_set_object_callbacks(ParseInfo pi) {
data/ext/oj/odd.c CHANGED
@@ -5,6 +5,8 @@
5
5
 
6
6
  #include <string.h>
7
7
 
8
+ #include "mem.h"
9
+
8
10
  static Odd odds = NULL;
9
11
  static ID sec_id;
10
12
  static ID sec_fraction_id;
@@ -68,7 +70,7 @@ void print_all_odds(const char *label) {
68
70
  }
69
71
 
70
72
  static Odd odd_create(void) {
71
- Odd odd = ALLOC(struct _odd);
73
+ Odd odd = OJ_R_ALLOC(struct _odd);
72
74
 
73
75
  memset(odd, 0, sizeof(struct _odd));
74
76
  odd->next = odds;
@@ -172,7 +174,7 @@ Odd oj_get_oddc(const char *classname, size_t len) {
172
174
  }
173
175
 
174
176
  OddArgs oj_odd_alloc_args(Odd odd) {
175
- OddArgs oa = ALLOC_N(struct _oddArgs, 1);
177
+ OddArgs oa = OJ_R_ALLOC_N(struct _oddArgs, 1);
176
178
  VALUE *a;
177
179
  int i;
178
180
 
@@ -184,7 +186,7 @@ OddArgs oj_odd_alloc_args(Odd odd) {
184
186
  }
185
187
 
186
188
  void oj_odd_free(OddArgs args) {
187
- xfree(args);
189
+ OJ_R_FREE(args);
188
190
  }
189
191
 
190
192
  int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
@@ -210,7 +212,7 @@ void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt,
210
212
  odd = odd_create();
211
213
  odd->clas = clas;
212
214
  rb_gc_register_mark_object(odd->clas);
213
- if (NULL == (odd->classname = strdup(rb_class2name(clas)))) {
215
+ if (NULL == (odd->classname = OJ_STRDUP(rb_class2name(clas)))) {
214
216
  rb_raise(rb_eNoMemError, "for class name.");
215
217
  }
216
218
  odd->clen = strlen(odd->classname);
@@ -224,13 +226,13 @@ void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt,
224
226
  *fp = 0;
225
227
  switch (rb_type(*members)) {
226
228
  case T_STRING:
227
- if (NULL == (*np = strdup(RSTRING_PTR(*members)))) {
229
+ if (NULL == (*np = OJ_STRDUP(RSTRING_PTR(*members)))) {
228
230
  rb_raise(rb_eNoMemError, "for attribute name.");
229
231
  }
230
232
  break;
231
233
  case T_SYMBOL:
232
234
  // The symbol can move and invalidate the name so make a copy.
233
- if (NULL == (*np = strdup(rb_id2name(SYM2ID(*members))))) {
235
+ if (NULL == (*np = OJ_STRDUP(rb_id2name(SYM2ID(*members))))) {
234
236
  rb_raise(rb_eNoMemError, "for attribute name.");
235
237
  }
236
238
  break;
data/ext/oj/odd.h CHANGED
@@ -14,7 +14,7 @@ typedef VALUE (*AttrGetFunc)(VALUE obj);
14
14
 
15
15
  typedef struct _odd {
16
16
  struct _odd *next;
17
- const char * classname;
17
+ const char *classname;
18
18
  size_t clen;
19
19
  VALUE clas; // Ruby class or module
20
20
  VALUE create_obj;
@@ -22,15 +22,15 @@ typedef struct _odd {
22
22
  int attr_cnt;
23
23
  bool is_module;
24
24
  bool raw;
25
- const char * attr_names[MAX_ODD_ARGS]; // NULL terminated attr names
25
+ const char *attr_names[MAX_ODD_ARGS]; // NULL terminated attr names
26
26
  ID attrs[MAX_ODD_ARGS]; // 0 terminated attr IDs
27
27
  AttrGetFunc attrFuncs[MAX_ODD_ARGS];
28
- } * Odd;
28
+ } *Odd;
29
29
 
30
30
  typedef struct _oddArgs {
31
31
  Odd odd;
32
32
  VALUE args[MAX_ODD_ARGS];
33
- } * OddArgs;
33
+ } *OddArgs;
34
34
 
35
35
  extern void oj_odd_init(void);
36
36
  extern Odd oj_get_odd(VALUE clas);