oj 3.12.2 → 3.13.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) 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 +193 -0
  5. data/ext/oj/cache.h +20 -0
  6. data/ext/oj/compat.c +8 -22
  7. data/ext/oj/custom.c +15 -14
  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 +4 -0
  15. data/ext/oj/fast.c +7 -18
  16. data/ext/oj/intern.c +398 -0
  17. data/ext/oj/intern.h +27 -0
  18. data/ext/oj/mimic_json.c +9 -9
  19. data/ext/oj/object.c +11 -59
  20. data/ext/oj/odd.c +1 -1
  21. data/ext/oj/oj.c +167 -109
  22. data/ext/oj/oj.h +2 -2
  23. data/ext/oj/parse.c +5 -5
  24. data/ext/oj/parser.c +1512 -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 +10 -27
  35. data/ext/oj/string_writer.c +2 -2
  36. data/ext/oj/usual.c +1228 -0
  37. data/ext/oj/validate.c +51 -0
  38. data/ext/oj/wab.c +9 -17
  39. data/lib/oj/error.rb +1 -1
  40. data/lib/oj/mimic.rb +1 -1
  41. data/lib/oj/version.rb +1 -1
  42. data/pages/Modes.md +2 -0
  43. data/pages/Options.md +17 -5
  44. data/pages/Parser.md +309 -0
  45. data/pages/Rails.md +2 -2
  46. data/test/json_gem/json_generator_test.rb +1 -1
  47. data/test/perf_parser.rb +184 -0
  48. data/test/test_hash.rb +1 -1
  49. data/test/test_parser.rb +27 -0
  50. data/test/test_parser_saj.rb +245 -0
  51. data/test/test_parser_usual.rb +213 -0
  52. metadata +22 -5
  53. data/ext/oj/hash.c +0 -168
  54. data/ext/oj/hash.h +0 -21
  55. 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.2
4
+ version: 3.13.2
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-07-25 00:00:00.000000000 Z
11
+ date: 2021-08-16 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
@@ -214,6 +223,7 @@ files:
214
223
  - test/perf_fast.rb
215
224
  - test/perf_file.rb
216
225
  - test/perf_object.rb
226
+ - test/perf_parser.rb
217
227
  - test/perf_saj.rb
218
228
  - test/perf_scp.rb
219
229
  - test/perf_simple.rb
@@ -245,6 +255,9 @@ files:
245
255
  - test/test_integer_range.rb
246
256
  - test/test_null.rb
247
257
  - test/test_object.rb
258
+ - test/test_parser.rb
259
+ - test/test_parser_saj.rb
260
+ - test/test_parser_usual.rb
248
261
  - test/test_rails.rb
249
262
  - test/test_saj.rb
250
263
  - test/test_scp.rb
@@ -339,6 +352,7 @@ test_files:
339
352
  - test/perf_fast.rb
340
353
  - test/perf_file.rb
341
354
  - test/perf_object.rb
355
+ - test/perf_parser.rb
342
356
  - test/perf_saj.rb
343
357
  - test/perf_scp.rb
344
358
  - test/perf_simple.rb
@@ -370,6 +384,9 @@ test_files:
370
384
  - test/test_integer_range.rb
371
385
  - test/test_null.rb
372
386
  - test/test_object.rb
387
+ - test/test_parser.rb
388
+ - test/test_parser_saj.rb
389
+ - test/test_parser_usual.rb
373
390
  - test/test_rails.rb
374
391
  - test/test_saj.rb
375
392
  - 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
- }