oj 3.7.4 → 3.11.2
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.
- checksums.yaml +4 -4
- data/README.md +12 -4
- data/ext/oj/buf.h +6 -34
- data/ext/oj/cache8.c +3 -3
- data/ext/oj/cache8.h +5 -33
- data/ext/oj/circarray.c +5 -9
- data/ext/oj/circarray.h +5 -8
- data/ext/oj/code.c +3 -6
- data/ext/oj/code.h +7 -10
- data/ext/oj/compat.c +11 -14
- data/ext/oj/custom.c +108 -75
- data/ext/oj/dump.c +132 -92
- data/ext/oj/dump.h +6 -7
- data/ext/oj/dump_compat.c +37 -34
- data/ext/oj/dump_leaf.c +3 -6
- data/ext/oj/dump_object.c +23 -17
- data/ext/oj/dump_strict.c +7 -9
- data/ext/oj/encode.h +6 -32
- data/ext/oj/err.c +2 -5
- data/ext/oj/err.h +6 -34
- data/ext/oj/extconf.rb +6 -0
- data/ext/oj/fast.c +39 -56
- data/ext/oj/hash.c +11 -39
- data/ext/oj/hash.h +5 -33
- data/ext/oj/hash_test.c +3 -31
- data/ext/oj/mimic_json.c +65 -44
- data/ext/oj/object.c +38 -69
- data/ext/oj/odd.c +18 -17
- data/ext/oj/odd.h +6 -9
- data/ext/oj/oj.c +139 -93
- data/ext/oj/oj.h +43 -35
- data/ext/oj/parse.c +164 -60
- data/ext/oj/parse.h +30 -31
- data/ext/oj/rails.c +119 -83
- data/ext/oj/rails.h +4 -7
- data/ext/oj/reader.c +5 -8
- data/ext/oj/reader.h +7 -10
- data/ext/oj/resolve.c +4 -7
- data/ext/oj/resolve.h +4 -7
- data/ext/oj/rxclass.c +8 -11
- data/ext/oj/rxclass.h +8 -11
- data/ext/oj/saj.c +9 -12
- data/ext/oj/scp.c +4 -7
- data/ext/oj/sparse.c +67 -33
- data/ext/oj/stream_writer.c +16 -15
- data/ext/oj/strict.c +9 -12
- data/ext/oj/string_writer.c +27 -8
- data/ext/oj/trace.c +5 -8
- data/ext/oj/trace.h +9 -12
- data/ext/oj/util.c +136 -0
- data/ext/oj/util.h +19 -0
- data/ext/oj/val_stack.c +28 -36
- data/ext/oj/val_stack.h +19 -50
- data/ext/oj/wab.c +29 -29
- data/lib/oj.rb +0 -8
- data/lib/oj/json.rb +1 -1
- data/lib/oj/mimic.rb +46 -2
- data/lib/oj/version.rb +2 -2
- data/pages/Modes.md +47 -45
- data/pages/Options.md +43 -10
- data/pages/Rails.md +60 -21
- data/pages/Security.md +1 -1
- data/test/activesupport5/abstract_unit.rb +45 -0
- data/test/activesupport5/decoding_test.rb +68 -60
- data/test/activesupport5/encoding_test.rb +111 -96
- data/test/activesupport5/encoding_test_cases.rb +33 -25
- data/test/activesupport5/test_helper.rb +43 -21
- data/test/activesupport5/time_zone_test_helpers.rb +18 -3
- data/test/activesupport6/abstract_unit.rb +44 -0
- data/test/activesupport6/decoding_test.rb +133 -0
- data/test/activesupport6/encoding_test.rb +507 -0
- data/test/activesupport6/encoding_test_cases.rb +98 -0
- data/test/activesupport6/test_common.rb +17 -0
- data/test/activesupport6/test_helper.rb +163 -0
- data/test/activesupport6/time_zone_test_helpers.rb +39 -0
- data/test/bar.rb +24 -6
- data/test/baz.rb +16 -0
- data/test/foo.rb +26 -57
- data/test/helper.rb +10 -0
- data/test/json_gem/json_common_interface_test.rb +8 -3
- data/test/json_gem/json_generator_test.rb +15 -3
- data/test/json_gem/test_helper.rb +8 -0
- data/test/prec.rb +23 -0
- data/test/sample_json.rb +1 -1
- data/test/test_compat.rb +21 -10
- data/test/test_custom.rb +135 -8
- data/test/test_integer_range.rb +1 -2
- data/test/test_object.rb +35 -2
- data/test/test_rails.rb +35 -0
- data/test/test_strict.rb +24 -1
- data/test/test_various.rb +52 -63
- data/test/test_writer.rb +19 -2
- data/test/tests.rb +1 -0
- data/test/zoo.rb +13 -0
- metadata +100 -75
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9deb076071bb73df196bc549faa4fc56d42eb8417b70c6a6d050ec086b04a89a
|
4
|
+
data.tar.gz: 0d6f76b98e0e44d639a32b48959ac8aec6316e9b7726190056adc1022b8dac00
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f856c84593191e1eddb72f85187c68c961f248d7e6ecac817f8fbfbba5d6bfbcf46a2691d6eacd307f51ed91a8a8bf637d97f76ab428d11e72b8760c59a35cc
|
7
|
+
data.tar.gz: 18498cc7854a8aace3beaab7d603361acd43545c8dbb8e73dddccee0ebe96aff9d47ca6635b9a7198e37288aa62366f1d81364a4e4be88117866543c773c40ee
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# [](http://www.ohler.com/oj) gem
|
2
2
|
|
3
|
-
[](http://travis-ci.org/ohler55/oj?branch=master)
|
3
|
+
[](http://travis-ci.org/ohler55/oj?branch=master)   [](https://dependabot.com/compatibility-score.html?dependency-name=oj&package-manager=bundler&version-scheme=semver) [](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
|
4
4
|
|
5
5
|
A *fast* JSON parser and Object marshaller as a Ruby gem.
|
6
6
|
|
@@ -42,7 +42,7 @@ gem 'oj'
|
|
42
42
|
|
43
43
|
## Support
|
44
44
|
|
45
|
-
[Get supported Oj with a Tidelift Subscription.](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
|
45
|
+
[Get supported Oj with a Tidelift Subscription.](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme) Security updates are [supported](https://tidelift.com/security).
|
46
46
|
|
47
47
|
## Further Reading
|
48
48
|
|
@@ -65,7 +65,7 @@ See [{file:CHANGELOG.md}](CHANGELOG.md)
|
|
65
65
|
|
66
66
|
## Links
|
67
67
|
|
68
|
-
|
68
|
+
- *Documentation*: http://www.ohler.com/oj/doc, http://rubydoc.info/gems/oj
|
69
69
|
|
70
70
|
- *GitHub* *repo*: https://github.com/ohler55/oj
|
71
71
|
|
@@ -93,4 +93,12 @@ Follow [@peterohler on Twitter](http://twitter.com/peterohler) for announcements
|
|
93
93
|
|
94
94
|
- *OjC, a C JSON parser*: https://www.ohler.com/ojc also at https://github.com/ohler55/ojc
|
95
95
|
|
96
|
-
- *
|
96
|
+
- *Agoo, a high performance Ruby web server supporting GraphQL on GitHub*: https://github.com/ohler55/agoo
|
97
|
+
|
98
|
+
- *Agoo-C, a high performance C web server supporting GraphQL on GitHub*: https://github.com/ohler55/agoo-c
|
99
|
+
|
100
|
+
#### Contributing
|
101
|
+
|
102
|
+
+ Provide a Pull Request off the `develop` branch.
|
103
|
+
+ Report a bug
|
104
|
+
+ Suggest an idea
|
data/ext/oj/buf.h
CHANGED
@@ -1,39 +1,11 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2011, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*
|
5
|
-
* Redistribution and use in source and binary forms, with or without
|
6
|
-
* modification, are permitted provided that the following conditions are met:
|
7
|
-
*
|
8
|
-
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
-
* list of conditions and the following disclaimer.
|
10
|
-
*
|
11
|
-
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
-
* this list of conditions and the following disclaimer in the documentation
|
13
|
-
* and/or other materials provided with the distribution.
|
14
|
-
*
|
15
|
-
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
-
* used to endorse or promote products derived from this software without
|
17
|
-
* specific prior written permission.
|
18
|
-
*
|
19
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
-
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
-
*/
|
1
|
+
// Copyright (c) 2011 Peter Ohler. All rights reserved.
|
30
2
|
|
31
|
-
#ifndef
|
32
|
-
#define
|
3
|
+
#ifndef OJ_BUF_H
|
4
|
+
#define OJ_BUF_H
|
33
5
|
|
34
6
|
#include "ruby.h"
|
35
7
|
|
36
|
-
typedef struct
|
8
|
+
typedef struct _buf {
|
37
9
|
char *head;
|
38
10
|
char *end;
|
39
11
|
char *tail;
|
@@ -78,7 +50,7 @@ buf_append_string(Buf buf, const char *s, size_t slen) {
|
|
78
50
|
memcpy(buf->tail, s, slen);
|
79
51
|
buf->tail += slen;
|
80
52
|
}
|
81
|
-
|
53
|
+
|
82
54
|
inline static void
|
83
55
|
buf_append(Buf buf, char c) {
|
84
56
|
if (buf->end <= buf->tail) {
|
@@ -100,4 +72,4 @@ buf_append(Buf buf, char c) {
|
|
100
72
|
//*buf->tail = '\0'; // for debugging
|
101
73
|
}
|
102
74
|
|
103
|
-
#endif /*
|
75
|
+
#endif /* OJ_BUF_H */
|
data/ext/oj/cache8.c
CHANGED
@@ -14,11 +14,11 @@
|
|
14
14
|
#define DEPTH 16
|
15
15
|
|
16
16
|
typedef union {
|
17
|
-
struct
|
17
|
+
struct _cache8 *child;
|
18
18
|
slot_t value;
|
19
19
|
} Bucket;
|
20
20
|
|
21
|
-
struct
|
21
|
+
struct _cache8 {
|
22
22
|
Bucket buckets[SLOT_CNT];
|
23
23
|
};
|
24
24
|
|
@@ -30,7 +30,7 @@ oj_cache8_new(Cache8 *cache) {
|
|
30
30
|
Bucket *b;
|
31
31
|
int i;
|
32
32
|
|
33
|
-
*cache = ALLOC(struct
|
33
|
+
*cache = ALLOC(struct _cache8);
|
34
34
|
for (i = SLOT_CNT, b = (*cache)->buckets; 0 < i; i--, b++) {
|
35
35
|
b->value = 0;
|
36
36
|
}
|
data/ext/oj/cache8.h
CHANGED
@@ -1,40 +1,12 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2011, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*
|
5
|
-
* Redistribution and use in source and binary forms, with or without
|
6
|
-
* modification, are permitted provided that the following conditions are met:
|
7
|
-
*
|
8
|
-
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
-
* list of conditions and the following disclaimer.
|
10
|
-
*
|
11
|
-
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
-
* this list of conditions and the following disclaimer in the documentation
|
13
|
-
* and/or other materials provided with the distribution.
|
14
|
-
*
|
15
|
-
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
-
* used to endorse or promote products derived from this software without
|
17
|
-
* specific prior written permission.
|
18
|
-
*
|
19
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
-
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
-
*/
|
1
|
+
// Copyright (c) 2011 Peter Ohler. All rights reserved.
|
30
2
|
|
31
|
-
#ifndef
|
32
|
-
#define
|
3
|
+
#ifndef OJ_CACHE8_H
|
4
|
+
#define OJ_CACHE8_H
|
33
5
|
|
34
6
|
#include "ruby.h"
|
35
7
|
#include "stdint.h"
|
36
8
|
|
37
|
-
typedef struct
|
9
|
+
typedef struct _cache8 *Cache8;
|
38
10
|
typedef uint64_t slot_t;
|
39
11
|
typedef uint64_t sid_t;
|
40
12
|
|
@@ -45,4 +17,4 @@ extern slot_t oj_cache8_get(Cache8 cache, sid_t key, slot_t **slot);
|
|
45
17
|
|
46
18
|
extern void oj_cache8_print(Cache8 cache);
|
47
19
|
|
48
|
-
#endif /*
|
20
|
+
#endif /* OJ_CACHE8_H */
|
data/ext/oj/circarray.c
CHANGED
@@ -1,21 +1,18 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2012, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2012 Peter Ohler. All rights reserved.
|
5
2
|
|
6
3
|
#include "circarray.h"
|
7
4
|
|
8
5
|
CircArray
|
9
6
|
oj_circ_array_new() {
|
10
7
|
CircArray ca;
|
11
|
-
|
12
|
-
if (0 == (ca = ALLOC(struct
|
8
|
+
|
9
|
+
if (0 == (ca = ALLOC(struct _circArray))) {
|
13
10
|
rb_raise(rb_eNoMemError, "not enough memory\n");
|
14
11
|
}
|
15
12
|
ca->objs = ca->obj_array;
|
16
13
|
ca->size = sizeof(ca->obj_array) / sizeof(VALUE);
|
17
14
|
ca->cnt = 0;
|
18
|
-
|
15
|
+
|
19
16
|
return ca;
|
20
17
|
}
|
21
18
|
|
@@ -40,7 +37,7 @@ oj_circ_array_set(CircArray ca, VALUE obj, unsigned long id) {
|
|
40
37
|
rb_raise(rb_eNoMemError, "not enough memory\n");
|
41
38
|
}
|
42
39
|
memcpy(ca->objs, ca->obj_array, sizeof(VALUE) * ca->cnt);
|
43
|
-
} else {
|
40
|
+
} else {
|
44
41
|
REALLOC_N(ca->objs, VALUE, cnt);
|
45
42
|
}
|
46
43
|
ca->size = cnt;
|
@@ -65,4 +62,3 @@ oj_circ_array_get(CircArray ca, unsigned long id) {
|
|
65
62
|
}
|
66
63
|
return obj;
|
67
64
|
}
|
68
|
-
|
data/ext/oj/circarray.h
CHANGED
@@ -1,14 +1,11 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2012, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2012 Peter Ohler. All rights reserved.
|
5
2
|
|
6
|
-
#ifndef
|
7
|
-
#define
|
3
|
+
#ifndef OJ_CIRCARRAY_H
|
4
|
+
#define OJ_CIRCARRAY_H
|
8
5
|
|
9
6
|
#include "ruby.h"
|
10
7
|
|
11
|
-
typedef struct
|
8
|
+
typedef struct _circArray {
|
12
9
|
VALUE obj_array[1024];
|
13
10
|
VALUE *objs;
|
14
11
|
unsigned long size; // allocated size or initial array size
|
@@ -20,4 +17,4 @@ extern void oj_circ_array_free(CircArray ca);
|
|
20
17
|
extern void oj_circ_array_set(CircArray ca, VALUE obj, unsigned long id);
|
21
18
|
extern VALUE oj_circ_array_get(CircArray ca, unsigned long id);
|
22
19
|
|
23
|
-
#endif /*
|
20
|
+
#endif /* OJ_CIRCARRAY_H */
|
data/ext/oj/code.c
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2017, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2017 Peter Ohler. All rights reserved.
|
5
2
|
|
6
3
|
#include "code.h"
|
7
4
|
#include "dump.h"
|
@@ -140,7 +137,7 @@ oj_code_attrs(VALUE obj, Attr attrs, int depth, Out out, bool with_class) {
|
|
140
137
|
size_t len = strlen(classname);
|
141
138
|
size_t size = d2 * out->indent + 10 + len + out->opts->create_id_len + sep_len;
|
142
139
|
bool no_comma = true;
|
143
|
-
|
140
|
+
|
144
141
|
assure_size(out, size);
|
145
142
|
*out->cur++ = '{';
|
146
143
|
|
@@ -201,7 +198,7 @@ oj_code_attrs(VALUE obj, Attr attrs, int depth, Out out, bool with_class) {
|
|
201
198
|
char *b = buf + sizeof(buf) - 1;
|
202
199
|
int neg = 0;
|
203
200
|
long num = attrs->num;
|
204
|
-
|
201
|
+
|
205
202
|
if (0 > num) {
|
206
203
|
neg = 1;
|
207
204
|
num = -num;
|
data/ext/oj/code.h
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2017, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2017 Peter Ohler. All rights reserved.
|
5
2
|
|
6
|
-
#ifndef
|
7
|
-
#define
|
3
|
+
#ifndef OJ_CODE_H
|
4
|
+
#define OJ_CODE_H
|
8
5
|
|
9
6
|
#include <ruby.h>
|
10
7
|
|
@@ -13,7 +10,7 @@
|
|
13
10
|
typedef void (*EncodeFunc)(VALUE obj, int depth, Out out);
|
14
11
|
typedef VALUE (*DecodeFunc)(VALUE clas, VALUE args);
|
15
12
|
|
16
|
-
typedef struct
|
13
|
+
typedef struct _code {
|
17
14
|
const char *name;
|
18
15
|
VALUE clas;
|
19
16
|
EncodeFunc encode;
|
@@ -22,7 +19,7 @@ typedef struct _Code {
|
|
22
19
|
} *Code;
|
23
20
|
|
24
21
|
// Used by encode functions.
|
25
|
-
typedef struct
|
22
|
+
typedef struct _attr {
|
26
23
|
const char *name;
|
27
24
|
int len;
|
28
25
|
VALUE value;
|
@@ -37,6 +34,6 @@ extern bool oj_code_has(Code codes, VALUE clas, bool encode);
|
|
37
34
|
|
38
35
|
extern void oj_code_attrs(VALUE obj, Attr attrs, int depth, Out out, bool with_class);
|
39
36
|
|
40
|
-
extern struct
|
37
|
+
extern struct _code oj_compat_codes[];
|
41
38
|
|
42
|
-
#endif /*
|
39
|
+
#endif /* OJ_CODE_H */
|
data/ext/oj/compat.c
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2012, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2012 Peter Ohler. All rights reserved.
|
5
2
|
|
6
3
|
#include <stdio.h>
|
7
4
|
|
@@ -65,7 +62,7 @@ hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *o
|
|
65
62
|
static VALUE
|
66
63
|
start_hash(ParseInfo pi) {
|
67
64
|
volatile VALUE h;
|
68
|
-
|
65
|
+
|
69
66
|
if (Qnil != pi->options.hash_class) {
|
70
67
|
h = rb_class_new_instance(0, NULL, pi->options.hash_class);
|
71
68
|
} else {
|
@@ -78,7 +75,7 @@ start_hash(ParseInfo pi) {
|
|
78
75
|
}
|
79
76
|
|
80
77
|
static void
|
81
|
-
end_hash(struct
|
78
|
+
end_hash(struct _parseInfo *pi) {
|
82
79
|
Val parent = stack_peek(&pi->stack);
|
83
80
|
|
84
81
|
if (0 != parent->classname) {
|
@@ -87,7 +84,7 @@ end_hash(struct _ParseInfo *pi) {
|
|
87
84
|
clas = oj_name2class(pi, parent->classname, parent->clen, 0, rb_eArgError);
|
88
85
|
if (Qundef != clas) { // else an error
|
89
86
|
ID creatable = rb_intern("json_creatable?");
|
90
|
-
|
87
|
+
|
91
88
|
if (!rb_respond_to(clas, creatable) || Qtrue == rb_funcall(clas, creatable, 0)) {
|
92
89
|
parent->val = rb_funcall(clas, oj_json_create_id, 1, parent->val);
|
93
90
|
}
|
@@ -144,9 +141,9 @@ add_num(ParseInfo pi, NumInfo ni) {
|
|
144
141
|
}
|
145
142
|
|
146
143
|
static void
|
147
|
-
hash_set_num(struct
|
144
|
+
hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) {
|
148
145
|
volatile VALUE rval = oj_num_as_value(ni);
|
149
|
-
|
146
|
+
|
150
147
|
if (!oj_use_hash_alt && rb_cHash != rb_obj_class(parent->val)) {
|
151
148
|
// The rb_hash_set would still work but the unit tests for the
|
152
149
|
// json gem require the less efficient []= method be called to set
|
@@ -192,7 +189,7 @@ static void
|
|
192
189
|
array_append_num(ParseInfo pi, NumInfo ni) {
|
193
190
|
Val parent = stack_peek(&pi->stack);
|
194
191
|
volatile VALUE rval = oj_num_as_value(ni);
|
195
|
-
|
192
|
+
|
196
193
|
if (!oj_use_array_alt && rb_cArray != rb_obj_class(parent->val)) {
|
197
194
|
// The rb_ary_push would still work but the unit tests for the json
|
198
195
|
// gem require the less efficient << method be called to push the
|
@@ -242,7 +239,7 @@ oj_set_compat_callbacks(ParseInfo pi) {
|
|
242
239
|
|
243
240
|
VALUE
|
244
241
|
oj_compat_parse(int argc, VALUE *argv, VALUE self) {
|
245
|
-
struct
|
242
|
+
struct _parseInfo pi;
|
246
243
|
|
247
244
|
parse_info_init(&pi);
|
248
245
|
pi.options = oj_default_options;
|
@@ -263,7 +260,7 @@ oj_compat_parse(int argc, VALUE *argv, VALUE self) {
|
|
263
260
|
|
264
261
|
VALUE
|
265
262
|
oj_compat_load(int argc, VALUE *argv, VALUE self) {
|
266
|
-
struct
|
263
|
+
struct _parseInfo pi;
|
267
264
|
|
268
265
|
parse_info_init(&pi);
|
269
266
|
pi.options = oj_default_options;
|
@@ -274,7 +271,7 @@ oj_compat_load(int argc, VALUE *argv, VALUE self) {
|
|
274
271
|
pi.options.nilnil = Yes;
|
275
272
|
pi.options.empty_string = Yes;
|
276
273
|
oj_set_compat_callbacks(&pi);
|
277
|
-
|
274
|
+
|
278
275
|
if (T_STRING == rb_type(*argv)) {
|
279
276
|
return oj_pi_parse(argc, argv, &pi, 0, 0, false);
|
280
277
|
} else {
|
@@ -284,7 +281,7 @@ oj_compat_load(int argc, VALUE *argv, VALUE self) {
|
|
284
281
|
|
285
282
|
VALUE
|
286
283
|
oj_compat_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
|
287
|
-
struct
|
284
|
+
struct _parseInfo pi;
|
288
285
|
|
289
286
|
parse_info_init(&pi);
|
290
287
|
pi.options = oj_default_options;
|
data/ext/oj/custom.c
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2012, 2017, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2012, 2017 Peter Ohler. All rights reserved.
|
5
2
|
|
3
|
+
#include <stdint.h>
|
6
4
|
#include <stdio.h>
|
7
5
|
|
8
6
|
#include "code.h"
|
@@ -15,13 +13,14 @@
|
|
15
13
|
#include "parse.h"
|
16
14
|
#include "resolve.h"
|
17
15
|
#include "trace.h"
|
16
|
+
#include "util.h"
|
18
17
|
|
19
18
|
extern void oj_set_obj_ivar(Val parent, Val kval, VALUE value);
|
20
19
|
extern VALUE oj_parse_xml_time(const char *str, int len); // from object.c
|
21
20
|
|
22
21
|
static void
|
23
22
|
dump_obj_str(VALUE obj, int depth, Out out) {
|
24
|
-
struct
|
23
|
+
struct _attr attrs[] = {
|
25
24
|
{ "s", 1, Qnil },
|
26
25
|
{ NULL, 0, Qnil },
|
27
26
|
};
|
@@ -30,6 +29,13 @@ dump_obj_str(VALUE obj, int depth, Out out) {
|
|
30
29
|
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
31
30
|
}
|
32
31
|
|
32
|
+
static void
|
33
|
+
dump_obj_as_str(VALUE obj, int depth, Out out) {
|
34
|
+
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
35
|
+
const char *str = rb_string_value_ptr((VALUE*)&rstr);
|
36
|
+
|
37
|
+
oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
|
38
|
+
}
|
33
39
|
|
34
40
|
static void
|
35
41
|
bigdecimal_dump(VALUE obj, int depth, Out out) {
|
@@ -55,19 +61,23 @@ static ID imag_id = 0;
|
|
55
61
|
|
56
62
|
static void
|
57
63
|
complex_dump(VALUE obj, int depth, Out out) {
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
if (NULL != out->opts->create_id) {
|
65
|
+
struct _attr attrs[] = {
|
66
|
+
{ "real", 4, Qnil },
|
67
|
+
{ "imag", 4, Qnil },
|
68
|
+
{ NULL, 0, Qnil },
|
69
|
+
};
|
70
|
+
if (0 == real_id) {
|
71
|
+
real_id = rb_intern("real");
|
72
|
+
imag_id = rb_intern("imag");
|
73
|
+
}
|
74
|
+
attrs[0].value = rb_funcall(obj, real_id, 0);
|
75
|
+
attrs[1].value = rb_funcall(obj, imag_id, 0);
|
69
76
|
|
70
|
-
|
77
|
+
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
78
|
+
} else {
|
79
|
+
dump_obj_as_str(obj, depth, out);
|
80
|
+
}
|
71
81
|
}
|
72
82
|
|
73
83
|
static VALUE
|
@@ -82,7 +92,7 @@ complex_load(VALUE clas, VALUE args) {
|
|
82
92
|
static void
|
83
93
|
time_dump(VALUE obj, int depth, Out out) {
|
84
94
|
if (Yes == out->opts->create_ok) {
|
85
|
-
struct
|
95
|
+
struct _attr attrs[] = {
|
86
96
|
{ "time", 4, Qundef, 0, Qundef },
|
87
97
|
{ NULL, 0, Qnil },
|
88
98
|
};
|
@@ -103,7 +113,7 @@ time_dump(VALUE obj, int depth, Out out) {
|
|
103
113
|
static void
|
104
114
|
date_dump(VALUE obj, int depth, Out out) {
|
105
115
|
if (Yes == out->opts->create_ok) {
|
106
|
-
struct
|
116
|
+
struct _attr attrs[] = {
|
107
117
|
{ "s", 1, Qnil },
|
108
118
|
{ NULL, 0, Qnil },
|
109
119
|
};
|
@@ -113,7 +123,7 @@ date_dump(VALUE obj, int depth, Out out) {
|
|
113
123
|
} else {
|
114
124
|
volatile VALUE v;
|
115
125
|
volatile VALUE ov;
|
116
|
-
|
126
|
+
|
117
127
|
switch (out->opts->time_format) {
|
118
128
|
case RubyTime:
|
119
129
|
case XmlTime:
|
@@ -148,7 +158,7 @@ date_dump(VALUE obj, int depth, Out out) {
|
|
148
158
|
static VALUE
|
149
159
|
date_load(VALUE clas, VALUE args) {
|
150
160
|
volatile VALUE v;
|
151
|
-
|
161
|
+
|
152
162
|
if (Qnil != (v = rb_hash_aref(args, rb_str_new2("s")))) {
|
153
163
|
return rb_funcall(oj_date_class, rb_intern("parse"), 1, v);
|
154
164
|
}
|
@@ -158,7 +168,7 @@ date_load(VALUE clas, VALUE args) {
|
|
158
168
|
static VALUE
|
159
169
|
datetime_load(VALUE clas, VALUE args) {
|
160
170
|
volatile VALUE v;
|
161
|
-
|
171
|
+
|
162
172
|
if (Qnil != (v = rb_hash_aref(args, rb_str_new2("s")))) {
|
163
173
|
return rb_funcall(oj_datetime_class, rb_intern("parse"), 1, v);
|
164
174
|
}
|
@@ -169,7 +179,7 @@ static ID table_id = 0;
|
|
169
179
|
|
170
180
|
static void
|
171
181
|
openstruct_dump(VALUE obj, int depth, Out out) {
|
172
|
-
struct
|
182
|
+
struct _attr attrs[] = {
|
173
183
|
{ "table", 5, Qnil },
|
174
184
|
{ NULL, 0, Qnil },
|
175
185
|
};
|
@@ -191,23 +201,27 @@ openstruct_load(VALUE clas, VALUE args) {
|
|
191
201
|
|
192
202
|
static void
|
193
203
|
range_dump(VALUE obj, int depth, Out out) {
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
204
|
+
if (NULL != out->opts->create_id) {
|
205
|
+
struct _attr attrs[] = {
|
206
|
+
{ "begin", 5, Qnil },
|
207
|
+
{ "end", 3, Qnil },
|
208
|
+
{ "exclude", 7, Qnil },
|
209
|
+
{ NULL, 0, Qnil },
|
210
|
+
};
|
211
|
+
attrs[0].value = rb_funcall(obj, oj_begin_id, 0);
|
212
|
+
attrs[1].value = rb_funcall(obj, oj_end_id, 0);
|
213
|
+
attrs[2].value = rb_funcall(obj, oj_exclude_end_id, 0);
|
203
214
|
|
204
|
-
|
215
|
+
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
216
|
+
} else {
|
217
|
+
dump_obj_as_str(obj, depth, out);
|
218
|
+
}
|
205
219
|
}
|
206
220
|
|
207
221
|
static VALUE
|
208
222
|
range_load(VALUE clas, VALUE args) {
|
209
223
|
VALUE nargs[3];
|
210
|
-
|
224
|
+
|
211
225
|
nargs[0] = rb_hash_aref(args, rb_id2str(oj_begin_id));
|
212
226
|
nargs[1] = rb_hash_aref(args, rb_id2str(oj_end_id));
|
213
227
|
nargs[2] = rb_hash_aref(args, rb_id2str(oj_exclude_end_id));
|
@@ -220,19 +234,23 @@ static ID denominator_id = 0;
|
|
220
234
|
|
221
235
|
static void
|
222
236
|
rational_dump(VALUE obj, int depth, Out out) {
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
237
|
+
if (NULL != out->opts->create_id) {
|
238
|
+
struct _attr attrs[] = {
|
239
|
+
{ "numerator", 9, Qnil },
|
240
|
+
{ "denominator", 11, Qnil },
|
241
|
+
{ NULL, 0, Qnil },
|
242
|
+
};
|
243
|
+
if (0 == numerator_id) {
|
244
|
+
numerator_id = rb_intern("numerator");
|
245
|
+
denominator_id = rb_intern("denominator");
|
246
|
+
}
|
247
|
+
attrs[0].value = rb_funcall(obj, numerator_id, 0);
|
248
|
+
attrs[1].value = rb_funcall(obj, denominator_id, 0);
|
234
249
|
|
235
|
-
|
250
|
+
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
251
|
+
} else {
|
252
|
+
dump_obj_as_str(obj, depth, out);
|
253
|
+
}
|
236
254
|
}
|
237
255
|
|
238
256
|
static VALUE
|
@@ -248,7 +266,7 @@ rational_load(VALUE clas, VALUE args) {
|
|
248
266
|
static VALUE
|
249
267
|
regexp_load(VALUE clas, VALUE args) {
|
250
268
|
volatile VALUE v;
|
251
|
-
|
269
|
+
|
252
270
|
if (Qnil != (v = rb_hash_aref(args, rb_str_new2("s")))) {
|
253
271
|
return rb_funcall(rb_cRegexp, oj_new_id, 1, v);
|
254
272
|
}
|
@@ -262,7 +280,7 @@ time_load(VALUE clas, VALUE args) {
|
|
262
280
|
return args;
|
263
281
|
}
|
264
282
|
|
265
|
-
static struct
|
283
|
+
static struct _code codes[] = {
|
266
284
|
{ "BigDecimal", Qnil, bigdecimal_dump, NULL, true },
|
267
285
|
{ "Complex", Qnil, complex_dump, complex_load, true },
|
268
286
|
{ "Date", Qnil, date_dump, date_load, true },
|
@@ -276,7 +294,8 @@ static struct _Code codes[] = {
|
|
276
294
|
};
|
277
295
|
|
278
296
|
static int
|
279
|
-
hash_cb(VALUE key, VALUE value,
|
297
|
+
hash_cb(VALUE key, VALUE value, VALUE ov) {
|
298
|
+
Out out = (Out)ov;
|
280
299
|
int depth = out->depth;
|
281
300
|
|
282
301
|
if (oj_dump_ignore(out->opts, value)) {
|
@@ -421,7 +440,7 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
421
440
|
v = rb_funcall(obj, *odd->attrs, 0);
|
422
441
|
if (Qundef == v || T_STRING != rb_type(v)) {
|
423
442
|
rb_raise(rb_eEncodingError, "Invalid type for raw JSON.\n");
|
424
|
-
} else {
|
443
|
+
} else {
|
425
444
|
const char *s = rb_string_value_ptr((VALUE*)&v);
|
426
445
|
int len = (int)RSTRING_LEN(v);
|
427
446
|
const char *name = rb_id2name(*odd->attrs);
|
@@ -457,9 +476,11 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
457
476
|
char *n;
|
458
477
|
char *end;
|
459
478
|
ID i;
|
460
|
-
|
479
|
+
|
461
480
|
if (sizeof(nbuf) <= nlen) {
|
462
|
-
n2 = strdup(name)
|
481
|
+
if (NULL == (n2 = strdup(name))) {
|
482
|
+
rb_raise(rb_eNoMemError, "for attribute name.");
|
483
|
+
}
|
463
484
|
} else {
|
464
485
|
strcpy(n2, name);
|
465
486
|
}
|
@@ -493,7 +514,10 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
493
514
|
// Return class if still needs dumping.
|
494
515
|
static VALUE
|
495
516
|
dump_common(VALUE obj, int depth, Out out) {
|
496
|
-
|
517
|
+
|
518
|
+
if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
|
519
|
+
oj_dump_raw_json(obj, depth, out);
|
520
|
+
} else if (Yes == out->opts->to_json && rb_respond_to(obj, oj_to_json_id)) {
|
497
521
|
volatile VALUE rs;
|
498
522
|
const char *s;
|
499
523
|
int len;
|
@@ -566,7 +590,8 @@ dump_common(VALUE obj, int depth, Out out) {
|
|
566
590
|
}
|
567
591
|
|
568
592
|
static int
|
569
|
-
dump_attr_cb(ID key, VALUE value,
|
593
|
+
dump_attr_cb(ID key, VALUE value, VALUE ov) {
|
594
|
+
Out out = (Out)ov;
|
570
595
|
int depth = out->depth;
|
571
596
|
size_t size;
|
572
597
|
const char *attr;
|
@@ -583,6 +608,8 @@ dump_attr_cb(ID key, VALUE value, Out out) {
|
|
583
608
|
// the key name is NULL. Not an empty string but NULL.
|
584
609
|
if (NULL == attr) {
|
585
610
|
attr = "";
|
611
|
+
} else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
|
612
|
+
return ST_CONTINUE;
|
586
613
|
}
|
587
614
|
if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
|
588
615
|
return ST_CONTINUE;
|
@@ -604,7 +631,7 @@ dump_attr_cb(ID key, VALUE value, Out out) {
|
|
604
631
|
oj_dump_custom_val(value, depth, out, true);
|
605
632
|
out->depth = depth;
|
606
633
|
*out->cur++ = ',';
|
607
|
-
|
634
|
+
|
608
635
|
return ST_CONTINUE;
|
609
636
|
}
|
610
637
|
|
@@ -776,7 +803,7 @@ static void
|
|
776
803
|
dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
777
804
|
long id = oj_check_circular(obj, out);
|
778
805
|
VALUE clas;
|
779
|
-
|
806
|
+
|
780
807
|
if (0 > id) {
|
781
808
|
oj_dump_nil(Qnil, depth, out, false);
|
782
809
|
} else if (Qnil != (clas = dump_common(obj, depth, out))) {
|
@@ -789,7 +816,7 @@ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
789
816
|
size_t size = d2 * out->indent + d3 * out->indent + 3;
|
790
817
|
const char *name;
|
791
818
|
int cnt;
|
792
|
-
size_t len;
|
819
|
+
size_t len;
|
793
820
|
|
794
821
|
assure_size(out, size);
|
795
822
|
if (clas == rb_cRange) {
|
@@ -867,7 +894,11 @@ dump_data(VALUE obj, int depth, Out out, bool as_ok) {
|
|
867
894
|
|
868
895
|
static void
|
869
896
|
dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
|
870
|
-
|
897
|
+
if (NULL != out->opts->create_id) {
|
898
|
+
dump_obj_str(obj, depth, out);
|
899
|
+
} else {
|
900
|
+
dump_obj_as_str(obj, depth, out);
|
901
|
+
}
|
871
902
|
}
|
872
903
|
|
873
904
|
static void
|
@@ -997,7 +1028,7 @@ hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *o
|
|
997
1028
|
}
|
998
1029
|
|
999
1030
|
static void
|
1000
|
-
end_hash(struct
|
1031
|
+
end_hash(struct _parseInfo *pi) {
|
1001
1032
|
Val parent = stack_peek(&pi->stack);
|
1002
1033
|
|
1003
1034
|
if (Qundef != parent->clas && parent->clas != rb_obj_class(parent->val)) {
|
@@ -1030,7 +1061,7 @@ calc_hash_key(ParseInfo pi, Val parent) {
|
|
1030
1061
|
}
|
1031
1062
|
|
1032
1063
|
static void
|
1033
|
-
hash_set_num(struct
|
1064
|
+
hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
|
1034
1065
|
Val parent = stack_peek(&pi->stack);
|
1035
1066
|
volatile VALUE rval = oj_num_as_value(ni);
|
1036
1067
|
|
@@ -1039,7 +1070,7 @@ hash_set_num(struct _ParseInfo *pi, Val kval, NumInfo ni) {
|
|
1039
1070
|
oj_set_obj_ivar(parent, kval, rval);
|
1040
1071
|
break;
|
1041
1072
|
case T_HASH:
|
1042
|
-
if (4 == parent->klen && NULL != parent->key && rb_cTime == parent->clas && 0 == strncmp("time", parent->key, 4)) {
|
1073
|
+
if (4 == parent->klen && NULL != parent->key && rb_cTime == parent->clas && 0 != ni->div && 0 == strncmp("time", parent->key, 4)) {
|
1043
1074
|
int64_t nsec = ni->num * 1000000000LL / ni->div;
|
1044
1075
|
|
1045
1076
|
if (ni->neg) {
|
@@ -1055,17 +1086,19 @@ hash_set_num(struct _ParseInfo *pi, Val kval, NumInfo ni) {
|
|
1055
1086
|
// offset and then a conversion to UTC keeps makes the time
|
1056
1087
|
// match the expected value.
|
1057
1088
|
parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
|
1058
|
-
} else if (ni->
|
1059
|
-
|
1060
|
-
struct
|
1061
|
-
VALUE
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
args[
|
1066
|
-
args[
|
1067
|
-
args[
|
1068
|
-
args[
|
1089
|
+
} else if (ni->has_exp) {
|
1090
|
+
int64_t t = (int64_t)(ni->i + ni->exp);
|
1091
|
+
struct _timeInfo ti;
|
1092
|
+
VALUE args[8];
|
1093
|
+
|
1094
|
+
sec_as_time(t, &ti);
|
1095
|
+
|
1096
|
+
args[0] = LONG2NUM(ti.year);
|
1097
|
+
args[1] = LONG2NUM(ti.mon);
|
1098
|
+
args[2] = LONG2NUM(ti.day);
|
1099
|
+
args[3] = LONG2NUM(ti.hour);
|
1100
|
+
args[4] = LONG2NUM(ti.min);
|
1101
|
+
args[5] = rb_float_new((double)ti.sec + ((double)nsec + 0.5) / 1000000000.0);
|
1069
1102
|
args[6] = LONG2NUM(ni->exp);
|
1070
1103
|
parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
|
1071
1104
|
} else {
|
@@ -1107,7 +1140,7 @@ static void
|
|
1107
1140
|
array_append_num(ParseInfo pi, NumInfo ni) {
|
1108
1141
|
Val parent = stack_peek(&pi->stack);
|
1109
1142
|
volatile VALUE rval = oj_num_as_value(ni);
|
1110
|
-
|
1143
|
+
|
1111
1144
|
rb_ary_push(parent->val, rval);
|
1112
1145
|
if (Yes == pi->options.trace) {
|
1113
1146
|
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
@@ -1146,7 +1179,7 @@ oj_set_custom_callbacks(ParseInfo pi) {
|
|
1146
1179
|
|
1147
1180
|
VALUE
|
1148
1181
|
oj_custom_parse(int argc, VALUE *argv, VALUE self) {
|
1149
|
-
struct
|
1182
|
+
struct _parseInfo pi;
|
1150
1183
|
|
1151
1184
|
parse_info_init(&pi);
|
1152
1185
|
pi.options = oj_default_options;
|
@@ -1166,7 +1199,7 @@ oj_custom_parse(int argc, VALUE *argv, VALUE self) {
|
|
1166
1199
|
|
1167
1200
|
VALUE
|
1168
1201
|
oj_custom_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
|
1169
|
-
struct
|
1202
|
+
struct _parseInfo pi;
|
1170
1203
|
|
1171
1204
|
parse_info_init(&pi);
|
1172
1205
|
pi.options = oj_default_options;
|