oj 3.13.23 → 3.14.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +2 -1
- data/ext/oj/buf.h +6 -5
- data/ext/oj/cache.c +11 -10
- data/ext/oj/cache8.c +3 -2
- data/ext/oj/circarray.c +6 -5
- data/ext/oj/compat.c +12 -31
- data/ext/oj/custom.c +16 -31
- data/ext/oj/dump.c +10 -13
- data/ext/oj/dump_compat.c +9 -19
- data/ext/oj/dump_object.c +8 -13
- data/ext/oj/dump_strict.c +8 -18
- data/ext/oj/extconf.rb +10 -2
- data/ext/oj/fast.c +31 -47
- data/ext/oj/intern.c +7 -5
- data/ext/oj/mem.c +324 -0
- data/ext/oj/mem.h +53 -0
- data/ext/oj/mimic_json.c +3 -2
- data/ext/oj/object.c +9 -13
- data/ext/oj/odd.c +7 -6
- data/ext/oj/oj.c +12 -5
- data/ext/oj/oj.h +6 -0
- data/ext/oj/parse.c +18 -13
- data/ext/oj/parser.c +7 -7
- data/ext/oj/rails.c +19 -28
- data/ext/oj/reader.c +4 -3
- data/ext/oj/reader.h +3 -1
- data/ext/oj/rxclass.c +5 -4
- data/ext/oj/saj.c +6 -5
- data/ext/oj/saj2.c +10 -5
- data/ext/oj/sparse.c +5 -4
- data/ext/oj/stream_writer.c +5 -4
- data/ext/oj/strict.c +4 -12
- data/ext/oj/string_writer.c +7 -6
- data/ext/oj/trace.h +16 -0
- data/ext/oj/usual.c +28 -27
- data/ext/oj/val_stack.h +4 -3
- data/ext/oj/wab.c +9 -21
- data/lib/oj/version.rb +1 -1
- data/pages/InstallOptions.md +20 -0
- data/test/foo.rb +46 -65
- data/test/perf_parser.rb +1 -0
- data/test/test_compat.rb +9 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35277d429b423f078c9c259bc2f7d8fd5714f55bb67def193b2b58c1352f3d11
|
4
|
+
data.tar.gz: 337ca936375237d94a5e6a6ece01abd28ce367119fbb72b53dc41c3248c9e136
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e41c8ef241150e82943a92becc0ca0ec501d3ea9f9a2729abcb2529f2f5ac4360bb0a7684d46fd2357c0edb81d9347b5a6228129536c24157df5b0a788a4fc22
|
7
|
+
data.tar.gz: 6b69fcd20fe9956826865a8fafbca921ae0d9d39f43fbb3aa713b8411381852bcbfa16f7b3a3557e0c24e0545fb0a82c120c93c24bcd81ea8616b89fb6db2b47
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 3.14.2 - 2023-02-10
|
4
|
+
|
5
|
+
- Fixed check for \0 in strings.
|
6
|
+
|
7
|
+
## 3.14.1 - 2023-02-01
|
8
|
+
|
9
|
+
- Fixed issue with uninitialized handler for Oj::Parser::Saj.
|
10
|
+
|
11
|
+
- Fixed hang on unterminated string with a \0 byte in parse.c.
|
12
|
+
|
13
|
+
## 3.14.0 - 2023-01-30
|
14
|
+
|
15
|
+
- Tracing is now a compile time option giving a 15 to 20% performance boost.
|
16
|
+
|
17
|
+
- Some cleanup in teh fast parser.
|
18
|
+
|
3
19
|
## 3.13.23 - 2022-11-06
|
4
20
|
|
5
21
|
- Fixed issue with Oj::Parser extension regarding GC timeing.
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# [![{}j](http://www.ohler.com/dev/images/oj_comet_64.svg)](http://www.ohler.com/oj) gem
|
2
2
|
|
3
|
-
[![
|
3
|
+
[![CI](https://github.com/ohler55/oj/actions/workflows/CI.yml/badge.svg)](https://github.com/ohler55/oj/actions/workflows/CI.yml)
|
4
4
|
![Gem](https://img.shields.io/gem/v/oj.svg)
|
5
5
|
![Gem](https://img.shields.io/gem/dt/oj.svg)
|
6
6
|
[![SemVer compatibility](https://api.dependabot.com/badges/compatibility_score?dependency-name=oj&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=oj&package-manager=bundler&version-scheme=semver)
|
@@ -70,6 +70,7 @@ links.
|
|
70
70
|
- [{file:Compatibility.md}](pages/Compatibility.md) lists current compatibility with Rubys and Rails.
|
71
71
|
- [{file:Advanced.md}](pages/Advanced.md) for fast parser and marshalling features.
|
72
72
|
- [{file:Security.md}](pages/Security.md) for security considerations.
|
73
|
+
- [{file:InstallOptions.md}](pages/InstallOptions.md) for install option.
|
73
74
|
|
74
75
|
## Releases
|
75
76
|
|
data/ext/oj/buf.h
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
#define OJ_BUF_H
|
6
6
|
|
7
7
|
#include "ruby.h"
|
8
|
+
#include "mem.h"
|
8
9
|
|
9
10
|
typedef struct _buf {
|
10
11
|
char *head;
|
@@ -25,7 +26,7 @@ inline static void buf_reset(Buf buf) {
|
|
25
26
|
|
26
27
|
inline static void buf_cleanup(Buf buf) {
|
27
28
|
if (buf->base != buf->head) {
|
28
|
-
|
29
|
+
OJ_R_FREE(buf->head);
|
29
30
|
}
|
30
31
|
}
|
31
32
|
|
@@ -49,10 +50,10 @@ inline static void buf_append_string(Buf buf, const char *s, size_t slen) {
|
|
49
50
|
size_t new_len = len + slen + len / 2;
|
50
51
|
|
51
52
|
if (buf->base == buf->head) {
|
52
|
-
buf->head =
|
53
|
+
buf->head = OJ_R_ALLOC_N(char, new_len);
|
53
54
|
memcpy(buf->head, buf->base, len);
|
54
55
|
} else {
|
55
|
-
|
56
|
+
OJ_R_REALLOC_N(buf->head, char, new_len);
|
56
57
|
}
|
57
58
|
buf->tail = buf->head + toff;
|
58
59
|
buf->end = buf->head + new_len - 1;
|
@@ -68,10 +69,10 @@ inline static void buf_append(Buf buf, char c) {
|
|
68
69
|
size_t new_len = len + len / 2;
|
69
70
|
|
70
71
|
if (buf->base == buf->head) {
|
71
|
-
buf->head =
|
72
|
+
buf->head = OJ_R_ALLOC_N(char, new_len);
|
72
73
|
memcpy(buf->head, buf->base, len);
|
73
74
|
} else {
|
74
|
-
|
75
|
+
OJ_R_REALLOC_N(buf->head, char, new_len);
|
75
76
|
}
|
76
77
|
buf->tail = buf->head + toff;
|
77
78
|
buf->end = buf->head + new_len - 1;
|
data/ext/oj/cache.c
CHANGED
@@ -6,6 +6,7 @@
|
|
6
6
|
#endif
|
7
7
|
#include <stdlib.h>
|
8
8
|
|
9
|
+
#include "mem.h"
|
9
10
|
#include "cache.h"
|
10
11
|
|
11
12
|
// The stdlib calloc, realloc, and free are used instead of the Ruby ALLOC,
|
@@ -100,7 +101,7 @@ static void rehash(Cache c) {
|
|
100
101
|
osize = c->size;
|
101
102
|
c->size = osize * 4;
|
102
103
|
c->mask = c->size - 1;
|
103
|
-
c->slots =
|
104
|
+
c->slots = OJ_REALLOC((void *)c->slots, sizeof(Slot) * c->size);
|
104
105
|
memset((Slot *)c->slots + osize, 0, sizeof(Slot) * osize * 3);
|
105
106
|
end = (Slot *)c->slots + osize;
|
106
107
|
for (sp = (Slot *)c->slots; sp < end; sp++) {
|
@@ -128,7 +129,7 @@ static VALUE lockless_intern(Cache c, const char *key, size_t len) {
|
|
128
129
|
while (REUSE_MAX < c->rcnt) {
|
129
130
|
if (NULL != (b = c->reuse)) {
|
130
131
|
c->reuse = b->next;
|
131
|
-
|
132
|
+
OJ_FREE(b);
|
132
133
|
c->rcnt--;
|
133
134
|
} else {
|
134
135
|
// An accounting error occured somewhere so correct it.
|
@@ -143,7 +144,7 @@ static VALUE lockless_intern(Cache c, const char *key, size_t len) {
|
|
143
144
|
}
|
144
145
|
rkey = c->form(key, len);
|
145
146
|
if (NULL == (b = c->reuse)) {
|
146
|
-
b =
|
147
|
+
b = OJ_CALLOC(1, sizeof(struct _slot));
|
147
148
|
} else {
|
148
149
|
c->reuse = b->next;
|
149
150
|
c->rcnt--;
|
@@ -174,7 +175,7 @@ static VALUE locking_intern(Cache c, const char *key, size_t len) {
|
|
174
175
|
while (REUSE_MAX < c->rcnt) {
|
175
176
|
if (NULL != (b = c->reuse)) {
|
176
177
|
c->reuse = b->next;
|
177
|
-
|
178
|
+
OJ_FREE(b);
|
178
179
|
c->rcnt--;
|
179
180
|
} else {
|
180
181
|
// An accounting error occured somewhere so correct it.
|
@@ -200,7 +201,7 @@ static VALUE locking_intern(Cache c, const char *key, size_t len) {
|
|
200
201
|
}
|
201
202
|
CACHE_UNLOCK(c);
|
202
203
|
if (NULL == b) {
|
203
|
-
b =
|
204
|
+
b = OJ_CALLOC(1, sizeof(struct _slot));
|
204
205
|
}
|
205
206
|
rkey = c->form(key, len);
|
206
207
|
b->hash = h;
|
@@ -228,7 +229,7 @@ static VALUE locking_intern(Cache c, const char *key, size_t len) {
|
|
228
229
|
}
|
229
230
|
|
230
231
|
Cache cache_create(size_t size, VALUE (*form)(const char *str, size_t len), bool mark, bool locking) {
|
231
|
-
Cache c =
|
232
|
+
Cache c = OJ_CALLOC(1, sizeof(struct _cache));
|
232
233
|
int shift = 0;
|
233
234
|
|
234
235
|
for (; REHASH_LIMIT < size; size /= 2, shift++) {
|
@@ -243,7 +244,7 @@ Cache cache_create(size_t size, VALUE (*form)(const char *str, size_t len), bool
|
|
243
244
|
#endif
|
244
245
|
c->size = 1 << shift;
|
245
246
|
c->mask = c->size - 1;
|
246
|
-
c->slots =
|
247
|
+
c->slots = OJ_CALLOC(c->size, sizeof(Slot));
|
247
248
|
c->form = form;
|
248
249
|
c->xrate = 1; // low
|
249
250
|
c->mark = mark;
|
@@ -268,11 +269,11 @@ void cache_free(Cache c) {
|
|
268
269
|
|
269
270
|
for (s = c->slots[i]; NULL != s; s = next) {
|
270
271
|
next = s->next;
|
271
|
-
|
272
|
+
OJ_FREE(s);
|
272
273
|
}
|
273
274
|
}
|
274
|
-
|
275
|
-
|
275
|
+
OJ_FREE((void *)c->slots);
|
276
|
+
OJ_FREE(c);
|
276
277
|
}
|
277
278
|
|
278
279
|
void cache_mark(Cache c) {
|
data/ext/oj/cache8.c
CHANGED
@@ -9,6 +9,7 @@
|
|
9
9
|
#include <stdlib.h>
|
10
10
|
#include <string.h>
|
11
11
|
|
12
|
+
#include "mem.h"
|
12
13
|
#include "ruby.h"
|
13
14
|
|
14
15
|
#define BITS 4
|
@@ -32,7 +33,7 @@ void oj_cache8_new(Cache8 *cache) {
|
|
32
33
|
Bucket *b;
|
33
34
|
int i;
|
34
35
|
|
35
|
-
*cache =
|
36
|
+
*cache = OJ_R_ALLOC(struct _cache8);
|
36
37
|
for (i = SLOT_CNT, b = (*cache)->buckets; 0 < i; i--, b++) {
|
37
38
|
b->value = 0;
|
38
39
|
}
|
@@ -51,7 +52,7 @@ static void cache8_delete(Cache8 cache, int depth) {
|
|
51
52
|
}
|
52
53
|
}
|
53
54
|
}
|
54
|
-
|
55
|
+
OJ_R_FREE(cache);
|
55
56
|
}
|
56
57
|
|
57
58
|
slot_t oj_cache8_get(Cache8 cache, sid_t key, slot_t **slot) {
|
data/ext/oj/circarray.c
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
// Copyright (c) 2012 Peter Ohler. All rights reserved.
|
2
2
|
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
3
3
|
|
4
|
+
#include "mem.h"
|
4
5
|
#include "circarray.h"
|
5
6
|
|
6
7
|
CircArray oj_circ_array_new(void) {
|
7
8
|
CircArray ca;
|
8
9
|
|
9
|
-
if (0 == (ca =
|
10
|
+
if (0 == (ca = OJ_R_ALLOC(struct _circArray))) {
|
10
11
|
rb_raise(rb_eNoMemError, "not enough memory\n");
|
11
12
|
}
|
12
13
|
ca->objs = ca->obj_array;
|
@@ -18,9 +19,9 @@ CircArray oj_circ_array_new(void) {
|
|
18
19
|
|
19
20
|
void oj_circ_array_free(CircArray ca) {
|
20
21
|
if (ca->objs != ca->obj_array) {
|
21
|
-
|
22
|
+
OJ_R_FREE(ca->objs);
|
22
23
|
}
|
23
|
-
|
24
|
+
OJ_R_FREE(ca);
|
24
25
|
}
|
25
26
|
|
26
27
|
void oj_circ_array_set(CircArray ca, VALUE obj, unsigned long id) {
|
@@ -31,12 +32,12 @@ void oj_circ_array_set(CircArray ca, VALUE obj, unsigned long id) {
|
|
31
32
|
unsigned long cnt = id + 512;
|
32
33
|
|
33
34
|
if (ca->objs == ca->obj_array) {
|
34
|
-
if (0 == (ca->objs =
|
35
|
+
if (0 == (ca->objs = OJ_R_ALLOC_N(VALUE, cnt))) {
|
35
36
|
rb_raise(rb_eNoMemError, "not enough memory\n");
|
36
37
|
}
|
37
38
|
memcpy(ca->objs, ca->obj_array, sizeof(VALUE) * ca->cnt);
|
38
39
|
} else {
|
39
|
-
|
40
|
+
OJ_R_REALLOC_N(ca->objs, VALUE, cnt);
|
40
41
|
}
|
41
42
|
ca->size = cnt;
|
42
43
|
}
|
data/ext/oj/compat.c
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
#include <stdio.h>
|
5
5
|
|
6
|
+
#include "mem.h"
|
6
7
|
#include "encode.h"
|
7
8
|
#include "err.h"
|
8
9
|
#include "intern.h"
|
@@ -54,9 +55,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
|
|
54
55
|
} else {
|
55
56
|
rb_hash_aset(parent->val, rkey, rstr);
|
56
57
|
}
|
57
|
-
|
58
|
-
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
|
59
|
-
}
|
58
|
+
TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rstr);
|
60
59
|
}
|
61
60
|
}
|
62
61
|
|
@@ -68,9 +67,7 @@ static VALUE start_hash(ParseInfo pi) {
|
|
68
67
|
} else {
|
69
68
|
h = rb_hash_new();
|
70
69
|
}
|
71
|
-
|
72
|
-
oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
|
73
|
-
}
|
70
|
+
TRACE_PARSE_IN(pi->options.trace, "start_hash", pi);
|
74
71
|
return h;
|
75
72
|
}
|
76
73
|
|
@@ -89,13 +86,11 @@ static void end_hash(struct _parseInfo *pi) {
|
|
89
86
|
}
|
90
87
|
}
|
91
88
|
if (0 != parent->classname) {
|
92
|
-
|
89
|
+
OJ_R_FREE((char *)parent->classname);
|
93
90
|
parent->classname = 0;
|
94
91
|
}
|
95
92
|
}
|
96
|
-
|
97
|
-
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
98
|
-
}
|
93
|
+
TRACE_PARSE_HASH_END(pi->options.trace, pi);
|
99
94
|
}
|
100
95
|
|
101
96
|
static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
@@ -110,16 +105,12 @@ static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig
|
|
110
105
|
}
|
111
106
|
}
|
112
107
|
pi->stack.head->val = rstr;
|
113
|
-
|
114
|
-
oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
|
115
|
-
}
|
108
|
+
TRACE_PARSE_CALL(pi->options.trace, "add_string", pi, rstr);
|
116
109
|
}
|
117
110
|
|
118
111
|
static void add_num(ParseInfo pi, NumInfo ni) {
|
119
112
|
pi->stack.head->val = oj_num_as_value(ni);
|
120
|
-
|
121
|
-
oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
|
122
|
-
}
|
113
|
+
TRACE_PARSE_CALL(pi->options.trace, "add_number", pi, pi->stack.head->val);
|
123
114
|
}
|
124
115
|
|
125
116
|
static void hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) {
|
@@ -138,9 +129,7 @@ static void hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) {
|
|
138
129
|
} else {
|
139
130
|
rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), rval);
|
140
131
|
}
|
141
|
-
|
142
|
-
oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
|
143
|
-
}
|
132
|
+
TRACE_PARSE_CALL(pi->options.trace, "set_number", pi, rval);
|
144
133
|
}
|
145
134
|
|
146
135
|
static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
|
@@ -157,18 +146,14 @@ static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
|
|
157
146
|
} else {
|
158
147
|
rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), value);
|
159
148
|
}
|
160
|
-
|
161
|
-
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
|
162
|
-
}
|
149
|
+
TRACE_PARSE_CALL(pi->options.trace, "set_value", pi, value);
|
163
150
|
}
|
164
151
|
|
165
152
|
static VALUE start_array(ParseInfo pi) {
|
166
153
|
if (Qnil != pi->options.array_class) {
|
167
154
|
return rb_class_new_instance(0, NULL, pi->options.array_class);
|
168
155
|
}
|
169
|
-
|
170
|
-
oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
|
171
|
-
}
|
156
|
+
TRACE_PARSE_IN(pi->options.trace, "start_array", pi);
|
172
157
|
return rb_ary_new();
|
173
158
|
}
|
174
159
|
|
@@ -184,9 +169,7 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
|
|
184
169
|
} else {
|
185
170
|
rb_ary_push(parent->val, rval);
|
186
171
|
}
|
187
|
-
|
188
|
-
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
189
|
-
}
|
172
|
+
TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, rval);
|
190
173
|
}
|
191
174
|
|
192
175
|
static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
@@ -201,9 +184,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
|
|
201
184
|
}
|
202
185
|
}
|
203
186
|
rb_ary_push(stack_peek(&pi->stack)->val, rstr);
|
204
|
-
|
205
|
-
oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
|
206
|
-
}
|
187
|
+
TRACE_PARSE_CALL(pi->options.trace, "append_string", pi, rstr);
|
207
188
|
}
|
208
189
|
|
209
190
|
void oj_set_compat_callbacks(ParseInfo pi) {
|
data/ext/oj/custom.c
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
#include <stdint.h>
|
5
5
|
#include <stdio.h>
|
6
6
|
|
7
|
+
#include "mem.h"
|
7
8
|
#include "code.h"
|
8
9
|
#include "dump.h"
|
9
10
|
#include "encode.h"
|
@@ -24,20 +25,20 @@ static void dump_obj_str(VALUE obj, int depth, Out out) {
|
|
24
25
|
{"s", 1, Qnil},
|
25
26
|
{NULL, 0, Qnil},
|
26
27
|
};
|
27
|
-
attrs->value =
|
28
|
+
attrs->value = oj_safe_string_convert(obj);
|
28
29
|
|
29
30
|
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
30
31
|
}
|
31
32
|
|
32
33
|
static void dump_obj_as_str(VALUE obj, int depth, Out out) {
|
33
|
-
volatile VALUE rstr =
|
34
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
34
35
|
const char *str = RSTRING_PTR(rstr);
|
35
36
|
|
36
37
|
oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
|
37
38
|
}
|
38
39
|
|
39
40
|
static void bigdecimal_dump(VALUE obj, int depth, Out out) {
|
40
|
-
volatile VALUE rstr =
|
41
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
41
42
|
const char *str = RSTRING_PTR(rstr);
|
42
43
|
int len = (int)RSTRING_LEN(rstr);
|
43
44
|
|
@@ -305,7 +306,7 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
305
306
|
switch (rb_type(key)) {
|
306
307
|
case T_STRING: oj_dump_str(key, 0, out, false); break;
|
307
308
|
case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
|
308
|
-
default: oj_dump_str(
|
309
|
+
default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
|
309
310
|
}
|
310
311
|
if (!out->opts->dump_opts.use) {
|
311
312
|
*out->cur++ = ':';
|
@@ -437,7 +438,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
437
438
|
ID i;
|
438
439
|
|
439
440
|
if (sizeof(nbuf) <= nlen) {
|
440
|
-
if (NULL == (n2 =
|
441
|
+
if (NULL == (n2 = OJ_STRDUP(name))) {
|
441
442
|
rb_raise(rb_eNoMemError, "for attribute name.");
|
442
443
|
}
|
443
444
|
} else {
|
@@ -454,7 +455,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
454
455
|
i = rb_intern(n);
|
455
456
|
v = rb_funcall(v, i, 0);
|
456
457
|
if (nbuf != n2) {
|
457
|
-
|
458
|
+
OJ_FREE(n2);
|
458
459
|
}
|
459
460
|
}
|
460
461
|
fill_indent(out, d2);
|
@@ -479,17 +480,13 @@ static VALUE dump_common(VALUE obj, int depth, Out out) {
|
|
479
480
|
const char *s;
|
480
481
|
int len;
|
481
482
|
|
482
|
-
|
483
|
-
oj_trace("to_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
|
484
|
-
}
|
483
|
+
TRACE(out->opts->trace, "to_json", obj, depth + 1, TraceRubyIn);
|
485
484
|
if (0 == rb_obj_method_arity(obj, oj_to_json_id)) {
|
486
485
|
rs = rb_funcall(obj, oj_to_json_id, 0);
|
487
486
|
} else {
|
488
487
|
rs = rb_funcall2(obj, oj_to_json_id, out->argc, out->argv);
|
489
488
|
}
|
490
|
-
|
491
|
-
oj_trace("to_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
|
492
|
-
}
|
489
|
+
TRACE(out->opts->trace, "to_json", obj, depth + 1, TraceRubyOut);
|
493
490
|
s = RSTRING_PTR(rs);
|
494
491
|
len = (int)RSTRING_LEN(rs);
|
495
492
|
|
@@ -499,9 +496,7 @@ static VALUE dump_common(VALUE obj, int depth, Out out) {
|
|
499
496
|
} else if (Yes == out->opts->as_json && rb_respond_to(obj, oj_as_json_id)) {
|
500
497
|
volatile VALUE aj;
|
501
498
|
|
502
|
-
|
503
|
-
oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
|
504
|
-
}
|
499
|
+
TRACE(out->opts->trace, "as_json", obj, depth + 1, TraceRubyIn);
|
505
500
|
// Some classes elect to not take an options argument so check the arity
|
506
501
|
// of as_json.
|
507
502
|
if (0 == rb_obj_method_arity(obj, oj_as_json_id)) {
|
@@ -509,12 +504,10 @@ static VALUE dump_common(VALUE obj, int depth, Out out) {
|
|
509
504
|
} else {
|
510
505
|
aj = rb_funcall2(obj, oj_as_json_id, out->argc, out->argv);
|
511
506
|
}
|
512
|
-
|
513
|
-
oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
|
514
|
-
}
|
507
|
+
TRACE(out->opts->trace, "as_json", obj, depth + 1, TraceRubyOut);
|
515
508
|
// Catch the obvious brain damaged recursive dumping.
|
516
509
|
if (aj == obj) {
|
517
|
-
volatile VALUE rstr =
|
510
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
518
511
|
|
519
512
|
oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), false, false, out);
|
520
513
|
} else {
|
@@ -876,9 +869,7 @@ static DumpFunc custom_funcs[] = {
|
|
876
869
|
void oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok) {
|
877
870
|
int type = rb_type(obj);
|
878
871
|
|
879
|
-
|
880
|
-
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
881
|
-
}
|
872
|
+
TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
|
882
873
|
if (MAX_DEPTH < depth) {
|
883
874
|
rb_raise(rb_eNoMemError, "Too deeply nested.\n");
|
884
875
|
}
|
@@ -887,16 +878,12 @@ void oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok) {
|
|
887
878
|
|
888
879
|
if (NULL != f) {
|
889
880
|
f(obj, depth, out, true);
|
890
|
-
|
891
|
-
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
|
892
|
-
}
|
881
|
+
TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
|
893
882
|
return;
|
894
883
|
}
|
895
884
|
}
|
896
885
|
oj_dump_nil(Qnil, depth, out, false);
|
897
|
-
|
898
|
-
oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
|
899
|
-
}
|
886
|
+
TRACE(out->opts->trace, "dump", Qnil, depth, TraceOut);
|
900
887
|
}
|
901
888
|
|
902
889
|
///// load functions /////
|
@@ -969,9 +956,7 @@ static void end_hash(struct _parseInfo *pi) {
|
|
969
956
|
}
|
970
957
|
parent->clas = Qundef;
|
971
958
|
}
|
972
|
-
|
973
|
-
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
974
|
-
}
|
959
|
+
TRACE_PARSE_HASH_END(pi->options.trace, pi);
|
975
960
|
}
|
976
961
|
|
977
962
|
static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
|
data/ext/oj/dump.c
CHANGED
@@ -14,6 +14,7 @@
|
|
14
14
|
#include <poll.h>
|
15
15
|
#endif
|
16
16
|
|
17
|
+
#include "mem.h"
|
17
18
|
#include "cache8.h"
|
18
19
|
#include "odd.h"
|
19
20
|
#include "oj.h"
|
@@ -463,7 +464,7 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
|
|
463
464
|
}
|
464
465
|
|
465
466
|
void oj_dump_ruby_time(VALUE obj, Out out) {
|
466
|
-
volatile VALUE rstr =
|
467
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
467
468
|
|
468
469
|
oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
|
469
470
|
}
|
@@ -736,13 +737,9 @@ void oj_dump_raw_json(VALUE obj, int depth, Out out) {
|
|
736
737
|
} else {
|
737
738
|
volatile VALUE jv;
|
738
739
|
|
739
|
-
|
740
|
-
oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
|
741
|
-
}
|
740
|
+
TRACE(out->opts->trace, "raw_json", obj, depth + 1, TraceRubyIn);
|
742
741
|
jv = rb_funcall(obj, oj_raw_json_id, 2, RB_INT2NUM(depth), RB_INT2NUM(out->indent));
|
743
|
-
|
744
|
-
oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
|
745
|
-
}
|
742
|
+
TRACE(out->opts->trace, "raw_json", obj, depth + 1, TraceRubyOut);
|
746
743
|
oj_dump_raw(RSTRING_PTR(jv), (size_t)RSTRING_LEN(jv), out);
|
747
744
|
}
|
748
745
|
}
|
@@ -932,7 +929,7 @@ void oj_dump_class(VALUE obj, int depth, Out out, bool as_ok) {
|
|
932
929
|
}
|
933
930
|
|
934
931
|
void oj_dump_obj_to_s(VALUE obj, Out out) {
|
935
|
-
volatile VALUE rstr =
|
932
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
936
933
|
|
937
934
|
oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
|
938
935
|
}
|
@@ -952,7 +949,7 @@ void oj_out_init(Out out) {
|
|
952
949
|
|
953
950
|
void oj_out_free(Out out) {
|
954
951
|
if (out->allocated) {
|
955
|
-
|
952
|
+
OJ_R_FREE(out->buf); // TBD
|
956
953
|
}
|
957
954
|
}
|
958
955
|
|
@@ -966,9 +963,9 @@ void oj_grow_out(Out out, size_t len) {
|
|
966
963
|
size += len;
|
967
964
|
}
|
968
965
|
if (out->allocated) {
|
969
|
-
|
966
|
+
OJ_R_REALLOC_N(buf, char, (size + BUFFER_EXTRA));
|
970
967
|
} else {
|
971
|
-
buf =
|
968
|
+
buf = OJ_R_ALLOC_N(char, (size + BUFFER_EXTRA));
|
972
969
|
out->allocated = true;
|
973
970
|
memcpy(buf, out->buf, out->end - out->buf + BUFFER_EXTRA);
|
974
971
|
}
|
@@ -1173,7 +1170,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1173
1170
|
} else if (d == (double)(long long int)d) {
|
1174
1171
|
cnt = snprintf(buf, sizeof(buf), "%.1f", d);
|
1175
1172
|
} else if (0 == out->opts->float_prec) {
|
1176
|
-
volatile VALUE rstr =
|
1173
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
1177
1174
|
|
1178
1175
|
cnt = (int)RSTRING_LEN(rstr);
|
1179
1176
|
if ((int)sizeof(buf) <= cnt) {
|
@@ -1195,7 +1192,7 @@ int oj_dump_float_printf(char *buf, size_t blen, VALUE obj, double d, const char
|
|
1195
1192
|
// Round off issues at 16 significant digits so check for obvious ones of
|
1196
1193
|
// 0001 and 9999.
|
1197
1194
|
if (17 <= cnt && (0 == strcmp("0001", buf + cnt - 4) || 0 == strcmp("9999", buf + cnt - 4))) {
|
1198
|
-
volatile VALUE rstr =
|
1195
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
1199
1196
|
|
1200
1197
|
strcpy(buf, RSTRING_PTR(rstr));
|
1201
1198
|
cnt = (int)RSTRING_LEN(rstr);
|
data/ext/oj/dump_compat.c
CHANGED
@@ -109,17 +109,13 @@ dump_to_json(VALUE obj, Out out) {
|
|
109
109
|
const char *s;
|
110
110
|
int len;
|
111
111
|
|
112
|
-
|
113
|
-
oj_trace("to_json", obj, __FILE__, __LINE__, 0, TraceRubyIn);
|
114
|
-
}
|
112
|
+
TRACE(out->opts->trace, "to_json", obj, 0, TraceRubyIn);
|
115
113
|
if (0 == rb_obj_method_arity(obj, oj_to_json_id)) {
|
116
114
|
rs = rb_funcall(obj, oj_to_json_id, 0);
|
117
115
|
} else {
|
118
116
|
rs = rb_funcall2(obj, oj_to_json_id, out->argc, out->argv);
|
119
117
|
}
|
120
|
-
|
121
|
-
oj_trace("to_json", obj, __FILE__, __LINE__, 0, TraceRubyOut);
|
122
|
-
}
|
118
|
+
TRACE(out->opts->trace, "to_json", obj, 0, TraceRubyOut);
|
123
119
|
|
124
120
|
s = RSTRING_PTR(rs);
|
125
121
|
len = (int)RSTRING_LEN(rs);
|
@@ -299,7 +295,7 @@ datetime_alt(VALUE obj, int depth, Out out) {
|
|
299
295
|
attrs[3].value = rb_funcall(obj, hour_id, 0);
|
300
296
|
attrs[4].value = rb_funcall(obj, min_id, 0);
|
301
297
|
attrs[5].value = rb_funcall(obj, sec_id, 0);
|
302
|
-
attrs[6].value =
|
298
|
+
attrs[6].value = oj_safe_string_convert(rb_funcall(obj, offset_id, 0));
|
303
299
|
attrs[7].value = rb_funcall(obj, start_id, 0);
|
304
300
|
|
305
301
|
oj_code_attrs(obj, attrs, depth, out, true);
|
@@ -606,7 +602,7 @@ dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
606
602
|
} else if (oj_rails_float_opt) {
|
607
603
|
cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, "%0.16g");
|
608
604
|
} else {
|
609
|
-
volatile VALUE rstr =
|
605
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
610
606
|
|
611
607
|
strcpy(buf, RSTRING_PTR(rstr));
|
612
608
|
cnt = (int)RSTRING_LEN(rstr);
|
@@ -648,7 +644,7 @@ hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
648
644
|
break;
|
649
645
|
default:
|
650
646
|
/*rb_raise(rb_eTypeError, "In :compat mode all Hash keys must be Strings or Symbols, not %s.\n", rb_class2name(rb_obj_class(key)));*/
|
651
|
-
oj_dump_str(
|
647
|
+
oj_dump_str(oj_safe_string_convert(key), 0, out, false);
|
652
648
|
break;
|
653
649
|
}
|
654
650
|
if (!out->opts->dump_opts.use) {
|
@@ -833,7 +829,7 @@ dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
833
829
|
if (use_bignum_alt) {
|
834
830
|
rs = rb_big2str(obj, 10);
|
835
831
|
} else {
|
836
|
-
rs =
|
832
|
+
rs = oj_safe_string_convert(obj);
|
837
833
|
}
|
838
834
|
rb_check_type(rs, T_STRING);
|
839
835
|
cnt = (int)RSTRING_LEN(rs);
|
@@ -893,9 +889,7 @@ void
|
|
893
889
|
oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok) {
|
894
890
|
int type = rb_type(obj);
|
895
891
|
|
896
|
-
|
897
|
-
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
898
|
-
}
|
892
|
+
TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
|
899
893
|
if (out->opts->dump_opts.max_depth <= depth) {
|
900
894
|
// When JSON.dump is called then an ArgumentError is expected and the
|
901
895
|
// limit is the depth inclusive. If JSON.generate is called then a
|
@@ -918,14 +912,10 @@ oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok) {
|
|
918
912
|
|
919
913
|
if (NULL != f) {
|
920
914
|
f(obj, depth, out, as_ok);
|
921
|
-
|
922
|
-
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
|
923
|
-
}
|
915
|
+
TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
|
924
916
|
return;
|
925
917
|
}
|
926
918
|
}
|
927
919
|
oj_dump_nil(Qnil, depth, out, false);
|
928
|
-
|
929
|
-
oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
|
930
|
-
}
|
920
|
+
TRACE(out->opts->trace, "dump", Qnil, depth, TraceOut);
|
931
921
|
}
|