oj 3.12.3 → 3.13.3

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -3
  3. data/ext/oj/buf.h +9 -0
  4. data/ext/oj/cache.c +341 -0
  5. data/ext/oj/cache.h +21 -0
  6. data/ext/oj/compat.c +7 -22
  7. data/ext/oj/custom.c +15 -17
  8. data/ext/oj/debug.c +132 -0
  9. data/ext/oj/dump.c +12 -15
  10. data/ext/oj/dump_compat.c +3 -3
  11. data/ext/oj/dump_object.c +9 -9
  12. data/ext/oj/dump_strict.c +3 -3
  13. data/ext/oj/err.h +19 -0
  14. data/ext/oj/extconf.rb +5 -0
  15. data/ext/oj/fast.c +7 -18
  16. data/ext/oj/intern.c +281 -0
  17. data/ext/oj/intern.h +26 -0
  18. data/ext/oj/mimic_json.c +2 -2
  19. data/ext/oj/object.c +15 -92
  20. data/ext/oj/odd.c +1 -1
  21. data/ext/oj/oj.c +117 -94
  22. data/ext/oj/oj.h +1 -1
  23. data/ext/oj/parse.c +5 -5
  24. data/ext/oj/parser.c +1483 -0
  25. data/ext/oj/parser.h +90 -0
  26. data/ext/oj/rails.c +5 -5
  27. data/ext/oj/resolve.c +2 -20
  28. data/ext/oj/rxclass.c +1 -1
  29. data/ext/oj/saj.c +1 -1
  30. data/ext/oj/saj2.c +348 -0
  31. data/ext/oj/scp.c +1 -1
  32. data/ext/oj/sparse.c +2 -2
  33. data/ext/oj/stream_writer.c +4 -4
  34. data/ext/oj/strict.c +9 -27
  35. data/ext/oj/string_writer.c +2 -2
  36. data/ext/oj/usual.c +1252 -0
  37. data/ext/oj/validate.c +51 -0
  38. data/ext/oj/wab.c +14 -19
  39. data/lib/oj/error.rb +1 -1
  40. data/lib/oj/state.rb +8 -7
  41. data/lib/oj/version.rb +1 -1
  42. data/pages/Options.md +1 -1
  43. data/pages/Parser.md +309 -0
  44. data/pages/Rails.md +2 -2
  45. data/test/json_gem/json_generator_test.rb +1 -1
  46. data/test/mem.rb +33 -0
  47. data/test/perf_once.rb +58 -0
  48. data/test/perf_parser.rb +189 -0
  49. data/test/test_hash.rb +1 -1
  50. data/test/test_parser.rb +27 -0
  51. data/test/test_parser_saj.rb +245 -0
  52. data/test/test_parser_usual.rb +213 -0
  53. metadata +26 -5
  54. data/ext/oj/hash.c +0 -168
  55. data/ext/oj/hash.h +0 -21
  56. data/ext/oj/hash_test.c +0 -491
@@ -0,0 +1,213 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << File.dirname(__FILE__)
5
+
6
+ require 'helper'
7
+
8
+ class UsualTest < Minitest::Test
9
+
10
+ def test_nil
11
+ p = Oj::Parser.new(:usual)
12
+ doc = p.parse('nil')
13
+ assert_nil(doc)
14
+ end
15
+
16
+ def test_primitive
17
+ p = Oj::Parser.new(:usual)
18
+ [
19
+ ['true', true],
20
+ ['false', false],
21
+ ['123', 123],
22
+ ['1.25', 1.25],
23
+ ['"abc"', 'abc'],
24
+ ].each { |x|
25
+ doc = p.parse(x[0])
26
+ assert_equal(x[1], doc)
27
+ }
28
+ end
29
+
30
+ def test_big
31
+ p = Oj::Parser.new(:usual)
32
+ doc = p.parse('12345678901234567890123456789')
33
+ assert_equal(BigDecimal, doc.class)
34
+ doc = p.parse('1234567890.1234567890123456789')
35
+ assert_equal(BigDecimal, doc.class)
36
+ end
37
+
38
+ def test_array
39
+ p = Oj::Parser.new(:usual)
40
+ [
41
+ ['[]', []],
42
+ ['[false]', [false]],
43
+ ['[true,false]', [true,false]],
44
+ ['[[]]', [[]]],
45
+ ['[true,[],false]', [true,[],false]],
46
+ ['[true,[true],false]', [true,[true],false]],
47
+ ].each { |x|
48
+ doc = p.parse(x[0])
49
+ assert_equal(x[1], doc)
50
+ }
51
+ end
52
+
53
+ def test_hash
54
+ p = Oj::Parser.new(:usual)
55
+ [
56
+ ['{}', {}],
57
+ ['{"a": null}', {'a' => nil}],
58
+ ['{"t": true, "f": false, "s": "abc"}', {'t' => true, 'f' => false, 's' => 'abc'}],
59
+ ['{"a": {}}', {'a' => {}}],
60
+ ['{"a": {"b": 2}}', {'a' => {'b' => 2}}],
61
+ ['{"a": [true]}', {'a' => [true]}],
62
+ ].each { |x|
63
+ doc = p.parse(x[0])
64
+ assert_equal(x[1], doc)
65
+ }
66
+ end
67
+
68
+ def test_symbol_keys
69
+ p = Oj::Parser.new(:usual)
70
+ assert_equal(false, p.symbol_keys)
71
+ p.symbol_keys = true
72
+ doc = p.parse('{"a": true, "b": false}')
73
+ assert_equal({a: true, b: false}, doc)
74
+ end
75
+
76
+ def test_capacity
77
+ p = Oj::Parser.new(:usual)
78
+ p.capacity = 1000
79
+ assert_equal(4096, p.capacity)
80
+ p.capacity = 5000
81
+ assert_equal(5000, p.capacity)
82
+ end
83
+
84
+ def test_decimal
85
+ p = Oj::Parser.new(:usual)
86
+ assert_equal(:auto, p.decimal)
87
+ doc = p.parse('1.234567890123456789')
88
+ assert_equal(BigDecimal, doc.class)
89
+ assert_equal('0.1234567890123456789e1', doc.to_s)
90
+ doc = p.parse('1.25')
91
+ assert_equal(Float, doc.class)
92
+
93
+ p.decimal = :float
94
+ assert_equal(:float, p.decimal)
95
+ doc = p.parse('1.234567890123456789')
96
+ assert_equal(Float, doc.class)
97
+
98
+ p.decimal = :bigdecimal
99
+ assert_equal(:bigdecimal, p.decimal)
100
+ doc = p.parse('1.234567890123456789')
101
+ assert_equal(BigDecimal, doc.class)
102
+ doc = p.parse('1.25')
103
+ assert_equal(BigDecimal, doc.class)
104
+ assert_equal('0.125e1', doc.to_s)
105
+
106
+ p.decimal = :ruby
107
+ assert_equal(:ruby, p.decimal)
108
+ doc = p.parse('1.234567890123456789')
109
+ assert_equal(Float, doc.class)
110
+ end
111
+
112
+ def test_omit_null
113
+ p = Oj::Parser.new(:usual)
114
+ p.omit_null = true
115
+ doc = p.parse('{"a":true,"b":null}')
116
+ assert_equal({'a'=>true}, doc)
117
+
118
+ p.omit_null = false
119
+ doc = p.parse('{"a":true,"b":null}')
120
+ assert_equal({'a'=>true, 'b'=>nil}, doc)
121
+ end
122
+
123
+ class MyArray < Array
124
+ end
125
+
126
+ def test_array_class
127
+ p = Oj::Parser.new(:usual)
128
+ p.array_class = MyArray
129
+ assert_equal(MyArray, p.array_class)
130
+ doc = p.parse('[true]')
131
+ assert_equal(MyArray, doc.class)
132
+ end
133
+
134
+ class MyHash < Hash
135
+ end
136
+
137
+ def test_hash_class
138
+ p = Oj::Parser.new(:usual)
139
+ p.hash_class = MyHash
140
+ assert_equal(MyHash, p.hash_class)
141
+ doc = p.parse('{"a":true}')
142
+ assert_equal(MyHash, doc.class)
143
+ end
144
+
145
+ class MyClass
146
+ attr_accessor :a
147
+ attr_accessor :b
148
+
149
+ def to_s
150
+ "#{self.class}{a: #{@a} b: #{b}}"
151
+ end
152
+ end
153
+
154
+ class MyClass2 < MyClass
155
+ def self.json_create(arg)
156
+ obj = new
157
+ obj.a = arg['a']
158
+ obj.b = arg['b']
159
+ obj
160
+ end
161
+ end
162
+
163
+ def test_create_id
164
+ p = Oj::Parser.new(:usual)
165
+ p.create_id = '^'
166
+ doc = p.parse('{"a":true}')
167
+ assert_equal(Hash, doc.class)
168
+ doc = p.parse('{"a":true,"^":"UsualTest::MyClass","b":false}')
169
+ assert_equal('UsualTest::MyClass{a: true b: false}', doc.to_s)
170
+
171
+ doc = p.parse('{"a":true,"^":"UsualTest::MyClass2","b":false}')
172
+ assert_equal('UsualTest::MyClass2{a: true b: false}', doc.to_s)
173
+
174
+ p.hash_class = MyHash
175
+ assert_equal(MyHash, p.hash_class)
176
+ doc = p.parse('{"a":true}')
177
+ assert_equal(MyHash, doc.class)
178
+
179
+ doc = p.parse('{"a":true,"^":"UsualTest::MyClass","b":false}')
180
+ assert_equal('UsualTest::MyClass{a: true b: false}', doc.to_s)
181
+ end
182
+
183
+ def test_missing_class
184
+ p = Oj::Parser.new(:usual)
185
+ p.create_id = '^'
186
+ json = '{"a":true,"^":"Auto","b":false}'
187
+ doc = p.parse(json)
188
+ assert_equal(Hash, doc.class)
189
+
190
+ p.missing_class = :auto
191
+ doc = p.parse(json)
192
+ # Auto should be defined after parsing
193
+ assert_equal(Auto, doc.class)
194
+ end
195
+
196
+ def test_class_cache
197
+ p = Oj::Parser.new(:usual)
198
+ p.create_id = '^'
199
+ p.class_cache = true
200
+ p.missing_class = :auto
201
+ json = '{"a":true,"^":"Auto2","b":false}'
202
+ doc = p.parse(json)
203
+ assert_equal(Auto2, doc.class)
204
+
205
+ doc = p.parse(json)
206
+ assert_equal(Auto2, doc.class)
207
+ end
208
+
209
+ def test_default_parser
210
+ doc = Oj::Parser.usual.parse('{"a":true,"b":null}')
211
+ assert_equal({'a'=>true, 'b'=>nil}, doc)
212
+ end
213
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oj
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.12.3
4
+ version: 3.13.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-02 00:00:00.000000000 Z
11
+ date: 2021-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -86,6 +86,7 @@ extra_rdoc_files:
86
86
  - pages/JsonGem.md
87
87
  - pages/Modes.md
88
88
  - pages/Options.md
89
+ - pages/Parser.md
89
90
  - pages/Rails.md
90
91
  - pages/Security.md
91
92
  - pages/WAB.md
@@ -93,6 +94,8 @@ files:
93
94
  - LICENSE
94
95
  - README.md
95
96
  - ext/oj/buf.h
97
+ - ext/oj/cache.c
98
+ - ext/oj/cache.h
96
99
  - ext/oj/cache8.c
97
100
  - ext/oj/cache8.h
98
101
  - ext/oj/circarray.c
@@ -101,6 +104,7 @@ files:
101
104
  - ext/oj/code.h
102
105
  - ext/oj/compat.c
103
106
  - ext/oj/custom.c
107
+ - ext/oj/debug.c
104
108
  - ext/oj/dump.c
105
109
  - ext/oj/dump.h
106
110
  - ext/oj/dump_compat.c
@@ -112,9 +116,8 @@ files:
112
116
  - ext/oj/err.h
113
117
  - ext/oj/extconf.rb
114
118
  - ext/oj/fast.c
115
- - ext/oj/hash.c
116
- - ext/oj/hash.h
117
- - ext/oj/hash_test.c
119
+ - ext/oj/intern.c
120
+ - ext/oj/intern.h
118
121
  - ext/oj/mimic_json.c
119
122
  - ext/oj/object.c
120
123
  - ext/oj/odd.c
@@ -123,6 +126,8 @@ files:
123
126
  - ext/oj/oj.h
124
127
  - ext/oj/parse.c
125
128
  - ext/oj/parse.h
129
+ - ext/oj/parser.c
130
+ - ext/oj/parser.h
126
131
  - ext/oj/rails.c
127
132
  - ext/oj/rails.h
128
133
  - ext/oj/reader.c
@@ -132,6 +137,7 @@ files:
132
137
  - ext/oj/rxclass.c
133
138
  - ext/oj/rxclass.h
134
139
  - ext/oj/saj.c
140
+ - ext/oj/saj2.c
135
141
  - ext/oj/scp.c
136
142
  - ext/oj/sparse.c
137
143
  - ext/oj/stream_writer.c
@@ -139,10 +145,12 @@ files:
139
145
  - ext/oj/string_writer.c
140
146
  - ext/oj/trace.c
141
147
  - ext/oj/trace.h
148
+ - ext/oj/usual.c
142
149
  - ext/oj/util.c
143
150
  - ext/oj/util.h
144
151
  - ext/oj/val_stack.c
145
152
  - ext/oj/val_stack.h
153
+ - ext/oj/validate.c
146
154
  - ext/oj/wab.c
147
155
  - lib/oj.rb
148
156
  - lib/oj/active_support_helper.rb
@@ -162,6 +170,7 @@ files:
162
170
  - pages/JsonGem.md
163
171
  - pages/Modes.md
164
172
  - pages/Options.md
173
+ - pages/Parser.md
165
174
  - pages/Rails.md
166
175
  - pages/Security.md
167
176
  - pages/WAB.md
@@ -209,11 +218,14 @@ files:
209
218
  - test/json_gem/json_parser_test.rb
210
219
  - test/json_gem/json_string_matching_test.rb
211
220
  - test/json_gem/test_helper.rb
221
+ - test/mem.rb
212
222
  - test/perf.rb
213
223
  - test/perf_compat.rb
214
224
  - test/perf_fast.rb
215
225
  - test/perf_file.rb
216
226
  - test/perf_object.rb
227
+ - test/perf_once.rb
228
+ - test/perf_parser.rb
217
229
  - test/perf_saj.rb
218
230
  - test/perf_scp.rb
219
231
  - test/perf_simple.rb
@@ -245,6 +257,9 @@ files:
245
257
  - test/test_integer_range.rb
246
258
  - test/test_null.rb
247
259
  - test/test_object.rb
260
+ - test/test_parser.rb
261
+ - test/test_parser_saj.rb
262
+ - test/test_parser_usual.rb
248
263
  - test/test_rails.rb
249
264
  - test/test_saj.rb
250
265
  - test/test_scp.rb
@@ -334,11 +349,14 @@ test_files:
334
349
  - test/json_gem/json_parser_test.rb
335
350
  - test/json_gem/json_string_matching_test.rb
336
351
  - test/json_gem/test_helper.rb
352
+ - test/mem.rb
337
353
  - test/perf.rb
338
354
  - test/perf_compat.rb
339
355
  - test/perf_fast.rb
340
356
  - test/perf_file.rb
341
357
  - test/perf_object.rb
358
+ - test/perf_once.rb
359
+ - test/perf_parser.rb
342
360
  - test/perf_saj.rb
343
361
  - test/perf_scp.rb
344
362
  - test/perf_simple.rb
@@ -370,6 +388,9 @@ test_files:
370
388
  - test/test_integer_range.rb
371
389
  - test/test_null.rb
372
390
  - test/test_object.rb
391
+ - test/test_parser.rb
392
+ - test/test_parser_saj.rb
393
+ - test/test_parser_usual.rb
373
394
  - test/test_rails.rb
374
395
  - test/test_saj.rb
375
396
  - test/test_scp.rb
data/ext/oj/hash.c DELETED
@@ -1,168 +0,0 @@
1
- // Copyright (c) 2011 Peter Ohler. All rights reserved.
2
- // Licensed under the MIT License. See LICENSE file in the project root for license details.
3
-
4
- #include "hash.h"
5
-
6
- #include <stdint.h>
7
-
8
- #define HASH_SLOT_CNT ((uint32_t)8192)
9
- #define HASH_MASK (HASH_SLOT_CNT - 1)
10
-
11
- typedef struct _keyVal {
12
- struct _keyVal *next;
13
- const char * key;
14
- size_t len;
15
- VALUE val;
16
- } * KeyVal;
17
-
18
- struct _hash {
19
- struct _keyVal slots[HASH_SLOT_CNT];
20
- };
21
-
22
- struct _hash class_hash;
23
- struct _hash str_hash;
24
- struct _hash sym_hash;
25
- struct _hash intern_hash;
26
-
27
- // almost the Murmur hash algorithm
28
- #define M 0x5bd1e995
29
- #define C1 0xCC9E2D51
30
- #define C2 0x1B873593
31
- #define N 0xE6546B64
32
-
33
- static uint32_t hash_calc(const uint8_t *key, size_t len) {
34
- const uint8_t *end = key + len;
35
- const uint8_t *endless = key + (len / 4 * 4);
36
- uint32_t h = (uint32_t)len;
37
- uint32_t k;
38
-
39
- while (key < endless) {
40
- k = (uint32_t)*key++;
41
- k |= (uint32_t)*key++ << 8;
42
- k |= (uint32_t)*key++ << 16;
43
- k |= (uint32_t)*key++ << 24;
44
-
45
- k *= M;
46
- k ^= k >> 24;
47
- h *= M;
48
- h ^= k * M;
49
- }
50
- if (1 < end - key) {
51
- uint16_t k16 = (uint16_t)*key++;
52
-
53
- k16 |= (uint16_t)*key++ << 8;
54
- h ^= k16 << 8;
55
- }
56
- if (key < end) {
57
- h ^= *key;
58
- }
59
- h *= M;
60
- h ^= h >> 13;
61
- h *= M;
62
- h ^= h >> 15;
63
-
64
- return h;
65
- }
66
-
67
- void oj_hash_init() {
68
- memset(class_hash.slots, 0, sizeof(class_hash.slots));
69
- memset(str_hash.slots, 0, sizeof(str_hash.slots));
70
- memset(sym_hash.slots, 0, sizeof(sym_hash.slots));
71
- memset(intern_hash.slots, 0, sizeof(intern_hash.slots));
72
- }
73
-
74
- // if slotp is 0 then just lookup
75
- static VALUE hash_get(Hash hash, const char *key, size_t len, VALUE **slotp, VALUE def_value) {
76
- uint32_t h = hash_calc((const uint8_t *)key, len) & HASH_MASK;
77
- KeyVal bucket = hash->slots + h;
78
-
79
- if (0 != bucket->key) {
80
- KeyVal b;
81
-
82
- for (b = bucket; 0 != b; b = b->next) {
83
- if (len == b->len && 0 == strncmp(b->key, key, len)) {
84
- *slotp = &b->val;
85
- return b->val;
86
- }
87
- bucket = b;
88
- }
89
- }
90
- if (0 != slotp) {
91
- if (0 != bucket->key) {
92
- KeyVal b = ALLOC(struct _keyVal);
93
-
94
- b->next = 0;
95
- bucket->next = b;
96
- bucket = b;
97
- }
98
- bucket->key = oj_strndup(key, len);
99
- bucket->len = len;
100
- bucket->val = def_value;
101
- *slotp = &bucket->val;
102
- }
103
- return def_value;
104
- }
105
-
106
- void oj_hash_print() {
107
- uint32_t i;
108
- KeyVal b;
109
-
110
- for (i = 0; i < HASH_SLOT_CNT; i++) {
111
- printf("%4d:", i);
112
- for (b = class_hash.slots + i; 0 != b && 0 != b->key; b = b->next) {
113
- printf(" %s", b->key);
114
- }
115
- printf("\n");
116
- }
117
- }
118
-
119
- void oj_hash_sizes() {
120
- uint32_t i;
121
- KeyVal b;
122
- int max = 0;
123
- int min = 1000000;
124
-
125
- for (i = 0; i < HASH_SLOT_CNT; i++) {
126
- int cnt = 0;
127
-
128
- for (b = str_hash.slots + i; 0 != b && 0 != b->key; b = b->next) {
129
- cnt++;
130
- }
131
- // printf(" %4d\n", cnt);
132
- if (max < cnt) {
133
- max = cnt;
134
- }
135
- if (cnt < min) {
136
- min = cnt;
137
- }
138
- }
139
- printf("min: %d max: %d\n", min, max);
140
- }
141
-
142
- VALUE
143
- oj_class_hash_get(const char *key, size_t len, VALUE **slotp) {
144
- return hash_get(&class_hash, key, len, slotp, Qnil);
145
- }
146
-
147
- VALUE
148
- oj_str_hash_get(const char *key, size_t len, VALUE **slotp) {
149
- return hash_get(&str_hash, key, len, slotp, Qnil);
150
- }
151
-
152
- VALUE
153
- oj_sym_hash_get(const char *key, size_t len, VALUE **slotp) {
154
- return hash_get(&sym_hash, key, len, slotp, Qnil);
155
- }
156
-
157
- ID oj_attr_hash_get(const char *key, size_t len, ID **slotp) {
158
- return (ID)hash_get(&intern_hash, key, len, (VALUE **)slotp, 0);
159
- }
160
-
161
- char *oj_strndup(const char *s, size_t len) {
162
- char *d = ALLOC_N(char, len + 1);
163
-
164
- memcpy(d, s, len);
165
- d[len] = '\0';
166
-
167
- return d;
168
- }