oj 3.7.4 → 3.13.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1352 -0
  3. data/README.md +29 -8
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +53 -72
  6. data/ext/oj/cache.c +326 -0
  7. data/ext/oj/cache.h +21 -0
  8. data/ext/oj/cache8.c +61 -64
  9. data/ext/oj/cache8.h +12 -39
  10. data/ext/oj/circarray.c +37 -43
  11. data/ext/oj/circarray.h +16 -17
  12. data/ext/oj/code.c +165 -179
  13. data/ext/oj/code.h +27 -29
  14. data/ext/oj/compat.c +174 -194
  15. data/ext/oj/custom.c +809 -866
  16. data/ext/oj/debug.c +132 -0
  17. data/ext/oj/dump.c +848 -863
  18. data/ext/oj/dump.h +81 -67
  19. data/ext/oj/dump_compat.c +85 -123
  20. data/ext/oj/dump_leaf.c +100 -188
  21. data/ext/oj/dump_object.c +527 -656
  22. data/ext/oj/dump_strict.c +315 -338
  23. data/ext/oj/encode.h +7 -34
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +40 -29
  26. data/ext/oj/err.h +48 -48
  27. data/ext/oj/extconf.rb +17 -4
  28. data/ext/oj/fast.c +1070 -1087
  29. data/ext/oj/intern.c +301 -0
  30. data/ext/oj/intern.h +26 -0
  31. data/ext/oj/mimic_json.c +469 -436
  32. data/ext/oj/object.c +525 -593
  33. data/ext/oj/odd.c +154 -138
  34. data/ext/oj/odd.h +37 -38
  35. data/ext/oj/oj.c +1325 -986
  36. data/ext/oj/oj.h +333 -316
  37. data/ext/oj/parse.c +1002 -846
  38. data/ext/oj/parse.h +92 -87
  39. data/ext/oj/parser.c +1557 -0
  40. data/ext/oj/parser.h +91 -0
  41. data/ext/oj/rails.c +888 -878
  42. data/ext/oj/rails.h +11 -14
  43. data/ext/oj/reader.c +141 -147
  44. data/ext/oj/reader.h +73 -89
  45. data/ext/oj/resolve.c +41 -62
  46. data/ext/oj/resolve.h +7 -9
  47. data/ext/oj/rxclass.c +71 -75
  48. data/ext/oj/rxclass.h +18 -19
  49. data/ext/oj/saj.c +443 -486
  50. data/ext/oj/saj2.c +602 -0
  51. data/ext/oj/scp.c +88 -113
  52. data/ext/oj/sparse.c +787 -709
  53. data/ext/oj/stream_writer.c +133 -159
  54. data/ext/oj/strict.c +127 -118
  55. data/ext/oj/string_writer.c +230 -249
  56. data/ext/oj/trace.c +34 -41
  57. data/ext/oj/trace.h +19 -19
  58. data/ext/oj/usual.c +1254 -0
  59. data/ext/oj/util.c +136 -0
  60. data/ext/oj/util.h +20 -0
  61. data/ext/oj/val_stack.c +59 -67
  62. data/ext/oj/val_stack.h +91 -129
  63. data/ext/oj/validate.c +46 -0
  64. data/ext/oj/wab.c +342 -353
  65. data/lib/oj/bag.rb +1 -0
  66. data/lib/oj/easy_hash.rb +5 -4
  67. data/lib/oj/error.rb +1 -1
  68. data/lib/oj/json.rb +1 -1
  69. data/lib/oj/mimic.rb +48 -14
  70. data/lib/oj/saj.rb +20 -6
  71. data/lib/oj/state.rb +8 -7
  72. data/lib/oj/version.rb +2 -2
  73. data/lib/oj.rb +0 -8
  74. data/pages/Compatibility.md +1 -1
  75. data/pages/JsonGem.md +15 -0
  76. data/pages/Modes.md +53 -46
  77. data/pages/Options.md +72 -11
  78. data/pages/Parser.md +309 -0
  79. data/pages/Rails.md +73 -22
  80. data/pages/Security.md +1 -1
  81. data/test/activerecord/result_test.rb +7 -2
  82. data/test/activesupport5/abstract_unit.rb +45 -0
  83. data/test/activesupport5/decoding_test.rb +68 -60
  84. data/test/activesupport5/encoding_test.rb +111 -96
  85. data/test/activesupport5/encoding_test_cases.rb +33 -25
  86. data/test/activesupport5/test_helper.rb +43 -21
  87. data/test/activesupport5/time_zone_test_helpers.rb +18 -3
  88. data/test/activesupport6/abstract_unit.rb +44 -0
  89. data/test/activesupport6/decoding_test.rb +133 -0
  90. data/test/activesupport6/encoding_test.rb +507 -0
  91. data/test/activesupport6/encoding_test_cases.rb +98 -0
  92. data/test/activesupport6/test_common.rb +17 -0
  93. data/test/activesupport6/test_helper.rb +163 -0
  94. data/test/activesupport6/time_zone_test_helpers.rb +39 -0
  95. data/test/activesupport7/abstract_unit.rb +49 -0
  96. data/test/activesupport7/decoding_test.rb +125 -0
  97. data/test/activesupport7/encoding_test.rb +486 -0
  98. data/test/activesupport7/encoding_test_cases.rb +104 -0
  99. data/test/activesupport7/time_zone_test_helpers.rb +47 -0
  100. data/test/bar.rb +6 -12
  101. data/test/baz.rb +16 -0
  102. data/test/bug.rb +16 -0
  103. data/test/foo.rb +69 -75
  104. data/test/helper.rb +16 -0
  105. data/test/json_gem/json_common_interface_test.rb +8 -3
  106. data/test/json_gem/json_generator_test.rb +18 -4
  107. data/test/json_gem/json_parser_test.rb +9 -0
  108. data/test/json_gem/test_helper.rb +12 -0
  109. data/test/mem.rb +33 -0
  110. data/test/perf.rb +1 -1
  111. data/test/perf_dump.rb +50 -0
  112. data/test/perf_once.rb +58 -0
  113. data/test/perf_parser.rb +189 -0
  114. data/test/perf_scp.rb +11 -10
  115. data/test/perf_strict.rb +17 -23
  116. data/test/prec.rb +23 -0
  117. data/test/sample_json.rb +1 -1
  118. data/test/test_compat.rb +46 -10
  119. data/test/test_custom.rb +147 -8
  120. data/test/test_fast.rb +62 -2
  121. data/test/test_file.rb +25 -2
  122. data/test/test_gc.rb +13 -0
  123. data/test/test_generate.rb +21 -0
  124. data/test/test_hash.rb +11 -1
  125. data/test/test_integer_range.rb +7 -2
  126. data/test/test_object.rb +85 -9
  127. data/test/test_parser.rb +27 -0
  128. data/test/test_parser_saj.rb +335 -0
  129. data/test/test_parser_usual.rb +217 -0
  130. data/test/test_rails.rb +35 -0
  131. data/test/test_saj.rb +1 -1
  132. data/test/test_scp.rb +5 -5
  133. data/test/test_strict.rb +26 -1
  134. data/test/test_various.rb +87 -65
  135. data/test/test_wab.rb +2 -0
  136. data/test/test_writer.rb +19 -2
  137. data/test/tests.rb +1 -1
  138. data/test/zoo.rb +13 -0
  139. metadata +60 -110
  140. data/ext/oj/hash.c +0 -163
  141. data/ext/oj/hash.h +0 -46
  142. data/ext/oj/hash_test.c +0 -512
data/ext/oj/strict.c CHANGED
@@ -1,210 +1,219 @@
1
- /* strict.c
2
- * Copyright (c) 2012, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
5
3
 
6
- #include <stdlib.h>
7
4
  #include <stdio.h>
5
+ #include <stdlib.h>
8
6
  #include <string.h>
9
7
  #include <unistd.h>
10
8
 
11
- #include "oj.h"
9
+ #include "encode.h"
12
10
  #include "err.h"
11
+ #include "intern.h"
12
+ #include "oj.h"
13
13
  #include "parse.h"
14
- #include "encode.h"
15
14
  #include "trace.h"
16
15
 
17
- static void
18
- hash_end(struct _ParseInfo *pi) {
19
- if (Yes == pi->options.trace) {
20
- oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
16
+ VALUE oj_cstr_to_value(const char *str, size_t len, size_t cache_str) {
17
+ volatile VALUE rstr = Qnil;
18
+
19
+ if (len < cache_str) {
20
+ rstr = oj_str_intern(str, len);
21
+ } else {
22
+ rstr = rb_str_new(str, len);
23
+ rstr = oj_encode(rstr);
21
24
  }
25
+ return rstr;
22
26
  }
23
27
 
24
- static void
25
- array_end(struct _ParseInfo *pi) {
26
- if (Yes == pi->options.trace) {
27
- oj_trace_parse_array_end(pi, __FILE__, __LINE__);
28
+ VALUE oj_calc_hash_key(ParseInfo pi, Val parent) {
29
+ volatile VALUE rkey = parent->key_val;
30
+
31
+ if (Qundef != rkey) {
32
+ return rkey;
28
33
  }
34
+ if (Yes != pi->options.cache_keys) {
35
+ if (Yes == pi->options.sym_key) {
36
+ rkey = ID2SYM(rb_intern3(parent->key, parent->klen, oj_utf8_encoding));
37
+ } else {
38
+ rkey = rb_str_new(parent->key, parent->klen);
39
+ rkey = oj_encode(rkey);
40
+ OBJ_FREEZE(rkey); // frozen when used as a Hash key anyway
41
+ }
42
+ return rkey;
43
+ }
44
+ if (Yes == pi->options.sym_key) {
45
+ rkey = oj_sym_intern(parent->key, parent->klen);
46
+ } else {
47
+ rkey = oj_str_intern(parent->key, parent->klen);
48
+ }
49
+ return rkey;
29
50
  }
30
51
 
31
- static VALUE
32
- noop_hash_key(struct _ParseInfo *pi, const char *key, size_t klen) {
52
+ static void hash_end(ParseInfo pi) {
53
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
54
+ oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
55
+ }
56
+ }
57
+
58
+ static void array_end(ParseInfo pi) {
59
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
60
+ oj_trace_parse_array_end(pi, __FILE__, __LINE__);
61
+ }
62
+ }
63
+
64
+ static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
33
65
  return Qundef;
34
66
  }
35
67
 
36
- static void
37
- add_value(ParseInfo pi, VALUE val) {
38
- if (Yes == pi->options.trace) {
39
- oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, val);
68
+ static void add_value(ParseInfo pi, VALUE val) {
69
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
70
+ oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, val);
40
71
  }
41
72
  pi->stack.head->val = val;
42
73
  }
43
74
 
44
- static void
45
- add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
46
- volatile VALUE rstr = rb_str_new(str, len);
75
+ static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
76
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
47
77
 
48
- rstr = oj_encode(rstr);
49
78
  pi->stack.head->val = rstr;
50
- if (Yes == pi->options.trace) {
51
- oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
79
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
80
+ oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
52
81
  }
53
82
  }
54
83
 
55
- static void
56
- add_num(ParseInfo pi, NumInfo ni) {
84
+ static void add_num(ParseInfo pi, NumInfo ni) {
57
85
  if (ni->infinity || ni->nan) {
58
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
86
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
59
87
  }
60
88
  pi->stack.head->val = oj_num_as_value(ni);
61
- if (Yes == pi->options.trace) {
62
- oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
89
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
90
+ oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
63
91
  }
64
92
  }
65
93
 
66
- static VALUE
67
- start_hash(ParseInfo pi) {
94
+ static VALUE start_hash(ParseInfo pi) {
68
95
  if (Qnil != pi->options.hash_class) {
69
- return rb_class_new_instance(0, NULL, pi->options.hash_class);
96
+ return rb_class_new_instance(0, NULL, pi->options.hash_class);
70
97
  }
71
- if (Yes == pi->options.trace) {
72
- oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
98
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
99
+ oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
73
100
  }
74
101
  return rb_hash_new();
75
102
  }
76
103
 
77
- static VALUE
78
- calc_hash_key(ParseInfo pi, Val parent) {
79
- volatile VALUE rkey = parent->key_val;
104
+ static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
105
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
80
106
 
81
- if (Qundef == rkey) {
82
- rkey = rb_str_new(parent->key, parent->klen);
107
+ rb_hash_aset(stack_peek(&pi->stack)->val,
108
+ oj_calc_hash_key(pi, parent),
109
+ rstr);
110
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
111
+ oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
83
112
  }
84
- rkey = oj_encode(rkey);
85
- if (Yes == pi->options.sym_key) {
86
- rkey = rb_str_intern(rkey);
87
- }
88
- return rkey;
89
113
  }
90
114
 
91
- static void
92
- hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
93
- volatile VALUE rstr = rb_str_new(str, len);
94
-
95
- rstr = oj_encode(rstr);
96
- rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rstr);
97
- if (Yes == pi->options.trace) {
98
- oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
99
- }
100
- }
115
+ static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
116
+ volatile VALUE v;
101
117
 
102
- static void
103
- hash_set_num(struct _ParseInfo *pi, Val parent, NumInfo ni) {
104
- volatile VALUE v;
105
-
106
118
  if (ni->infinity || ni->nan) {
107
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
119
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
108
120
  }
109
121
  v = oj_num_as_value(ni);
110
- rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), v);
111
- if (Yes == pi->options.trace) {
112
- oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, v);
122
+ rb_hash_aset(stack_peek(&pi->stack)->val,
123
+ oj_calc_hash_key(pi, parent),
124
+ v);
125
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
126
+ oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, v);
113
127
  }
114
128
  }
115
129
 
116
- static void
117
- hash_set_value(ParseInfo pi, Val parent, VALUE value) {
118
- rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value);
119
- if (Yes == pi->options.trace) {
120
- oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
130
+ static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
131
+ rb_hash_aset(stack_peek(&pi->stack)->val,
132
+ oj_calc_hash_key(pi, parent),
133
+ value);
134
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
135
+ oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
121
136
  }
122
137
  }
123
138
 
124
- static VALUE
125
- start_array(ParseInfo pi) {
126
- if (Yes == pi->options.trace) {
127
- oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
139
+ static VALUE start_array(ParseInfo pi) {
140
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
141
+ oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
128
142
  }
129
143
  return rb_ary_new();
130
144
  }
131
145
 
132
- static void
133
- array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
134
- volatile VALUE rstr = rb_str_new(str, len);
146
+ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
147
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
135
148
 
136
- rstr = oj_encode(rstr);
137
149
  rb_ary_push(stack_peek(&pi->stack)->val, rstr);
138
- if (Yes == pi->options.trace) {
139
- oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
150
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
151
+ oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
140
152
  }
141
153
  }
142
154
 
143
- static void
144
- array_append_num(ParseInfo pi, NumInfo ni) {
145
- volatile VALUE v;
146
-
155
+ static void array_append_num(ParseInfo pi, NumInfo ni) {
156
+ volatile VALUE v;
157
+
147
158
  if (ni->infinity || ni->nan) {
148
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
159
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
149
160
  }
150
161
  v = oj_num_as_value(ni);
151
162
  rb_ary_push(stack_peek(&pi->stack)->val, v);
152
- if (Yes == pi->options.trace) {
153
- oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, v);
163
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
164
+ oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, v);
154
165
  }
155
166
  }
156
167
 
157
- static void
158
- array_append_value(ParseInfo pi, VALUE value) {
168
+ static void array_append_value(ParseInfo pi, VALUE value) {
159
169
  rb_ary_push(stack_peek(&pi->stack)->val, value);
160
- if (Yes == pi->options.trace) {
161
- oj_trace_parse_call("append_value", pi, __FILE__, __LINE__, value);
162
- }
163
- }
164
-
165
- void
166
- oj_set_strict_callbacks(ParseInfo pi) {
167
- pi->start_hash = start_hash;
168
- pi->end_hash = hash_end;
169
- pi->hash_key = noop_hash_key;
170
- pi->hash_set_cstr = hash_set_cstr;
171
- pi->hash_set_num = hash_set_num;
172
- pi->hash_set_value = hash_set_value;
173
- pi->start_array = start_array;
174
- pi->end_array = array_end;
175
- pi->array_append_cstr = array_append_cstr;
176
- pi->array_append_num = array_append_num;
170
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
171
+ oj_trace_parse_call("append_value", pi, __FILE__, __LINE__, value);
172
+ }
173
+ }
174
+
175
+ void oj_set_strict_callbacks(ParseInfo pi) {
176
+ pi->start_hash = start_hash;
177
+ pi->end_hash = hash_end;
178
+ pi->hash_key = noop_hash_key;
179
+ pi->hash_set_cstr = hash_set_cstr;
180
+ pi->hash_set_num = hash_set_num;
181
+ pi->hash_set_value = hash_set_value;
182
+ pi->start_array = start_array;
183
+ pi->end_array = array_end;
184
+ pi->array_append_cstr = array_append_cstr;
185
+ pi->array_append_num = array_append_num;
177
186
  pi->array_append_value = array_append_value;
178
- pi->add_cstr = add_cstr;
179
- pi->add_num = add_num;
180
- pi->add_value = add_value;
181
- pi->expect_value = 1;
187
+ pi->add_cstr = add_cstr;
188
+ pi->add_num = add_num;
189
+ pi->add_value = add_value;
190
+ pi->expect_value = 1;
182
191
  }
183
192
 
184
193
  VALUE
185
194
  oj_strict_parse(int argc, VALUE *argv, VALUE self) {
186
- struct _ParseInfo pi;
195
+ struct _parseInfo pi;
187
196
 
188
197
  parse_info_init(&pi);
189
- pi.options = oj_default_options;
190
- pi.handler = Qnil;
198
+ pi.options = oj_default_options;
199
+ pi.handler = Qnil;
191
200
  pi.err_class = Qnil;
192
201
  oj_set_strict_callbacks(&pi);
193
202
 
194
203
  if (T_STRING == rb_type(*argv)) {
195
- return oj_pi_parse(argc, argv, &pi, 0, 0, true);
204
+ return oj_pi_parse(argc, argv, &pi, 0, 0, true);
196
205
  } else {
197
- return oj_pi_sparse(argc, argv, &pi, 0);
206
+ return oj_pi_sparse(argc, argv, &pi, 0);
198
207
  }
199
208
  }
200
209
 
201
210
  VALUE
202
211
  oj_strict_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
203
- struct _ParseInfo pi;
212
+ struct _parseInfo pi;
204
213
 
205
214
  parse_info_init(&pi);
206
- pi.options = oj_default_options;
207
- pi.handler = Qnil;
215
+ pi.options = oj_default_options;
216
+ pi.handler = Qnil;
208
217
  pi.err_class = Qnil;
209
218
  oj_set_strict_callbacks(&pi);
210
219