oj 3.13.11 → 3.15.0
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/CHANGELOG.md +74 -0
- data/README.md +4 -2
- data/ext/oj/buf.h +11 -6
- data/ext/oj/cache.c +25 -24
- data/ext/oj/cache8.c +10 -9
- data/ext/oj/circarray.c +8 -6
- data/ext/oj/circarray.h +2 -2
- data/ext/oj/code.c +17 -24
- data/ext/oj/code.h +2 -2
- data/ext/oj/compat.c +17 -44
- data/ext/oj/custom.c +70 -141
- data/ext/oj/debug.c +3 -9
- data/ext/oj/dump.c +128 -118
- data/ext/oj/dump.h +12 -8
- data/ext/oj/dump_compat.c +564 -641
- data/ext/oj/dump_leaf.c +17 -63
- data/ext/oj/dump_object.c +70 -199
- data/ext/oj/dump_strict.c +22 -46
- data/ext/oj/encoder.c +1 -1
- data/ext/oj/err.c +2 -13
- data/ext/oj/err.h +9 -12
- data/ext/oj/extconf.rb +14 -5
- data/ext/oj/fast.c +75 -103
- data/ext/oj/intern.c +52 -50
- data/ext/oj/intern.h +4 -8
- data/ext/oj/mem.c +318 -0
- data/ext/oj/mem.h +53 -0
- data/ext/oj/mimic_json.c +75 -47
- data/ext/oj/object.c +49 -66
- data/ext/oj/odd.c +89 -67
- data/ext/oj/odd.h +15 -15
- data/ext/oj/oj.c +140 -99
- data/ext/oj/oj.h +80 -51
- data/ext/oj/parse.c +162 -184
- data/ext/oj/parse.h +7 -10
- data/ext/oj/parser.c +89 -34
- data/ext/oj/parser.h +18 -7
- data/ext/oj/rails.c +82 -146
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +11 -12
- data/ext/oj/reader.h +4 -2
- data/ext/oj/resolve.c +3 -4
- data/ext/oj/rxclass.c +6 -5
- data/ext/oj/rxclass.h +1 -1
- data/ext/oj/saj.c +20 -31
- data/ext/oj/saj2.c +329 -93
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/scp.c +3 -14
- data/ext/oj/sparse.c +26 -70
- data/ext/oj/stream_writer.c +12 -22
- data/ext/oj/strict.c +20 -52
- data/ext/oj/string_writer.c +21 -21
- data/ext/oj/trace.h +31 -4
- data/ext/oj/usual.c +105 -150
- data/ext/oj/usual.h +68 -0
- data/ext/oj/util.h +1 -1
- data/ext/oj/val_stack.c +1 -1
- data/ext/oj/val_stack.h +8 -7
- data/ext/oj/validate.c +21 -26
- data/ext/oj/wab.c +31 -68
- data/lib/oj/active_support_helper.rb +0 -1
- data/lib/oj/bag.rb +7 -1
- data/lib/oj/easy_hash.rb +4 -5
- data/lib/oj/error.rb +0 -1
- data/lib/oj/json.rb +4 -2
- data/lib/oj/mimic.rb +4 -2
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/state.rb +9 -6
- data/lib/oj/version.rb +1 -2
- data/lib/oj.rb +2 -0
- data/pages/Compatibility.md +1 -1
- data/pages/InstallOptions.md +20 -0
- data/pages/Options.md +10 -0
- data/test/_test_active.rb +8 -9
- data/test/_test_active_mimic.rb +7 -8
- data/test/_test_mimic_rails.rb +17 -20
- data/test/activerecord/result_test.rb +5 -6
- data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
- data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
- data/test/{activesupport5 → activesupport7}/encoding_test.rb +20 -34
- data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
- data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
- data/test/files.rb +15 -15
- data/test/foo.rb +9 -71
- data/test/helper.rb +11 -8
- data/test/isolated/shared.rb +3 -2
- data/test/json_gem/json_addition_test.rb +2 -2
- data/test/json_gem/json_common_interface_test.rb +4 -4
- data/test/json_gem/json_encoding_test.rb +0 -0
- data/test/json_gem/json_ext_parser_test.rb +1 -0
- data/test/json_gem/json_fixtures_test.rb +3 -2
- data/test/json_gem/json_generator_test.rb +48 -36
- data/test/json_gem/json_generic_object_test.rb +11 -11
- data/test/json_gem/json_parser_test.rb +54 -47
- data/test/json_gem/json_string_matching_test.rb +9 -9
- data/test/json_gem/test_helper.rb +7 -3
- data/test/mem.rb +13 -12
- data/test/perf.rb +21 -26
- data/test/perf_compat.rb +31 -33
- data/test/perf_dump.rb +50 -0
- data/test/perf_fast.rb +80 -82
- data/test/perf_file.rb +27 -29
- data/test/perf_object.rb +65 -69
- data/test/perf_once.rb +12 -11
- data/test/perf_parser.rb +42 -48
- data/test/perf_saj.rb +46 -54
- data/test/perf_scp.rb +57 -69
- data/test/perf_simple.rb +41 -39
- data/test/perf_strict.rb +68 -70
- data/test/perf_wab.rb +67 -69
- data/test/prec.rb +3 -3
- data/test/sample/change.rb +0 -1
- data/test/sample/dir.rb +0 -1
- data/test/sample/doc.rb +0 -1
- data/test/sample/file.rb +0 -1
- data/test/sample/group.rb +0 -1
- data/test/sample/hasprops.rb +0 -1
- data/test/sample/layer.rb +0 -1
- data/test/sample/rect.rb +0 -1
- data/test/sample/shape.rb +0 -1
- data/test/sample/text.rb +0 -1
- data/test/sample.rb +16 -16
- data/test/sample_json.rb +8 -8
- data/test/test_compat.rb +76 -42
- data/test/test_custom.rb +72 -51
- data/test/test_debian.rb +7 -10
- data/test/test_fast.rb +86 -90
- data/test/test_file.rb +41 -30
- data/test/test_gc.rb +16 -5
- data/test/test_generate.rb +5 -5
- data/test/test_hash.rb +4 -4
- data/test/test_integer_range.rb +9 -9
- data/test/test_null.rb +20 -20
- data/test/test_object.rb +85 -96
- data/test/test_parser.rb +6 -22
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +115 -23
- data/test/test_parser_usual.rb +6 -6
- data/test/test_rails.rb +2 -2
- data/test/test_saj.rb +10 -8
- data/test/test_scp.rb +37 -39
- data/test/test_strict.rb +30 -32
- data/test/test_various.rb +147 -99
- data/test/test_wab.rb +48 -44
- data/test/test_writer.rb +47 -47
- data/test/tests.rb +13 -4
- data/test/tests_mimic.rb +12 -3
- data/test/tests_mimic_addition.rb +12 -3
- metadata +33 -144
- data/test/activesupport4/decoding_test.rb +0 -108
- data/test/activesupport4/encoding_test.rb +0 -531
- data/test/activesupport4/test_helper.rb +0 -41
- data/test/activesupport5/test_helper.rb +0 -72
- data/test/bar.rb +0 -16
- data/test/baz.rb +0 -16
- data/test/bug.rb +0 -16
- data/test/zoo.rb +0 -13
data/ext/oj/mem.c
ADDED
@@ -0,0 +1,318 @@
|
|
1
|
+
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#include "mem.h"
|
4
|
+
|
5
|
+
#include <pthread.h>
|
6
|
+
#include <ruby.h>
|
7
|
+
#include <stdbool.h>
|
8
|
+
#include <stdint.h>
|
9
|
+
#include <stdio.h>
|
10
|
+
#include <stdlib.h>
|
11
|
+
#include <string.h>
|
12
|
+
|
13
|
+
typedef struct _rec {
|
14
|
+
struct _rec *next;
|
15
|
+
const void *ptr;
|
16
|
+
size_t size;
|
17
|
+
const char *file;
|
18
|
+
int line;
|
19
|
+
bool ruby;
|
20
|
+
} *Rec;
|
21
|
+
|
22
|
+
typedef struct _rep {
|
23
|
+
struct _rep *next;
|
24
|
+
size_t size;
|
25
|
+
const char *file;
|
26
|
+
int line;
|
27
|
+
int cnt;
|
28
|
+
} *Rep;
|
29
|
+
|
30
|
+
#ifdef MEM_DEBUG
|
31
|
+
|
32
|
+
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
33
|
+
static Rec recs = NULL;
|
34
|
+
static const char mem_pad[] = "--- This is a memory pad and should not change until being freed. ---";
|
35
|
+
|
36
|
+
void *oj_malloc(size_t size, const char *file, int line) {
|
37
|
+
void *ptr = malloc(size + sizeof(mem_pad));
|
38
|
+
|
39
|
+
if (NULL != ptr) {
|
40
|
+
Rec r = (Rec)malloc(sizeof(struct _rec));
|
41
|
+
|
42
|
+
if (NULL != r) {
|
43
|
+
strcpy(((char *)ptr) + size, mem_pad);
|
44
|
+
r->ptr = ptr;
|
45
|
+
r->size = size;
|
46
|
+
r->file = file;
|
47
|
+
r->line = line;
|
48
|
+
r->ruby = false;
|
49
|
+
pthread_mutex_lock(&lock);
|
50
|
+
r->next = recs;
|
51
|
+
recs = r;
|
52
|
+
pthread_mutex_unlock(&lock);
|
53
|
+
} else {
|
54
|
+
free(ptr);
|
55
|
+
ptr = NULL;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
return ptr;
|
59
|
+
}
|
60
|
+
|
61
|
+
void *oj_realloc(void *orig, size_t size, const char *file, int line) {
|
62
|
+
void *ptr = realloc(orig, size + sizeof(mem_pad));
|
63
|
+
Rec r;
|
64
|
+
|
65
|
+
if (NULL != ptr) {
|
66
|
+
strcpy(((char *)ptr) + size, mem_pad);
|
67
|
+
pthread_mutex_lock(&lock);
|
68
|
+
for (r = recs; NULL != r; r = r->next) {
|
69
|
+
if (orig == r->ptr) {
|
70
|
+
r->ptr = ptr;
|
71
|
+
r->size = size;
|
72
|
+
r->file = file;
|
73
|
+
r->line = line;
|
74
|
+
r->ruby = false;
|
75
|
+
break;
|
76
|
+
}
|
77
|
+
}
|
78
|
+
pthread_mutex_unlock(&lock);
|
79
|
+
if (NULL == r) {
|
80
|
+
printf("Realloc at %s:%d (%p) not allocated.\n", file, line, orig);
|
81
|
+
}
|
82
|
+
}
|
83
|
+
return ptr;
|
84
|
+
}
|
85
|
+
|
86
|
+
void *oj_calloc(size_t count, size_t size, const char *file, int line) {
|
87
|
+
void *ptr;
|
88
|
+
|
89
|
+
size *= count;
|
90
|
+
if (NULL != (ptr = malloc(size + sizeof(mem_pad)))) {
|
91
|
+
Rec r = (Rec)malloc(sizeof(struct _rec));
|
92
|
+
|
93
|
+
if (NULL != r) {
|
94
|
+
memset(ptr, 0, size);
|
95
|
+
strcpy(((char *)ptr) + size, mem_pad);
|
96
|
+
r->ptr = ptr;
|
97
|
+
r->size = size;
|
98
|
+
r->file = file;
|
99
|
+
r->line = line;
|
100
|
+
r->ruby = false;
|
101
|
+
pthread_mutex_lock(&lock);
|
102
|
+
r->next = recs;
|
103
|
+
recs = r;
|
104
|
+
pthread_mutex_unlock(&lock);
|
105
|
+
} else {
|
106
|
+
free(ptr);
|
107
|
+
ptr = NULL;
|
108
|
+
}
|
109
|
+
}
|
110
|
+
return ptr;
|
111
|
+
}
|
112
|
+
|
113
|
+
void *oj_r_alloc(size_t size, const char *file, int line) {
|
114
|
+
void *ptr = ruby_xmalloc(size + sizeof(mem_pad));
|
115
|
+
|
116
|
+
if (NULL != ptr) {
|
117
|
+
Rec r = (Rec)malloc(sizeof(struct _rec));
|
118
|
+
|
119
|
+
if (NULL != r) {
|
120
|
+
strcpy(((char *)ptr) + size, mem_pad);
|
121
|
+
r->ptr = ptr;
|
122
|
+
r->size = size;
|
123
|
+
r->file = file;
|
124
|
+
r->line = line;
|
125
|
+
r->ruby = true;
|
126
|
+
pthread_mutex_lock(&lock);
|
127
|
+
r->next = recs;
|
128
|
+
recs = r;
|
129
|
+
pthread_mutex_unlock(&lock);
|
130
|
+
} else {
|
131
|
+
free(ptr);
|
132
|
+
ptr = NULL;
|
133
|
+
}
|
134
|
+
}
|
135
|
+
return ptr;
|
136
|
+
}
|
137
|
+
|
138
|
+
void *oj_r_realloc(void *orig, size_t size, const char *file, int line) {
|
139
|
+
void *ptr = ruby_xrealloc2(orig, 1, size + sizeof(mem_pad));
|
140
|
+
Rec r;
|
141
|
+
|
142
|
+
if (NULL != ptr) {
|
143
|
+
strcpy(((char *)ptr) + size, mem_pad);
|
144
|
+
pthread_mutex_lock(&lock);
|
145
|
+
for (r = recs; NULL != r; r = r->next) {
|
146
|
+
if (orig == r->ptr) {
|
147
|
+
r->ptr = ptr;
|
148
|
+
r->size = size;
|
149
|
+
r->file = file;
|
150
|
+
r->line = line;
|
151
|
+
r->ruby = true;
|
152
|
+
break;
|
153
|
+
}
|
154
|
+
}
|
155
|
+
pthread_mutex_unlock(&lock);
|
156
|
+
if (NULL == r) {
|
157
|
+
printf("Realloc at %s:%d (%p) not allocated.\n", file, line, orig);
|
158
|
+
}
|
159
|
+
}
|
160
|
+
return ptr;
|
161
|
+
}
|
162
|
+
|
163
|
+
void oj_freed(void *ptr, const char *file, int line, bool ruby) {
|
164
|
+
if (NULL != ptr) {
|
165
|
+
Rec r = NULL;
|
166
|
+
Rec prev = NULL;
|
167
|
+
|
168
|
+
pthread_mutex_lock(&lock);
|
169
|
+
for (r = recs; NULL != r; r = r->next) {
|
170
|
+
if (ptr == r->ptr) {
|
171
|
+
if (NULL == prev) {
|
172
|
+
recs = r->next;
|
173
|
+
} else {
|
174
|
+
prev->next = r->next;
|
175
|
+
}
|
176
|
+
break;
|
177
|
+
}
|
178
|
+
prev = r;
|
179
|
+
}
|
180
|
+
pthread_mutex_unlock(&lock);
|
181
|
+
if (NULL == r) {
|
182
|
+
printf("Free at %s:%d (%p) not allocated or already freed.\n", file, line, ptr);
|
183
|
+
} else {
|
184
|
+
char *pad = (char *)r->ptr + r->size;
|
185
|
+
|
186
|
+
if (r->ruby != ruby) {
|
187
|
+
if (r->ruby) {
|
188
|
+
printf("Memory at %s:%d (%p) allocated with Ruby allocator and freed with stdlib free.\n",
|
189
|
+
file,
|
190
|
+
line,
|
191
|
+
ptr);
|
192
|
+
} else {
|
193
|
+
printf("Memory at %s:%d (%p) allocated with stdlib allocator and freed with Ruby free.\n",
|
194
|
+
file,
|
195
|
+
line,
|
196
|
+
ptr);
|
197
|
+
}
|
198
|
+
}
|
199
|
+
if (0 != strcmp(mem_pad, pad)) {
|
200
|
+
uint8_t *p;
|
201
|
+
uint8_t *end = (uint8_t *)pad + sizeof(mem_pad);
|
202
|
+
|
203
|
+
printf("Memory at %s:%d (%p) write outside allocated.\n", file, line, ptr);
|
204
|
+
for (p = (uint8_t *)pad; p < end; p++) {
|
205
|
+
if (0x20 < *p && *p < 0x7f) {
|
206
|
+
printf("%c ", *p);
|
207
|
+
} else {
|
208
|
+
printf("%02x ", *(uint8_t *)p);
|
209
|
+
}
|
210
|
+
}
|
211
|
+
printf("\n");
|
212
|
+
}
|
213
|
+
free(r);
|
214
|
+
}
|
215
|
+
}
|
216
|
+
}
|
217
|
+
|
218
|
+
void oj_r_free(void *ptr, const char *file, int line) {
|
219
|
+
oj_freed(ptr, file, line, true);
|
220
|
+
xfree(ptr);
|
221
|
+
}
|
222
|
+
|
223
|
+
void oj_free(void *ptr, const char *file, int line) {
|
224
|
+
oj_freed(ptr, file, line, false);
|
225
|
+
free(ptr);
|
226
|
+
}
|
227
|
+
|
228
|
+
char *oj_mem_strdup(const char *str, const char *file, int line) {
|
229
|
+
size_t size = strlen(str) + 1;
|
230
|
+
char *ptr = (char *)malloc(size + sizeof(mem_pad));
|
231
|
+
|
232
|
+
if (NULL != ptr) {
|
233
|
+
Rec r = (Rec)malloc(sizeof(struct _rec));
|
234
|
+
|
235
|
+
if (NULL != r) {
|
236
|
+
strcpy(ptr, str);
|
237
|
+
strcpy(((char *)ptr) + size, mem_pad);
|
238
|
+
r->ptr = (void *)ptr;
|
239
|
+
r->size = size;
|
240
|
+
r->file = file;
|
241
|
+
r->line = line;
|
242
|
+
r->ruby = false;
|
243
|
+
pthread_mutex_lock(&lock);
|
244
|
+
r->next = recs;
|
245
|
+
recs = r;
|
246
|
+
pthread_mutex_unlock(&lock);
|
247
|
+
} else {
|
248
|
+
free(ptr);
|
249
|
+
ptr = NULL;
|
250
|
+
}
|
251
|
+
}
|
252
|
+
return ptr;
|
253
|
+
}
|
254
|
+
|
255
|
+
#endif
|
256
|
+
|
257
|
+
#ifdef MEM_DEBUG
|
258
|
+
|
259
|
+
static Rep update_reps(Rep reps, Rec r) {
|
260
|
+
Rep rp = reps;
|
261
|
+
|
262
|
+
for (; NULL != rp; rp = rp->next) {
|
263
|
+
if (rp->line == r->line && (rp->file == r->file || 0 == strcmp(rp->file, r->file))) {
|
264
|
+
rp->size += r->size;
|
265
|
+
rp->cnt++;
|
266
|
+
break;
|
267
|
+
}
|
268
|
+
}
|
269
|
+
if (NULL == rp && NULL != (rp = (Rep)malloc(sizeof(struct _rep)))) {
|
270
|
+
rp->size = r->size;
|
271
|
+
rp->file = r->file;
|
272
|
+
rp->line = r->line;
|
273
|
+
rp->cnt = 1;
|
274
|
+
rp->next = reps;
|
275
|
+
reps = rp;
|
276
|
+
}
|
277
|
+
return reps;
|
278
|
+
}
|
279
|
+
|
280
|
+
static void print_stats() {
|
281
|
+
printf("\n--- Memory Usage Report --------------------------------------------------------\n");
|
282
|
+
pthread_mutex_lock(&lock);
|
283
|
+
|
284
|
+
if (NULL == recs) {
|
285
|
+
printf("No memory leaks\n");
|
286
|
+
} else {
|
287
|
+
Rep reps = NULL;
|
288
|
+
Rep rp;
|
289
|
+
Rec r;
|
290
|
+
size_t leaked = 0;
|
291
|
+
|
292
|
+
for (r = recs; NULL != r; r = r->next) {
|
293
|
+
reps = update_reps(reps, r);
|
294
|
+
}
|
295
|
+
while (NULL != (rp = reps)) {
|
296
|
+
reps = rp->next;
|
297
|
+
printf("%16s:%3d %8lu bytes over %d occurances allocated and not freed.\n",
|
298
|
+
rp->file,
|
299
|
+
rp->line,
|
300
|
+
rp->size,
|
301
|
+
rp->cnt);
|
302
|
+
leaked += rp->size;
|
303
|
+
free(rp);
|
304
|
+
}
|
305
|
+
printf("%lu bytes leaked\n", leaked);
|
306
|
+
}
|
307
|
+
pthread_mutex_unlock(&lock);
|
308
|
+
printf("--------------------------------------------------------------------------------\n");
|
309
|
+
}
|
310
|
+
|
311
|
+
#endif
|
312
|
+
|
313
|
+
void oj_mem_report(void) {
|
314
|
+
#ifdef MEM_DEBUG
|
315
|
+
rb_gc();
|
316
|
+
print_stats();
|
317
|
+
#endif
|
318
|
+
}
|
data/ext/oj/mem.h
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#ifndef OJ_MEM_H
|
4
|
+
#define OJ_MEM_H
|
5
|
+
|
6
|
+
#include <stdio.h>
|
7
|
+
#include <stdlib.h>
|
8
|
+
#include <string.h>
|
9
|
+
|
10
|
+
#ifdef MEM_DEBUG
|
11
|
+
|
12
|
+
#define OJ_MALLOC(size) oj_malloc(size, __FILE__, __LINE__)
|
13
|
+
#define OJ_REALLOC(ptr, size) oj_realloc(ptr, size, __FILE__, __LINE__)
|
14
|
+
#define OJ_CALLOC(count, size) oj_calloc(count, size, __FILE__, __LINE__)
|
15
|
+
#define OJ_FREE(ptr) oj_free(ptr, __FILE__, __LINE__)
|
16
|
+
|
17
|
+
#define OJ_R_ALLOC(type) oj_r_alloc(sizeof(type), __FILE__, __LINE__)
|
18
|
+
#define OJ_R_ALLOC_N(type, n) (type *)oj_r_alloc(sizeof(type) * (n), __FILE__, __LINE__)
|
19
|
+
#define OJ_R_REALLOC_N(ptr, type, n) ((ptr) = (type *)oj_r_realloc(ptr, (sizeof(type) * (n)), __FILE__, __LINE__))
|
20
|
+
#define OJ_R_FREE(ptr) oj_r_free(ptr, __FILE__, __LINE__)
|
21
|
+
|
22
|
+
#define OJ_STRDUP(str) oj_mem_strdup(str, __FILE__, __LINE__)
|
23
|
+
|
24
|
+
extern void *oj_malloc(size_t size, const char *file, int line);
|
25
|
+
extern void *oj_realloc(void *ptr, size_t size, const char *file, int line);
|
26
|
+
extern void *oj_calloc(size_t count, size_t size, const char *file, int line);
|
27
|
+
extern void oj_free(void *ptr, const char *file, int line);
|
28
|
+
|
29
|
+
extern void *oj_r_alloc(size_t size, const char *file, int line);
|
30
|
+
extern void *oj_r_realloc(void *ptr, size_t size, const char *file, int line);
|
31
|
+
extern void oj_r_free(void *ptr, const char *file, int line);
|
32
|
+
|
33
|
+
extern char *oj_mem_strdup(const char *str, const char *file, int line);
|
34
|
+
|
35
|
+
#else
|
36
|
+
|
37
|
+
#define OJ_MALLOC(size) malloc(size)
|
38
|
+
#define OJ_REALLOC(ptr, size) realloc(ptr, size)
|
39
|
+
#define OJ_CALLOC(count, size) calloc(count, size)
|
40
|
+
#define OJ_FREE(ptr) free(ptr)
|
41
|
+
|
42
|
+
#define OJ_R_ALLOC(type) RB_ALLOC(type)
|
43
|
+
#define OJ_R_ALLOC_N(type, n) RB_ALLOC_N(type, n)
|
44
|
+
#define OJ_R_REALLOC_N(ptr, type, n) RB_REALLOC_N(ptr, type, n)
|
45
|
+
#define OJ_R_FREE(ptr) xfree(ptr)
|
46
|
+
|
47
|
+
#define OJ_STRDUP(str) strdup(str)
|
48
|
+
|
49
|
+
#endif
|
50
|
+
|
51
|
+
extern void oj_mem_report();
|
52
|
+
|
53
|
+
#endif /* OJ_MEM_H */
|
data/ext/oj/mimic_json.c
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
#include "dump.h"
|
5
5
|
#include "encode.h"
|
6
|
+
#include "mem.h"
|
6
7
|
#include "oj.h"
|
7
8
|
#include "parse.h"
|
8
9
|
|
@@ -198,7 +199,6 @@ static int mimic_limit_arg(VALUE a) {
|
|
198
199
|
* Returns [_String_] a JSON string.
|
199
200
|
*/
|
200
201
|
static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
|
201
|
-
char buf[4096];
|
202
202
|
struct _out out;
|
203
203
|
struct _options copts = oj_default_options;
|
204
204
|
VALUE rstr;
|
@@ -206,9 +206,9 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
206
206
|
|
207
207
|
copts.str_rx.head = NULL;
|
208
208
|
copts.str_rx.tail = NULL;
|
209
|
-
|
210
|
-
out
|
211
|
-
|
209
|
+
|
210
|
+
oj_out_init(&out);
|
211
|
+
|
212
212
|
out.caller = CALLER_DUMP;
|
213
213
|
copts.escape_mode = JXEsc;
|
214
214
|
copts.mode = CompatMode;
|
@@ -257,9 +257,9 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
257
257
|
rb_funcall2(io, oj_write_id, 1, args);
|
258
258
|
rstr = io;
|
259
259
|
}
|
260
|
-
|
261
|
-
|
262
|
-
|
260
|
+
|
261
|
+
oj_out_free(&out);
|
262
|
+
|
263
263
|
return rstr;
|
264
264
|
}
|
265
265
|
|
@@ -349,26 +349,26 @@ static VALUE mimic_load(int argc, VALUE *argv, VALUE self) {
|
|
349
349
|
static VALUE mimic_dump_load(int argc, VALUE *argv, VALUE self) {
|
350
350
|
if (1 > argc) {
|
351
351
|
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
|
352
|
-
}
|
352
|
+
}
|
353
|
+
if (T_STRING == rb_type(*argv)) {
|
353
354
|
return mimic_load(argc, argv, self);
|
354
|
-
} else {
|
355
|
-
return mimic_dump(argc, argv, self);
|
356
355
|
}
|
357
|
-
return
|
356
|
+
return mimic_dump(argc, argv, self);
|
358
357
|
}
|
359
358
|
|
360
359
|
static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
361
|
-
char buf[4096];
|
362
360
|
struct _out out;
|
363
361
|
VALUE rstr;
|
364
362
|
|
365
|
-
|
363
|
+
if (0 == argc) {
|
364
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0))");
|
365
|
+
}
|
366
|
+
memset(out.stack_buffer, 0, sizeof(out.stack_buffer));
|
367
|
+
|
368
|
+
oj_out_init(&out);
|
366
369
|
|
367
|
-
out.
|
368
|
-
out.
|
369
|
-
out.allocated = false;
|
370
|
-
out.omit_nil = copts->dump_opts.omit_nil;
|
371
|
-
out.caller = CALLER_GENERATE;
|
370
|
+
out.omit_nil = copts->dump_opts.omit_nil;
|
371
|
+
out.caller = CALLER_GENERATE;
|
372
372
|
// For obj.to_json or generate nan is not allowed but if called from dump
|
373
373
|
// it is.
|
374
374
|
copts->dump_opts.nan_dump = RaiseNan;
|
@@ -388,6 +388,8 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
388
388
|
VALUE active_hack[1];
|
389
389
|
|
390
390
|
if (Qundef == state_class) {
|
391
|
+
rb_warn("Oj::Rails.mimic_JSON was called implicitly. "
|
392
|
+
"Call it explicitly beforehand if you want to remove this warning.");
|
391
393
|
oj_define_mimic_json(0, NULL, Qnil);
|
392
394
|
}
|
393
395
|
active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
|
@@ -398,9 +400,9 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
398
400
|
}
|
399
401
|
rstr = rb_str_new2(out.buf);
|
400
402
|
rstr = oj_encode(rstr);
|
401
|
-
|
402
|
-
|
403
|
-
|
403
|
+
|
404
|
+
oj_out_free(&out);
|
405
|
+
|
404
406
|
return rstr;
|
405
407
|
}
|
406
408
|
|
@@ -457,7 +459,10 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
457
459
|
// a Hash. I haven't dug deep enough to find out why but using a State
|
458
460
|
// instance and not a Hash gives the desired behavior.
|
459
461
|
*rargs = *argv;
|
460
|
-
if (
|
462
|
+
if (0 == argc) {
|
463
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0))");
|
464
|
+
}
|
465
|
+
if (1 == argc || Qnil == argv[1]) {
|
461
466
|
h = rb_hash_new();
|
462
467
|
} else {
|
463
468
|
h = argv[1];
|
@@ -478,6 +483,8 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
478
483
|
rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
|
479
484
|
}
|
480
485
|
if (Qundef == state_class) {
|
486
|
+
rb_warn("Oj::Rails.mimic_JSON was called implicitly. "
|
487
|
+
"Call it explicitly beforehand if you want to remove this warning.");
|
481
488
|
oj_define_mimic_json(0, NULL, Qnil);
|
482
489
|
}
|
483
490
|
rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
|
@@ -533,14 +540,6 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE info) {
|
|
533
540
|
}
|
534
541
|
} else if (oj_decimal_class_sym == k) {
|
535
542
|
pi->options.compat_bigdec = (oj_bigdecimal_class == v);
|
536
|
-
} else if (oj_max_nesting_sym == k) {
|
537
|
-
if (Qtrue == v) {
|
538
|
-
pi->max_depth = 100;
|
539
|
-
} else if (Qfalse == v || Qnil == v) {
|
540
|
-
pi->max_depth = 0;
|
541
|
-
} else if (T_FIXNUM == rb_type(v)) {
|
542
|
-
pi->max_depth = NUM2INT(v);
|
543
|
-
}
|
544
543
|
}
|
545
544
|
return ST_CONTINUE;
|
546
545
|
}
|
@@ -570,11 +569,21 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
570
569
|
pi.max_depth = 100;
|
571
570
|
|
572
571
|
if (Qnil != ropts) {
|
572
|
+
VALUE v;
|
573
|
+
|
573
574
|
if (T_HASH != rb_type(ropts)) {
|
574
575
|
rb_raise(rb_eArgError, "options must be a hash.");
|
575
576
|
}
|
576
577
|
|
577
578
|
rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
|
579
|
+
v = rb_hash_lookup(ropts, oj_max_nesting_sym);
|
580
|
+
if (Qtrue == v) {
|
581
|
+
pi.max_depth = 100;
|
582
|
+
} else if (Qfalse == v || Qnil == v) {
|
583
|
+
pi.max_depth = 0;
|
584
|
+
} else if (T_FIXNUM == rb_type(v)) {
|
585
|
+
pi.max_depth = NUM2INT(v);
|
586
|
+
}
|
578
587
|
oj_parse_opt_match_string(&pi.options.str_rx, ropts);
|
579
588
|
if (Yes == pi.options.create_ok && Yes == pi.options.sym_key) {
|
580
589
|
rb_raise(rb_eArgError, ":symbolize_names and :create_additions can not both be true.");
|
@@ -644,23 +653,22 @@ static VALUE mimic_recurse_proc(VALUE self, VALUE obj) {
|
|
644
653
|
*
|
645
654
|
* - *id* [_nil_|String] new create_id
|
646
655
|
*
|
647
|
-
* Returns [_String_] the id.
|
656
|
+
* Returns [_nil_|_String_] the id.
|
648
657
|
*/
|
649
658
|
static VALUE mimic_set_create_id(VALUE self, VALUE id) {
|
650
|
-
Check_Type(id, T_STRING);
|
651
|
-
|
652
659
|
if (NULL != oj_default_options.create_id) {
|
653
660
|
if (oj_json_class != oj_default_options.create_id) {
|
654
|
-
|
661
|
+
OJ_R_FREE((char *)oj_default_options.create_id);
|
655
662
|
}
|
656
663
|
oj_default_options.create_id = NULL;
|
657
664
|
oj_default_options.create_id_len = 0;
|
658
665
|
}
|
659
666
|
if (Qnil != id) {
|
660
|
-
|
667
|
+
const char *ptr = StringValueCStr(id);
|
668
|
+
size_t len = RSTRING_LEN(id) + 1;
|
661
669
|
|
662
|
-
oj_default_options.create_id =
|
663
|
-
strcpy((char *)oj_default_options.create_id,
|
670
|
+
oj_default_options.create_id = OJ_R_ALLOC_N(char, len);
|
671
|
+
strcpy((char *)oj_default_options.create_id, ptr);
|
664
672
|
oj_default_options.create_id_len = len - 1;
|
665
673
|
}
|
666
674
|
return id;
|
@@ -730,6 +738,7 @@ static struct _options mimic_object_to_json_options = {0, // indent
|
|
730
738
|
0, // array_size
|
731
739
|
RaiseNan, // nan_dump
|
732
740
|
false, // omit_nil
|
741
|
+
false, // omit_null_byte
|
733
742
|
100, // max_depth
|
734
743
|
},
|
735
744
|
{
|
@@ -740,19 +749,18 @@ static struct _options mimic_object_to_json_options = {0, // indent
|
|
740
749
|
}};
|
741
750
|
|
742
751
|
static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
|
743
|
-
char buf[4096];
|
744
752
|
struct _out out;
|
745
753
|
VALUE rstr;
|
746
754
|
struct _options copts = oj_default_options;
|
747
755
|
|
748
756
|
copts.str_rx.head = NULL;
|
749
757
|
copts.str_rx.tail = NULL;
|
750
|
-
|
751
|
-
out
|
752
|
-
|
753
|
-
out.omit_nil
|
754
|
-
copts.mode
|
755
|
-
copts.to_json
|
758
|
+
|
759
|
+
oj_out_init(&out);
|
760
|
+
|
761
|
+
out.omit_nil = copts.dump_opts.omit_nil;
|
762
|
+
copts.mode = CompatMode;
|
763
|
+
copts.to_json = No;
|
756
764
|
if (1 <= argc && Qnil != argv[0]) {
|
757
765
|
oj_parse_mimic_dump_options(argv[0], &copts);
|
758
766
|
}
|
@@ -765,9 +773,9 @@ static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
|
|
765
773
|
}
|
766
774
|
rstr = rb_str_new2(out.buf);
|
767
775
|
rstr = oj_encode(rstr);
|
768
|
-
|
769
|
-
|
770
|
-
|
776
|
+
|
777
|
+
oj_out_free(&out);
|
778
|
+
|
771
779
|
return rstr;
|
772
780
|
}
|
773
781
|
|
@@ -784,28 +792,48 @@ void oj_mimic_json_methods(VALUE json) {
|
|
784
792
|
VALUE json_error;
|
785
793
|
VALUE generator;
|
786
794
|
VALUE ext;
|
795
|
+
VALUE verbose;
|
787
796
|
|
797
|
+
// rb_undef_method doesn't work for modules or maybe sometimes
|
798
|
+
// doesn't. Anyway setting verbose should hide the warning.
|
799
|
+
verbose = rb_gv_get("$VERBOSE");
|
800
|
+
rb_gv_set("$VERBOSE", Qfalse);
|
801
|
+
|
802
|
+
rb_undef_method(json, "create_id=");
|
788
803
|
rb_define_module_function(json, "create_id=", mimic_set_create_id, 1);
|
804
|
+
rb_undef_method(json, "create_id");
|
789
805
|
rb_define_module_function(json, "create_id", mimic_create_id, 0);
|
790
806
|
|
807
|
+
rb_undef_method(json, "dump");
|
791
808
|
rb_define_module_function(json, "dump", mimic_dump, -1);
|
809
|
+
rb_undef_method(json, "load");
|
792
810
|
rb_define_module_function(json, "load", mimic_load, -1);
|
793
811
|
rb_define_module_function(json, "restore", mimic_load, -1);
|
812
|
+
rb_undef_method(json, "recurse_proc");
|
794
813
|
rb_define_module_function(json, "recurse_proc", mimic_recurse_proc, 1);
|
814
|
+
rb_undef_method(json, "[]");
|
795
815
|
rb_define_module_function(json, "[]", mimic_dump_load, -1);
|
796
816
|
|
817
|
+
rb_undef_method(json, "generate");
|
797
818
|
rb_define_module_function(json, "generate", oj_mimic_generate, -1);
|
819
|
+
rb_undef_method(json, "fast_generate");
|
798
820
|
rb_define_module_function(json, "fast_generate", oj_mimic_generate, -1);
|
821
|
+
rb_undef_method(json, "pretty_generate");
|
799
822
|
rb_define_module_function(json, "pretty_generate", oj_mimic_pretty_generate, -1);
|
800
823
|
// For older versions of JSON, the deprecated unparse methods.
|
824
|
+
rb_undef_method(json, "unparse");
|
801
825
|
rb_define_module_function(json, "unparse", oj_mimic_generate, -1);
|
802
826
|
rb_define_module_function(json, "fast_unparse", oj_mimic_generate, -1);
|
803
827
|
rb_define_module_function(json, "pretty_unparse", oj_mimic_pretty_generate, -1);
|
804
828
|
|
829
|
+
rb_undef_method(json, "parse");
|
805
830
|
rb_define_module_function(json, "parse", oj_mimic_parse, -1);
|
831
|
+
rb_undef_method(json, "parse!");
|
806
832
|
rb_define_module_function(json, "parse!", mimic_parse_bang, -1);
|
807
833
|
|
834
|
+
rb_undef_method(json, "state");
|
808
835
|
rb_define_module_function(json, "state", mimic_state, 0);
|
836
|
+
rb_gv_set("$VERBOSE", verbose);
|
809
837
|
|
810
838
|
if (rb_const_defined_at(json, rb_intern("JSONError"))) {
|
811
839
|
json_error = rb_const_get(json, rb_intern("JSONError"));
|