oj 3.13.23 → 3.16.9
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 +81 -0
- data/README.md +2 -2
- data/ext/oj/buf.h +7 -6
- data/ext/oj/cache.c +29 -26
- data/ext/oj/cache.h +3 -2
- data/ext/oj/cache8.c +10 -9
- data/ext/oj/circarray.c +7 -5
- data/ext/oj/circarray.h +2 -2
- data/ext/oj/code.c +5 -12
- data/ext/oj/code.h +2 -2
- data/ext/oj/compat.c +20 -60
- data/ext/oj/custom.c +26 -59
- data/ext/oj/debug.c +3 -9
- data/ext/oj/dump.c +103 -53
- data/ext/oj/dump.h +1 -4
- data/ext/oj/dump_compat.c +557 -592
- data/ext/oj/dump_leaf.c +3 -5
- data/ext/oj/dump_object.c +42 -48
- data/ext/oj/dump_strict.c +10 -22
- 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 +16 -7
- data/ext/oj/fast.c +60 -92
- data/ext/oj/intern.c +62 -47
- data/ext/oj/intern.h +3 -7
- data/ext/oj/mem.c +318 -0
- data/ext/oj/mem.h +53 -0
- data/ext/oj/mimic_json.c +51 -32
- data/ext/oj/object.c +33 -43
- data/ext/oj/odd.c +8 -6
- data/ext/oj/odd.h +4 -4
- data/ext/oj/oj.c +243 -212
- data/ext/oj/oj.h +83 -81
- data/ext/oj/parse.c +94 -148
- data/ext/oj/parse.h +21 -24
- data/ext/oj/parser.c +80 -67
- data/ext/oj/parser.h +7 -8
- data/ext/oj/rails.c +70 -92
- data/ext/oj/reader.c +9 -14
- 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 +10 -9
- data/ext/oj/saj2.c +37 -49
- data/ext/oj/saj2.h +1 -1
- data/ext/oj/scp.c +3 -14
- data/ext/oj/sparse.c +22 -70
- data/ext/oj/stream_writer.c +45 -41
- data/ext/oj/strict.c +20 -52
- data/ext/oj/string_writer.c +64 -38
- data/ext/oj/trace.h +31 -4
- data/ext/oj/usual.c +125 -114
- data/ext/oj/usual.h +7 -6
- data/ext/oj/util.h +1 -1
- data/ext/oj/val_stack.c +13 -2
- data/ext/oj/val_stack.h +8 -7
- data/ext/oj/wab.c +25 -57
- data/lib/oj/active_support_helper.rb +1 -3
- 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 +162 -150
- data/lib/oj/mimic.rb +7 -7
- data/lib/oj/schandler.rb +5 -4
- data/lib/oj/state.rb +8 -5
- data/lib/oj/version.rb +1 -2
- data/lib/oj.rb +2 -0
- data/pages/InstallOptions.md +20 -0
- data/pages/Options.md +4 -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/activesupport6/encoding_test.rb +63 -28
- data/test/activesupport7/abstract_unit.rb +4 -1
- data/test/activesupport7/encoding_test.rb +72 -22
- data/test/files.rb +15 -15
- data/test/foo.rb +18 -69
- data/test/helper.rb +5 -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 +8 -6
- 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 +50 -33
- data/test/json_gem/json_generic_object_test.rb +11 -11
- data/test/json_gem/json_parser_test.rb +46 -46
- data/test/json_gem/json_string_matching_test.rb +9 -9
- data/test/mem.rb +13 -12
- data/test/perf.rb +21 -26
- data/test/perf_compat.rb +31 -33
- data/test/perf_dump.rb +28 -28
- 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 +5 -5
- 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 +81 -54
- data/test/test_custom.rb +63 -52
- data/test/test_debian.rb +7 -10
- data/test/test_fast.rb +86 -90
- data/test/test_file.rb +24 -29
- data/test/test_gc.rb +5 -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 +92 -87
- data/test/test_parser.rb +4 -4
- data/test/test_parser_debug.rb +5 -5
- data/test/test_parser_saj.rb +27 -25
- data/test/test_parser_usual.rb +44 -6
- data/test/test_rails.rb +2 -2
- data/test/test_saj.rb +10 -8
- data/test/test_scp.rb +35 -35
- data/test/test_strict.rb +38 -32
- data/test/test_various.rb +146 -97
- data/test/test_wab.rb +46 -44
- data/test/test_writer.rb +63 -47
- data/test/tests.rb +7 -7
- data/test/tests_mimic.rb +6 -6
- data/test/tests_mimic_addition.rb +6 -6
- metadata +46 -26
- 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/abstract_unit.rb +0 -45
- data/test/activesupport5/decoding_test.rb +0 -133
- data/test/activesupport5/encoding_test.rb +0 -500
- data/test/activesupport5/encoding_test_cases.rb +0 -98
- data/test/activesupport5/test_helper.rb +0 -72
- data/test/activesupport5/time_zone_test_helpers.rb +0 -39
- data/test/bar.rb +0 -11
- 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
|
|
@@ -208,7 +209,6 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
208
209
|
|
209
210
|
oj_out_init(&out);
|
210
211
|
|
211
|
-
out.caller = CALLER_DUMP;
|
212
212
|
copts.escape_mode = JXEsc;
|
213
213
|
copts.mode = CompatMode;
|
214
214
|
|
@@ -348,12 +348,11 @@ static VALUE mimic_load(int argc, VALUE *argv, VALUE self) {
|
|
348
348
|
static VALUE mimic_dump_load(int argc, VALUE *argv, VALUE self) {
|
349
349
|
if (1 > argc) {
|
350
350
|
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
|
351
|
-
}
|
351
|
+
}
|
352
|
+
if (T_STRING == rb_type(*argv)) {
|
352
353
|
return mimic_load(argc, argv, self);
|
353
|
-
} else {
|
354
|
-
return mimic_dump(argc, argv, self);
|
355
354
|
}
|
356
|
-
return
|
355
|
+
return mimic_dump(argc, argv, self);
|
357
356
|
}
|
358
357
|
|
359
358
|
static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
@@ -367,8 +366,7 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
367
366
|
|
368
367
|
oj_out_init(&out);
|
369
368
|
|
370
|
-
out.omit_nil
|
371
|
-
out.caller = CALLER_GENERATE;
|
369
|
+
out.omit_nil = copts->dump_opts.omit_nil;
|
372
370
|
// For obj.to_json or generate nan is not allowed but if called from dump
|
373
371
|
// it is.
|
374
372
|
copts->dump_opts.nan_dump = RaiseNan;
|
@@ -388,10 +386,8 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
388
386
|
VALUE active_hack[1];
|
389
387
|
|
390
388
|
if (Qundef == state_class) {
|
391
|
-
rb_warn(
|
392
|
-
|
393
|
-
"Call it explicitly beforehand if you want to remove this warning."
|
394
|
-
);
|
389
|
+
rb_warn("Oj::Rails.mimic_JSON was called implicitly. "
|
390
|
+
"Call it explicitly beforehand if you want to remove this warning.");
|
395
391
|
oj_define_mimic_json(0, NULL, Qnil);
|
396
392
|
}
|
397
393
|
active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
|
@@ -429,7 +425,7 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
429
425
|
* - *:object_nl* [_String_] String placed after a JSON object
|
430
426
|
* - *:array_nl* [_String_] String placed after a JSON array
|
431
427
|
* - *:ascii_only* [_Boolean_] if not nil or false then use only ascii characters in the output.
|
432
|
-
*
|
428
|
+
* Note JSON.generate does support this even if it is not documented.
|
433
429
|
*
|
434
430
|
* Returns [_String_] generated JSON.
|
435
431
|
*/
|
@@ -466,7 +462,7 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
466
462
|
}
|
467
463
|
if (1 == argc || Qnil == argv[1]) {
|
468
464
|
h = rb_hash_new();
|
469
|
-
} else
|
465
|
+
} else {
|
470
466
|
h = argv[1];
|
471
467
|
}
|
472
468
|
if (!oj_hash_has_key(h, oj_indent_sym)) {
|
@@ -485,10 +481,8 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
485
481
|
rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
|
486
482
|
}
|
487
483
|
if (Qundef == state_class) {
|
488
|
-
rb_warn(
|
489
|
-
|
490
|
-
"Call it explicitly beforehand if you want to remove this warning."
|
491
|
-
);
|
484
|
+
rb_warn("Oj::Rails.mimic_JSON was called implicitly. "
|
485
|
+
"Call it explicitly beforehand if you want to remove this warning.");
|
492
486
|
oj_define_mimic_json(0, NULL, Qnil);
|
493
487
|
}
|
494
488
|
rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
|
@@ -578,7 +572,6 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
578
572
|
if (T_HASH != rb_type(ropts)) {
|
579
573
|
rb_raise(rb_eArgError, "options must be a hash.");
|
580
574
|
}
|
581
|
-
|
582
575
|
rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
|
583
576
|
v = rb_hash_lookup(ropts, oj_max_nesting_sym);
|
584
577
|
if (Qtrue == v) {
|
@@ -612,9 +605,9 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
612
605
|
* - *source* [_String_|IO] source to parse
|
613
606
|
* - *opts* [_Hash_] options
|
614
607
|
* - *:symbolize* [Boolean] _names flag indicating JSON object keys should be Symbols instead of
|
615
|
-
*
|
608
|
+
* Strings
|
616
609
|
* - *:create_additions* [Boolean] flag indicating a key matching +create_id+ in a JSON object
|
617
|
-
*
|
610
|
+
* should trigger the creation of Ruby Object
|
618
611
|
*
|
619
612
|
* Returns [Object]
|
620
613
|
* @see create_id=
|
@@ -657,23 +650,22 @@ static VALUE mimic_recurse_proc(VALUE self, VALUE obj) {
|
|
657
650
|
*
|
658
651
|
* - *id* [_nil_|String] new create_id
|
659
652
|
*
|
660
|
-
* Returns [_String_] the id.
|
653
|
+
* Returns [_nil_|_String_] the id.
|
661
654
|
*/
|
662
655
|
static VALUE mimic_set_create_id(VALUE self, VALUE id) {
|
663
|
-
Check_Type(id, T_STRING);
|
664
|
-
|
665
656
|
if (NULL != oj_default_options.create_id) {
|
666
657
|
if (oj_json_class != oj_default_options.create_id) {
|
667
|
-
|
658
|
+
OJ_R_FREE((char *)oj_default_options.create_id);
|
668
659
|
}
|
669
660
|
oj_default_options.create_id = NULL;
|
670
661
|
oj_default_options.create_id_len = 0;
|
671
662
|
}
|
672
663
|
if (Qnil != id) {
|
673
|
-
|
664
|
+
const char *ptr = StringValueCStr(id);
|
665
|
+
size_t len = RSTRING_LEN(id) + 1;
|
674
666
|
|
675
|
-
oj_default_options.create_id =
|
676
|
-
strcpy((char *)oj_default_options.create_id,
|
667
|
+
oj_default_options.create_id = OJ_R_ALLOC_N(char, len);
|
668
|
+
strcpy((char *)oj_default_options.create_id, ptr);
|
677
669
|
oj_default_options.create_id_len = len - 1;
|
678
670
|
}
|
679
671
|
return id;
|
@@ -743,6 +735,7 @@ static struct _options mimic_object_to_json_options = {0, // indent
|
|
743
735
|
0, // array_size
|
744
736
|
RaiseNan, // nan_dump
|
745
737
|
false, // omit_nil
|
738
|
+
false, // omit_null_byte
|
746
739
|
100, // max_depth
|
747
740
|
},
|
748
741
|
{
|
@@ -762,9 +755,9 @@ static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
|
|
762
755
|
|
763
756
|
oj_out_init(&out);
|
764
757
|
|
765
|
-
out.omit_nil
|
766
|
-
copts.mode
|
767
|
-
copts.to_json
|
758
|
+
out.omit_nil = copts.dump_opts.omit_nil;
|
759
|
+
copts.mode = CompatMode;
|
760
|
+
copts.to_json = No;
|
768
761
|
if (1 <= argc && Qnil != argv[0]) {
|
769
762
|
oj_parse_mimic_dump_options(argv[0], &copts);
|
770
763
|
}
|
@@ -796,39 +789,63 @@ void oj_mimic_json_methods(VALUE json) {
|
|
796
789
|
VALUE json_error;
|
797
790
|
VALUE generator;
|
798
791
|
VALUE ext;
|
792
|
+
VALUE verbose;
|
799
793
|
|
794
|
+
// rb_undef_method doesn't work for modules or maybe sometimes
|
795
|
+
// doesn't. Anyway setting verbose should hide the warning.
|
796
|
+
verbose = rb_gv_get("$VERBOSE");
|
797
|
+
rb_gv_set("$VERBOSE", Qfalse);
|
798
|
+
|
799
|
+
rb_undef_method(json, "create_id=");
|
800
800
|
rb_define_module_function(json, "create_id=", mimic_set_create_id, 1);
|
801
|
+
rb_undef_method(json, "create_id");
|
801
802
|
rb_define_module_function(json, "create_id", mimic_create_id, 0);
|
802
803
|
|
804
|
+
rb_undef_method(json, "dump");
|
803
805
|
rb_define_module_function(json, "dump", mimic_dump, -1);
|
806
|
+
rb_undef_method(json, "load");
|
804
807
|
rb_define_module_function(json, "load", mimic_load, -1);
|
805
808
|
rb_define_module_function(json, "restore", mimic_load, -1);
|
809
|
+
rb_undef_method(json, "recurse_proc");
|
806
810
|
rb_define_module_function(json, "recurse_proc", mimic_recurse_proc, 1);
|
811
|
+
rb_undef_method(json, "[]");
|
807
812
|
rb_define_module_function(json, "[]", mimic_dump_load, -1);
|
808
813
|
|
814
|
+
rb_undef_method(json, "generate");
|
809
815
|
rb_define_module_function(json, "generate", oj_mimic_generate, -1);
|
816
|
+
rb_undef_method(json, "fast_generate");
|
810
817
|
rb_define_module_function(json, "fast_generate", oj_mimic_generate, -1);
|
818
|
+
rb_undef_method(json, "pretty_generate");
|
811
819
|
rb_define_module_function(json, "pretty_generate", oj_mimic_pretty_generate, -1);
|
812
820
|
// For older versions of JSON, the deprecated unparse methods.
|
821
|
+
rb_undef_method(json, "unparse");
|
813
822
|
rb_define_module_function(json, "unparse", oj_mimic_generate, -1);
|
814
823
|
rb_define_module_function(json, "fast_unparse", oj_mimic_generate, -1);
|
815
824
|
rb_define_module_function(json, "pretty_unparse", oj_mimic_pretty_generate, -1);
|
816
825
|
|
826
|
+
rb_undef_method(json, "parse");
|
817
827
|
rb_define_module_function(json, "parse", oj_mimic_parse, -1);
|
828
|
+
rb_undef_method(json, "parse!");
|
818
829
|
rb_define_module_function(json, "parse!", mimic_parse_bang, -1);
|
819
830
|
|
831
|
+
rb_undef_method(json, "state");
|
820
832
|
rb_define_module_function(json, "state", mimic_state, 0);
|
833
|
+
rb_gv_set("$VERBOSE", verbose);
|
821
834
|
|
822
835
|
if (rb_const_defined_at(json, rb_intern("JSONError"))) {
|
823
836
|
json_error = rb_const_get(json, rb_intern("JSONError"));
|
824
837
|
} else {
|
825
838
|
json_error = rb_define_class_under(json, "JSONError", rb_eStandardError);
|
826
839
|
}
|
840
|
+
|
841
|
+
rb_global_variable(&oj_json_parser_error_class);
|
827
842
|
if (rb_const_defined_at(json, rb_intern("ParserError"))) {
|
828
843
|
oj_json_parser_error_class = rb_const_get(json, rb_intern("ParserError"));
|
829
844
|
} else {
|
830
845
|
oj_json_parser_error_class = rb_define_class_under(json, "ParserError", json_error);
|
831
846
|
}
|
847
|
+
|
848
|
+
rb_global_variable(&oj_json_generator_error_class);
|
832
849
|
if (rb_const_defined_at(json, rb_intern("GeneratorError"))) {
|
833
850
|
oj_json_generator_error_class = rb_const_get(json, rb_intern("GeneratorError"));
|
834
851
|
} else {
|
@@ -854,8 +871,8 @@ void oj_mimic_json_methods(VALUE json) {
|
|
854
871
|
rb_require("oj/state");
|
855
872
|
}
|
856
873
|
// Pull in the JSON::State mimic file.
|
874
|
+
rb_global_variable(&state_class);
|
857
875
|
state_class = rb_const_get_at(generator, rb_intern("State"));
|
858
|
-
rb_gc_register_mark_object(state_class);
|
859
876
|
}
|
860
877
|
|
861
878
|
/* Document-module: JSON
|
@@ -892,7 +909,9 @@ oj_define_mimic_json(int argc, VALUE *argv, VALUE self) {
|
|
892
909
|
}
|
893
910
|
oj_mimic_json_methods(json);
|
894
911
|
|
895
|
-
|
912
|
+
if (!rb_const_defined(rb_cObject, rb_intern("ActiveSupport"))) {
|
913
|
+
rb_define_method(rb_cObject, "to_json", mimic_object_to_json, -1);
|
914
|
+
}
|
896
915
|
|
897
916
|
rb_gv_set("$VERBOSE", verbose);
|
898
917
|
|