oj 3.13.9 → 3.16.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 (161) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +101 -0
  3. data/README.md +13 -2
  4. data/ext/oj/buf.h +11 -6
  5. data/ext/oj/cache.c +25 -24
  6. data/ext/oj/cache8.c +10 -9
  7. data/ext/oj/circarray.c +8 -6
  8. data/ext/oj/circarray.h +2 -2
  9. data/ext/oj/code.c +19 -33
  10. data/ext/oj/code.h +2 -2
  11. data/ext/oj/compat.c +20 -60
  12. data/ext/oj/custom.c +76 -155
  13. data/ext/oj/debug.c +3 -9
  14. data/ext/oj/dump.c +203 -213
  15. data/ext/oj/dump.h +26 -12
  16. data/ext/oj/dump_compat.c +565 -642
  17. data/ext/oj/dump_leaf.c +17 -63
  18. data/ext/oj/dump_object.c +59 -181
  19. data/ext/oj/dump_strict.c +24 -48
  20. data/ext/oj/encoder.c +43 -0
  21. data/ext/oj/err.c +2 -13
  22. data/ext/oj/err.h +9 -12
  23. data/ext/oj/extconf.rb +18 -7
  24. data/ext/oj/fast.c +83 -108
  25. data/ext/oj/intern.c +52 -50
  26. data/ext/oj/intern.h +4 -8
  27. data/ext/oj/mem.c +318 -0
  28. data/ext/oj/mem.h +53 -0
  29. data/ext/oj/mimic_json.c +104 -81
  30. data/ext/oj/object.c +50 -67
  31. data/ext/oj/odd.c +89 -67
  32. data/ext/oj/odd.h +15 -15
  33. data/ext/oj/oj.c +171 -106
  34. data/ext/oj/oj.h +96 -74
  35. data/ext/oj/parse.c +169 -189
  36. data/ext/oj/parse.h +23 -24
  37. data/ext/oj/parser.c +89 -34
  38. data/ext/oj/parser.h +20 -9
  39. data/ext/oj/rails.c +86 -151
  40. data/ext/oj/rails.h +1 -1
  41. data/ext/oj/reader.c +12 -15
  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 +21 -32
  47. data/ext/oj/saj2.c +329 -93
  48. data/ext/oj/saj2.h +23 -0
  49. data/ext/oj/scp.c +3 -14
  50. data/ext/oj/sparse.c +26 -70
  51. data/ext/oj/stream_writer.c +12 -22
  52. data/ext/oj/strict.c +20 -52
  53. data/ext/oj/string_writer.c +21 -22
  54. data/ext/oj/trace.h +31 -4
  55. data/ext/oj/usual.c +105 -150
  56. data/ext/oj/usual.h +68 -0
  57. data/ext/oj/util.h +1 -1
  58. data/ext/oj/val_stack.c +1 -1
  59. data/ext/oj/val_stack.h +8 -7
  60. data/ext/oj/validate.c +21 -26
  61. data/ext/oj/wab.c +32 -69
  62. data/lib/oj/active_support_helper.rb +1 -3
  63. data/lib/oj/bag.rb +7 -1
  64. data/lib/oj/easy_hash.rb +4 -5
  65. data/lib/oj/error.rb +0 -1
  66. data/lib/oj/json.rb +162 -150
  67. data/lib/oj/mimic.rb +6 -2
  68. data/lib/oj/saj.rb +20 -6
  69. data/lib/oj/state.rb +9 -6
  70. data/lib/oj/version.rb +1 -2
  71. data/lib/oj.rb +2 -0
  72. data/pages/Compatibility.md +1 -1
  73. data/pages/InstallOptions.md +20 -0
  74. data/pages/JsonGem.md +15 -0
  75. data/pages/Modes.md +6 -3
  76. data/pages/Options.md +10 -0
  77. data/pages/Rails.md +12 -0
  78. data/test/_test_active.rb +8 -9
  79. data/test/_test_active_mimic.rb +7 -8
  80. data/test/_test_mimic_rails.rb +17 -20
  81. data/test/activerecord/result_test.rb +5 -6
  82. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  83. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  84. data/test/{activesupport5 → activesupport7}/encoding_test.rb +20 -34
  85. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  86. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  87. data/test/files.rb +15 -15
  88. data/test/foo.rb +15 -15
  89. data/test/helper.rb +11 -8
  90. data/test/isolated/shared.rb +3 -2
  91. data/test/json_gem/json_addition_test.rb +2 -2
  92. data/test/json_gem/json_common_interface_test.rb +8 -6
  93. data/test/json_gem/json_encoding_test.rb +0 -0
  94. data/test/json_gem/json_ext_parser_test.rb +1 -0
  95. data/test/json_gem/json_fixtures_test.rb +3 -2
  96. data/test/json_gem/json_generator_test.rb +49 -37
  97. data/test/json_gem/json_generic_object_test.rb +11 -11
  98. data/test/json_gem/json_parser_test.rb +54 -47
  99. data/test/json_gem/json_string_matching_test.rb +9 -9
  100. data/test/json_gem/test_helper.rb +7 -3
  101. data/test/mem.rb +13 -12
  102. data/test/perf.rb +21 -26
  103. data/test/perf_compat.rb +31 -33
  104. data/test/perf_dump.rb +50 -0
  105. data/test/perf_fast.rb +80 -82
  106. data/test/perf_file.rb +27 -29
  107. data/test/perf_object.rb +65 -69
  108. data/test/perf_once.rb +12 -11
  109. data/test/perf_parser.rb +42 -48
  110. data/test/perf_saj.rb +46 -54
  111. data/test/perf_scp.rb +57 -69
  112. data/test/perf_simple.rb +41 -39
  113. data/test/perf_strict.rb +68 -70
  114. data/test/perf_wab.rb +67 -69
  115. data/test/prec.rb +3 -3
  116. data/test/sample/change.rb +0 -1
  117. data/test/sample/dir.rb +0 -1
  118. data/test/sample/doc.rb +0 -1
  119. data/test/sample/file.rb +0 -1
  120. data/test/sample/group.rb +0 -1
  121. data/test/sample/hasprops.rb +0 -1
  122. data/test/sample/layer.rb +0 -1
  123. data/test/sample/rect.rb +0 -1
  124. data/test/sample/shape.rb +0 -1
  125. data/test/sample/text.rb +0 -1
  126. data/test/sample.rb +16 -16
  127. data/test/sample_json.rb +8 -8
  128. data/test/test_compat.rb +95 -43
  129. data/test/test_custom.rb +72 -51
  130. data/test/test_debian.rb +7 -10
  131. data/test/test_fast.rb +102 -87
  132. data/test/test_file.rb +41 -30
  133. data/test/test_gc.rb +16 -5
  134. data/test/test_generate.rb +5 -5
  135. data/test/test_hash.rb +4 -4
  136. data/test/test_integer_range.rb +9 -9
  137. data/test/test_null.rb +20 -20
  138. data/test/test_object.rb +85 -96
  139. data/test/test_parser.rb +6 -22
  140. data/test/test_parser_debug.rb +27 -0
  141. data/test/test_parser_saj.rb +115 -23
  142. data/test/test_parser_usual.rb +6 -6
  143. data/test/test_rails.rb +2 -2
  144. data/test/test_saj.rb +10 -8
  145. data/test/test_scp.rb +37 -39
  146. data/test/test_strict.rb +40 -32
  147. data/test/test_various.rb +163 -84
  148. data/test/test_wab.rb +48 -44
  149. data/test/test_writer.rb +47 -47
  150. data/test/tests.rb +13 -5
  151. data/test/tests_mimic.rb +12 -3
  152. data/test/tests_mimic_addition.rb +12 -3
  153. metadata +34 -144
  154. data/test/activesupport4/decoding_test.rb +0 -108
  155. data/test/activesupport4/encoding_test.rb +0 -531
  156. data/test/activesupport4/test_helper.rb +0 -41
  157. data/test/activesupport5/test_helper.rb +0 -72
  158. data/test/bar.rb +0 -16
  159. data/test/baz.rb +0 -16
  160. data/test/bug.rb +0 -16
  161. data/test/zoo.rb +0 -13
data/ext/oj/odd.c CHANGED
@@ -5,28 +5,29 @@
5
5
 
6
6
  #include <string.h>
7
7
 
8
- static struct _odd _odds[4]; // bump up if new initial Odd classes are added
9
- static struct _odd *odds = _odds;
10
- static long odd_cnt = 0;
11
- static ID sec_id;
12
- static ID sec_fraction_id;
13
- static ID to_f_id;
14
- static ID numerator_id;
15
- static ID denominator_id;
16
- static ID rational_id;
17
- static VALUE rational_class;
8
+ #include "mem.h"
9
+
10
+ static Odd odds = NULL;
11
+ static ID sec_id;
12
+ static ID sec_fraction_id;
13
+ static ID to_f_id;
14
+ static ID numerator_id;
15
+ static ID denominator_id;
16
+ static ID rational_id;
18
17
 
19
18
  static void set_class(Odd odd, const char *classname) {
20
19
  const char **np;
21
- ID * idp;
20
+ ID *idp;
22
21
 
23
- odd->classname = classname;
24
- odd->clen = strlen(classname);
25
- odd->clas = rb_const_get(rb_cObject, rb_intern(classname));
22
+ odd->classname = classname;
23
+ odd->clen = strlen(classname);
24
+ odd->clas = rb_const_get(rb_cObject, rb_intern(classname));
25
+ rb_gc_register_mark_object(odd->clas);
26
26
  odd->create_obj = odd->clas;
27
- odd->create_op = rb_intern("new");
28
- odd->is_module = (T_MODULE == rb_type(odd->clas));
29
- odd->raw = 0;
27
+ rb_gc_register_mark_object(odd->create_obj);
28
+ odd->create_op = rb_intern("new");
29
+ odd->is_module = (T_MODULE == rb_type(odd->clas));
30
+ odd->raw = 0;
30
31
  for (np = odd->attr_names, idp = odd->attrs; 0 != *np; np++, idp++) {
31
32
  *idp = rb_intern(*np);
32
33
  }
@@ -37,15 +38,48 @@ static VALUE get_datetime_secs(VALUE obj) {
37
38
  volatile VALUE rsecs = rb_funcall(obj, sec_id, 0);
38
39
  volatile VALUE rfrac = rb_funcall(obj, sec_fraction_id, 0);
39
40
  long sec = NUM2LONG(rsecs);
40
- long long num = rb_num2ll(rb_funcall(rfrac, numerator_id, 0));
41
- long long den = rb_num2ll(rb_funcall(rfrac, denominator_id, 0));
41
+ long long num = NUM2LL(rb_funcall(rfrac, numerator_id, 0));
42
+ long long den = NUM2LL(rb_funcall(rfrac, denominator_id, 0));
42
43
 
43
44
  num += sec * den;
44
45
 
45
46
  return rb_funcall(rb_cObject, rational_id, 2, rb_ll2inum(num), rb_ll2inum(den));
46
47
  }
47
48
 
48
- void oj_odd_init() {
49
+ static void print_odd(Odd odd) {
50
+ const char **np;
51
+ int i;
52
+
53
+ printf(" %s {\n", odd->classname);
54
+ printf(" attr_cnt: %d %p\n", odd->attr_cnt, (void *)odd->attr_names);
55
+ printf(" attr_names: %p\n", (void *)*odd->attr_names);
56
+ printf(" attr_names: %c\n", **odd->attr_names);
57
+ for (i = odd->attr_cnt, np = odd->attr_names; 0 < i; i--, np++) {
58
+ printf(" %d %s\n", i, *np);
59
+ }
60
+ printf(" }\n");
61
+ }
62
+
63
+ void print_all_odds(const char *label) {
64
+ Odd odd;
65
+ printf("@ %s {\n", label);
66
+ for (odd = odds; NULL != odd; odd = odd->next) {
67
+ print_odd(odd);
68
+ }
69
+ printf("}\n");
70
+ }
71
+
72
+ static Odd odd_create(void) {
73
+ Odd odd = OJ_R_ALLOC(struct _odd);
74
+
75
+ memset(odd, 0, sizeof(struct _odd));
76
+ odd->next = odds;
77
+ odds = odd;
78
+
79
+ return odd;
80
+ }
81
+
82
+ void oj_odd_init(void) {
49
83
  Odd odd;
50
84
  const char **np;
51
85
 
@@ -55,11 +89,9 @@ void oj_odd_init() {
55
89
  numerator_id = rb_intern("numerator");
56
90
  denominator_id = rb_intern("denominator");
57
91
  rational_id = rb_intern("Rational");
58
- rational_class = rb_const_get(rb_cObject, rational_id);
59
92
 
60
- memset(_odds, 0, sizeof(_odds));
61
- odd = odds;
62
93
  // Rational
94
+ odd = odd_create();
63
95
  np = odd->attr_names;
64
96
  *np++ = "numerator";
65
97
  *np++ = "denominator";
@@ -68,8 +100,9 @@ void oj_odd_init() {
68
100
  odd->create_obj = rb_cObject;
69
101
  odd->create_op = rational_id;
70
102
  odd->attr_cnt = 2;
103
+
71
104
  // Date
72
- odd++;
105
+ odd = odd_create();
73
106
  np = odd->attr_names;
74
107
  *np++ = "year";
75
108
  *np++ = "month";
@@ -78,8 +111,9 @@ void oj_odd_init() {
78
111
  *np++ = 0;
79
112
  set_class(odd, "Date");
80
113
  odd->attr_cnt = 4;
114
+
81
115
  // DateTime
82
- odd++;
116
+ odd = odd_create();
83
117
  np = odd->attr_names;
84
118
  *np++ = "year";
85
119
  *np++ = "month";
@@ -93,8 +127,9 @@ void oj_odd_init() {
93
127
  set_class(odd, "DateTime");
94
128
  odd->attr_cnt = 8;
95
129
  odd->attrFuncs[5] = get_datetime_secs;
130
+
96
131
  // Range
97
- odd++;
132
+ odd = odd_create();
98
133
  np = odd->attr_names;
99
134
  *np++ = "begin";
100
135
  *np++ = "end";
@@ -102,15 +137,13 @@ void oj_odd_init() {
102
137
  *np++ = 0;
103
138
  set_class(odd, "Range");
104
139
  odd->attr_cnt = 3;
105
-
106
- odd_cnt = odd - odds + 1;
107
140
  }
108
141
 
109
142
  Odd oj_get_odd(VALUE clas) {
110
143
  Odd odd;
111
144
  const char *classname = NULL;
112
145
 
113
- for (odd = odds + odd_cnt - 1; odds <= odd; odd--) {
146
+ for (odd = odds; NULL != odd; odd = odd->next) {
114
147
  if (clas == odd->clas) {
115
148
  return odd;
116
149
  }
@@ -129,21 +162,20 @@ Odd oj_get_odd(VALUE clas) {
129
162
  Odd oj_get_oddc(const char *classname, size_t len) {
130
163
  Odd odd;
131
164
 
132
- for (odd = odds + odd_cnt - 1; odds <= odd; odd--) {
165
+ for (odd = odds; NULL != odd; odd = odd->next) {
133
166
  if (len == odd->clen && 0 == strncmp(classname, odd->classname, len)) {
134
167
  return odd;
135
168
  }
136
- if (odd->is_module && 0 == strncmp(odd->classname, classname, odd->clen) &&
137
- ':' == classname[odd->clen]) {
169
+ if (odd->is_module && 0 == strncmp(odd->classname, classname, odd->clen) && ':' == classname[odd->clen]) {
138
170
  return odd;
139
171
  }
140
172
  }
141
- return 0;
173
+ return NULL;
142
174
  }
143
175
 
144
176
  OddArgs oj_odd_alloc_args(Odd odd) {
145
- OddArgs oa = ALLOC_N(struct _oddArgs, 1);
146
- VALUE * a;
177
+ OddArgs oa = OJ_R_ALLOC_N(struct _oddArgs, 1);
178
+ VALUE *a;
147
179
  int i;
148
180
 
149
181
  oa->odd = odd;
@@ -154,16 +186,15 @@ OddArgs oj_odd_alloc_args(Odd odd) {
154
186
  }
155
187
 
156
188
  void oj_odd_free(OddArgs args) {
157
- xfree(args);
189
+ OJ_R_FREE(args);
158
190
  }
159
191
 
160
192
  int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
161
193
  const char **np;
162
- VALUE * vp;
194
+ VALUE *vp;
163
195
  int i;
164
196
 
165
- for (i = args->odd->attr_cnt, np = args->odd->attr_names, vp = args->args; 0 < i;
166
- i--, np++, vp++) {
197
+ for (i = args->odd->attr_cnt, np = args->odd->attr_names, vp = args->args; 0 < i; i--, np++, vp++) {
167
198
  if (0 == strncmp(key, *np, klen) && '\0' == *((*np) + klen)) {
168
199
  *vp = value;
169
200
  return 0;
@@ -172,52 +203,43 @@ int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
172
203
  return -1;
173
204
  }
174
205
 
175
- void oj_reg_odd(VALUE clas,
176
- VALUE create_object,
177
- VALUE create_method,
178
- int mcnt,
179
- VALUE *members,
180
- bool raw) {
206
+ void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw) {
181
207
  Odd odd;
182
208
  const char **np;
183
- ID * ap;
209
+ ID *ap;
184
210
  AttrGetFunc *fp;
185
211
 
186
- if (_odds == odds) {
187
- odds = ALLOC_N(struct _odd, odd_cnt + 1);
188
-
189
- memcpy(odds, _odds, sizeof(struct _odd) * odd_cnt);
190
- } else {
191
- REALLOC_N(odds, struct _odd, odd_cnt + 1);
192
- }
193
- odd = odds + odd_cnt;
212
+ odd = odd_create();
194
213
  odd->clas = clas;
195
- if (NULL == (odd->classname = strdup(rb_class2name(clas)))) {
196
- rb_raise(rb_eNoMemError, "for attribute name.");
214
+ rb_gc_register_mark_object(odd->clas);
215
+ if (NULL == (odd->classname = OJ_STRDUP(rb_class2name(clas)))) {
216
+ rb_raise(rb_eNoMemError, "for class name.");
197
217
  }
198
218
  odd->clen = strlen(odd->classname);
199
219
  odd->create_obj = create_object;
200
- odd->create_op = SYM2ID(create_method);
201
- odd->attr_cnt = mcnt;
202
- odd->is_module = (T_MODULE == rb_type(clas));
203
- odd->raw = raw;
204
- for (ap = odd->attrs, np = odd->attr_names, fp = odd->attrFuncs; 0 < mcnt;
205
- mcnt--, ap++, np++, members++, fp++) {
220
+ rb_gc_register_mark_object(odd->create_obj);
221
+ odd->create_op = SYM2ID(create_method);
222
+ odd->attr_cnt = mcnt;
223
+ odd->is_module = (T_MODULE == rb_type(clas));
224
+ odd->raw = raw;
225
+ for (ap = odd->attrs, np = odd->attr_names, fp = odd->attrFuncs; 0 < mcnt; mcnt--, ap++, np++, members++, fp++) {
206
226
  *fp = 0;
207
227
  switch (rb_type(*members)) {
208
228
  case T_STRING:
209
- if (NULL == (*np = strdup(RSTRING_PTR(*members)))) {
229
+ if (NULL == (*np = OJ_STRDUP(RSTRING_PTR(*members)))) {
210
230
  rb_raise(rb_eNoMemError, "for attribute name.");
211
231
  }
212
232
  break;
213
- case T_SYMBOL: *np = rb_id2name(SYM2ID(*members)); break;
214
- default:
215
- rb_raise(rb_eArgError, "registered member identifiers must be Strings or Symbols.");
233
+ case T_SYMBOL:
234
+ // The symbol can move and invalidate the name so make a copy.
235
+ if (NULL == (*np = OJ_STRDUP(rb_id2name(SYM2ID(*members))))) {
236
+ rb_raise(rb_eNoMemError, "for attribute name.");
237
+ }
216
238
  break;
239
+ default: rb_raise(rb_eArgError, "registered member identifiers must be Strings or Symbols."); break;
217
240
  }
218
241
  *ap = rb_intern(*np);
219
242
  }
220
243
  *np = 0;
221
244
  *ap = 0;
222
- odd_cnt++;
223
245
  }
data/ext/oj/odd.h CHANGED
@@ -13,23 +13,24 @@
13
13
  typedef VALUE (*AttrGetFunc)(VALUE obj);
14
14
 
15
15
  typedef struct _odd {
16
- const char *classname;
17
- size_t clen;
18
- VALUE clas; // Ruby class or module
19
- VALUE create_obj;
20
- ID create_op;
21
- int attr_cnt;
22
- bool is_module;
23
- bool raw;
24
- const char *attr_names[MAX_ODD_ARGS]; // NULL terminated attr names
25
- ID attrs[MAX_ODD_ARGS]; // 0 terminated attr IDs
26
- AttrGetFunc attrFuncs[MAX_ODD_ARGS];
27
- } * Odd;
16
+ struct _odd *next;
17
+ const char *classname;
18
+ size_t clen;
19
+ VALUE clas; // Ruby class or module
20
+ VALUE create_obj;
21
+ ID create_op;
22
+ int attr_cnt;
23
+ bool is_module;
24
+ bool raw;
25
+ const char *attr_names[MAX_ODD_ARGS]; // NULL terminated attr names
26
+ ID attrs[MAX_ODD_ARGS]; // 0 terminated attr IDs
27
+ AttrGetFunc attrFuncs[MAX_ODD_ARGS];
28
+ } *Odd;
28
29
 
29
30
  typedef struct _oddArgs {
30
31
  Odd odd;
31
32
  VALUE args[MAX_ODD_ARGS];
32
- } * OddArgs;
33
+ } *OddArgs;
33
34
 
34
35
  extern void oj_odd_init(void);
35
36
  extern Odd oj_get_odd(VALUE clas);
@@ -37,7 +38,6 @@ extern Odd oj_get_oddc(const char *classname, size_t len);
37
38
  extern OddArgs oj_odd_alloc_args(Odd odd);
38
39
  extern void oj_odd_free(OddArgs args);
39
40
  extern int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value);
40
- extern void
41
- oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw);
41
+ extern void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw);
42
42
 
43
43
  #endif /* OJ_ODD_H */