oj 3.13.23 → 3.14.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/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
data/ext/oj/mem.c
ADDED
@@ -0,0 +1,324 @@
|
|
1
|
+
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#include <pthread.h>
|
4
|
+
#include <stdbool.h>
|
5
|
+
#include <stdint.h>
|
6
|
+
#include <stdio.h>
|
7
|
+
#include <stdlib.h>
|
8
|
+
#include <string.h>
|
9
|
+
|
10
|
+
#include <ruby.h>
|
11
|
+
|
12
|
+
#include "mem.h"
|
13
|
+
|
14
|
+
typedef struct _rec {
|
15
|
+
struct _rec *next;
|
16
|
+
const void *ptr;
|
17
|
+
size_t size;
|
18
|
+
const char *file;
|
19
|
+
int line;
|
20
|
+
bool ruby;
|
21
|
+
} *Rec;
|
22
|
+
|
23
|
+
typedef struct _rep {
|
24
|
+
struct _rep *next;
|
25
|
+
size_t size;
|
26
|
+
const char *file;
|
27
|
+
int line;
|
28
|
+
int cnt;
|
29
|
+
} *Rep;
|
30
|
+
|
31
|
+
#ifdef MEM_DEBUG
|
32
|
+
|
33
|
+
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
34
|
+
static Rec recs = NULL;
|
35
|
+
static const char mem_pad[] = "--- This is a memory pad and should not change until being freed. ---";
|
36
|
+
|
37
|
+
void*
|
38
|
+
oj_malloc(size_t size, const char *file, int line) {
|
39
|
+
void *ptr = malloc(size + sizeof(mem_pad));
|
40
|
+
|
41
|
+
if (NULL != ptr) {
|
42
|
+
Rec r = (Rec)malloc(sizeof(struct _rec));
|
43
|
+
|
44
|
+
if (NULL != r) {
|
45
|
+
strcpy(((char*)ptr) + size, mem_pad);
|
46
|
+
r->ptr = ptr;
|
47
|
+
r->size = size;
|
48
|
+
r->file = file;
|
49
|
+
r->line = line;
|
50
|
+
r->ruby = false;
|
51
|
+
pthread_mutex_lock(&lock);
|
52
|
+
r->next = recs;
|
53
|
+
recs = r;
|
54
|
+
pthread_mutex_unlock(&lock);
|
55
|
+
} else {
|
56
|
+
free(ptr);
|
57
|
+
ptr = NULL;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
return ptr;
|
61
|
+
}
|
62
|
+
|
63
|
+
void*
|
64
|
+
oj_realloc(void *orig, size_t size, const char *file, int line) {
|
65
|
+
void *ptr = realloc(orig, size + sizeof(mem_pad));
|
66
|
+
Rec r;
|
67
|
+
|
68
|
+
if (NULL != ptr) {
|
69
|
+
strcpy(((char*)ptr) + size, mem_pad);
|
70
|
+
pthread_mutex_lock(&lock);
|
71
|
+
for (r = recs; NULL != r; r = r->next) {
|
72
|
+
if (orig == r->ptr) {
|
73
|
+
r->ptr = ptr;
|
74
|
+
r->size = size;
|
75
|
+
r->file = file;
|
76
|
+
r->line = line;
|
77
|
+
r->ruby = false;
|
78
|
+
break;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
pthread_mutex_unlock(&lock);
|
82
|
+
if (NULL == r) {
|
83
|
+
printf("Realloc at %s:%d (%p) not allocated.\n", file, line, orig);
|
84
|
+
}
|
85
|
+
}
|
86
|
+
return ptr;
|
87
|
+
}
|
88
|
+
|
89
|
+
void*
|
90
|
+
oj_calloc(size_t count, size_t size, const char *file, int line) {
|
91
|
+
void *ptr;
|
92
|
+
|
93
|
+
size *= count;
|
94
|
+
if (NULL != (ptr = malloc(size + sizeof(mem_pad)))) {
|
95
|
+
Rec r = (Rec)malloc(sizeof(struct _rec));
|
96
|
+
|
97
|
+
if (NULL != r) {
|
98
|
+
memset(ptr, 0, size);
|
99
|
+
strcpy(((char*)ptr) + size, mem_pad);
|
100
|
+
r->ptr = ptr;
|
101
|
+
r->size = size;
|
102
|
+
r->file = file;
|
103
|
+
r->line = line;
|
104
|
+
r->ruby = false;
|
105
|
+
pthread_mutex_lock(&lock);
|
106
|
+
r->next = recs;
|
107
|
+
recs = r;
|
108
|
+
pthread_mutex_unlock(&lock);
|
109
|
+
} else {
|
110
|
+
free(ptr);
|
111
|
+
ptr = NULL;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
return ptr;
|
115
|
+
}
|
116
|
+
|
117
|
+
void*
|
118
|
+
oj_r_alloc(size_t size, const char *file, int line) {
|
119
|
+
void *ptr = ruby_xmalloc(size + sizeof(mem_pad));
|
120
|
+
|
121
|
+
if (NULL != ptr) {
|
122
|
+
Rec r = (Rec)malloc(sizeof(struct _rec));
|
123
|
+
|
124
|
+
if (NULL != r) {
|
125
|
+
strcpy(((char*)ptr) + size, mem_pad);
|
126
|
+
r->ptr = ptr;
|
127
|
+
r->size = size;
|
128
|
+
r->file = file;
|
129
|
+
r->line = line;
|
130
|
+
r->ruby = true;
|
131
|
+
pthread_mutex_lock(&lock);
|
132
|
+
r->next = recs;
|
133
|
+
recs = r;
|
134
|
+
pthread_mutex_unlock(&lock);
|
135
|
+
} else {
|
136
|
+
free(ptr);
|
137
|
+
ptr = NULL;
|
138
|
+
}
|
139
|
+
}
|
140
|
+
return ptr;
|
141
|
+
}
|
142
|
+
|
143
|
+
void*
|
144
|
+
oj_r_realloc(void *orig, size_t size, const char *file, int line) {
|
145
|
+
void *ptr = ruby_xrealloc2(orig, 1, size + sizeof(mem_pad));
|
146
|
+
Rec r;
|
147
|
+
|
148
|
+
if (NULL != ptr) {
|
149
|
+
strcpy(((char*)ptr) + size, mem_pad);
|
150
|
+
pthread_mutex_lock(&lock);
|
151
|
+
for (r = recs; NULL != r; r = r->next) {
|
152
|
+
if (orig == r->ptr) {
|
153
|
+
r->ptr = ptr;
|
154
|
+
r->size = size;
|
155
|
+
r->file = file;
|
156
|
+
r->line = line;
|
157
|
+
r->ruby = true;
|
158
|
+
break;
|
159
|
+
}
|
160
|
+
}
|
161
|
+
pthread_mutex_unlock(&lock);
|
162
|
+
if (NULL == r) {
|
163
|
+
printf("Realloc at %s:%d (%p) not allocated.\n", file, line, orig);
|
164
|
+
}
|
165
|
+
}
|
166
|
+
return ptr;
|
167
|
+
}
|
168
|
+
|
169
|
+
|
170
|
+
void
|
171
|
+
oj_freed(void *ptr, const char *file, int line, bool ruby) {
|
172
|
+
if (NULL != ptr) {
|
173
|
+
Rec r = NULL;
|
174
|
+
Rec prev = NULL;
|
175
|
+
|
176
|
+
pthread_mutex_lock(&lock);
|
177
|
+
for (r = recs; NULL != r; r = r->next) {
|
178
|
+
if (ptr == r->ptr) {
|
179
|
+
if (NULL == prev) {
|
180
|
+
recs = r->next;
|
181
|
+
} else {
|
182
|
+
prev->next = r->next;
|
183
|
+
}
|
184
|
+
break;
|
185
|
+
}
|
186
|
+
prev = r;
|
187
|
+
}
|
188
|
+
pthread_mutex_unlock(&lock);
|
189
|
+
if (NULL == r) {
|
190
|
+
printf("Free at %s:%d (%p) not allocated or already freed.\n", file, line, ptr);
|
191
|
+
} else {
|
192
|
+
char *pad = (char*)r->ptr + r->size;
|
193
|
+
|
194
|
+
if (r->ruby != ruby) {
|
195
|
+
if (r->ruby) {
|
196
|
+
printf("Memory at %s:%d (%p) allocated with Ruby allocator and freed with stdlib free.\n", file, line, ptr);
|
197
|
+
} else {
|
198
|
+
printf("Memory at %s:%d (%p) allocated with stdlib allocator and freed with Ruby free.\n", file, line, ptr);
|
199
|
+
}
|
200
|
+
}
|
201
|
+
if (0 != strcmp(mem_pad, pad)) {
|
202
|
+
uint8_t *p;
|
203
|
+
uint8_t *end = (uint8_t*)pad + sizeof(mem_pad);
|
204
|
+
|
205
|
+
printf("Memory at %s:%d (%p) write outside allocated.\n", file, line, ptr);
|
206
|
+
for (p = (uint8_t*)pad; p < end; p++) {
|
207
|
+
if (0x20 < *p && *p < 0x7f) {
|
208
|
+
printf("%c ", *p);
|
209
|
+
} else {
|
210
|
+
printf("%02x ", *(uint8_t*)p);
|
211
|
+
}
|
212
|
+
}
|
213
|
+
printf("\n");
|
214
|
+
}
|
215
|
+
free(r);
|
216
|
+
}
|
217
|
+
}
|
218
|
+
}
|
219
|
+
|
220
|
+
void
|
221
|
+
oj_r_free(void *ptr, const char *file, int line) {
|
222
|
+
oj_freed(ptr, file, line, true);
|
223
|
+
xfree(ptr);
|
224
|
+
}
|
225
|
+
|
226
|
+
|
227
|
+
void
|
228
|
+
oj_free(void *ptr, const char *file, int line) {
|
229
|
+
oj_freed(ptr, file, line, false);
|
230
|
+
free(ptr);
|
231
|
+
}
|
232
|
+
|
233
|
+
char*
|
234
|
+
oj_mem_strdup(const char *str, const char *file, int line) {
|
235
|
+
size_t size = strlen(str) + 1;
|
236
|
+
char *ptr = (char*)malloc(size + sizeof(mem_pad));
|
237
|
+
|
238
|
+
if (NULL != ptr) {
|
239
|
+
Rec r = (Rec)malloc(sizeof(struct _rec));
|
240
|
+
|
241
|
+
if (NULL != r) {
|
242
|
+
strcpy(ptr, str);
|
243
|
+
strcpy(((char*)ptr) + size, mem_pad);
|
244
|
+
r->ptr = (void*)ptr;
|
245
|
+
r->size = size;
|
246
|
+
r->file = file;
|
247
|
+
r->line = line;
|
248
|
+
r->ruby = false;
|
249
|
+
pthread_mutex_lock(&lock);
|
250
|
+
r->next = recs;
|
251
|
+
recs = r;
|
252
|
+
pthread_mutex_unlock(&lock);
|
253
|
+
} else {
|
254
|
+
free(ptr);
|
255
|
+
ptr = NULL;
|
256
|
+
}
|
257
|
+
}
|
258
|
+
return ptr;
|
259
|
+
}
|
260
|
+
|
261
|
+
#endif
|
262
|
+
|
263
|
+
#ifdef MEM_DEBUG
|
264
|
+
|
265
|
+
static Rep
|
266
|
+
update_reps(Rep reps, Rec r) {
|
267
|
+
Rep rp = reps;
|
268
|
+
|
269
|
+
for (; NULL != rp; rp = rp->next) {
|
270
|
+
if (rp->line == r->line && (rp->file == r->file || 0 == strcmp(rp->file, r->file))) {
|
271
|
+
rp->size += r->size;
|
272
|
+
rp->cnt++;
|
273
|
+
break;
|
274
|
+
}
|
275
|
+
}
|
276
|
+
if (NULL == rp &&
|
277
|
+
NULL != (rp = (Rep)malloc(sizeof(struct _rep)))) {
|
278
|
+
rp->size = r->size;
|
279
|
+
rp->file = r->file;
|
280
|
+
rp->line = r->line;
|
281
|
+
rp->cnt = 1;
|
282
|
+
rp->next = reps;
|
283
|
+
reps = rp;
|
284
|
+
}
|
285
|
+
return reps;
|
286
|
+
}
|
287
|
+
|
288
|
+
static void
|
289
|
+
print_stats() {
|
290
|
+
printf("\n--- Memory Usage Report --------------------------------------------------------\n");
|
291
|
+
pthread_mutex_lock(&lock);
|
292
|
+
|
293
|
+
if (NULL == recs) {
|
294
|
+
printf("No memory leaks\n");
|
295
|
+
} else {
|
296
|
+
Rep reps = NULL;
|
297
|
+
Rep rp;
|
298
|
+
Rec r;
|
299
|
+
size_t leaked = 0;
|
300
|
+
|
301
|
+
for (r = recs; NULL != r; r = r->next) {
|
302
|
+
reps = update_reps(reps, r);
|
303
|
+
}
|
304
|
+
while (NULL != (rp = reps)) {
|
305
|
+
reps = rp->next;
|
306
|
+
printf("%16s:%3d %8lu bytes over %d occurances allocated and not freed.\n", rp->file, rp->line, rp->size, rp->cnt);
|
307
|
+
leaked += rp->size;
|
308
|
+
free(rp);
|
309
|
+
}
|
310
|
+
printf("%lu bytes leaked\n", leaked);
|
311
|
+
}
|
312
|
+
pthread_mutex_unlock(&lock);
|
313
|
+
printf("--------------------------------------------------------------------------------\n");
|
314
|
+
}
|
315
|
+
|
316
|
+
#endif
|
317
|
+
|
318
|
+
void
|
319
|
+
oj_mem_report() {
|
320
|
+
#ifdef MEM_DEBUG
|
321
|
+
rb_gc();
|
322
|
+
print_stats();
|
323
|
+
#endif
|
324
|
+
}
|
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
@@ -1,6 +1,7 @@
|
|
1
1
|
// Copyright (c) 2012, 2017 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 "dump.h"
|
5
6
|
#include "encode.h"
|
6
7
|
#include "oj.h"
|
@@ -664,7 +665,7 @@ static VALUE mimic_set_create_id(VALUE self, VALUE id) {
|
|
664
665
|
|
665
666
|
if (NULL != oj_default_options.create_id) {
|
666
667
|
if (oj_json_class != oj_default_options.create_id) {
|
667
|
-
|
668
|
+
OJ_R_FREE((char *)oj_default_options.create_id);
|
668
669
|
}
|
669
670
|
oj_default_options.create_id = NULL;
|
670
671
|
oj_default_options.create_id_len = 0;
|
@@ -672,7 +673,7 @@ static VALUE mimic_set_create_id(VALUE self, VALUE id) {
|
|
672
673
|
if (Qnil != id) {
|
673
674
|
size_t len = RSTRING_LEN(id) + 1;
|
674
675
|
|
675
|
-
oj_default_options.create_id =
|
676
|
+
oj_default_options.create_id = OJ_R_ALLOC_N(char, len);
|
676
677
|
strcpy((char *)oj_default_options.create_id, StringValuePtr(id));
|
677
678
|
oj_default_options.create_id_len = len - 1;
|
678
679
|
}
|
data/ext/oj/object.c
CHANGED
@@ -308,7 +308,7 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
|
|
308
308
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
|
309
309
|
return 1;
|
310
310
|
}
|
311
|
-
e1 = *
|
311
|
+
e1 = *RARRAY_CONST_PTR(value);
|
312
312
|
// check for anonymous Struct
|
313
313
|
if (T_ARRAY == rb_type(e1)) {
|
314
314
|
VALUE args[1024];
|
@@ -322,10 +322,10 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
|
|
322
322
|
sc = rb_funcall2(rb_cStruct, oj_new_id, cnt, args);
|
323
323
|
} else {
|
324
324
|
// If struct is not defined then we let this fail and raise an exception.
|
325
|
-
sc = oj_name2struct(pi, *
|
325
|
+
sc = oj_name2struct(pi, *RARRAY_CONST_PTR(value), rb_eArgError);
|
326
326
|
}
|
327
327
|
if (sc == rb_cRange) {
|
328
|
-
parent->val = rb_class_new_instance(len - 1,
|
328
|
+
parent->val = rb_class_new_instance(len - 1, RARRAY_CONST_PTR(value) + 1, rb_cRange);
|
329
329
|
} else {
|
330
330
|
// Create a properly initialized struct instance without calling the initialize method.
|
331
331
|
parent->val = rb_obj_alloc(sc);
|
@@ -346,20 +346,20 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
|
|
346
346
|
int i;
|
347
347
|
|
348
348
|
for (i = 0; i < len - 1; i++) {
|
349
|
-
rb_struct_aset(parent->val, INT2FIX(i),
|
349
|
+
rb_struct_aset(parent->val, INT2FIX(i), RARRAY_CONST_PTR(value)[i + 1]);
|
350
350
|
}
|
351
351
|
}
|
352
352
|
}
|
353
353
|
return 1;
|
354
354
|
} else if (3 <= klen && '#' == key[1]) {
|
355
|
-
volatile VALUE *a;
|
355
|
+
volatile const VALUE *a;
|
356
356
|
|
357
357
|
if (2 != len) {
|
358
358
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
|
359
359
|
return 1;
|
360
360
|
}
|
361
361
|
parent->val = rb_hash_new();
|
362
|
-
a =
|
362
|
+
a = RARRAY_CONST_PTR(value);
|
363
363
|
rb_hash_aset(parent->val, *a, a[1]);
|
364
364
|
|
365
365
|
return 1;
|
@@ -546,7 +546,7 @@ WHICH_TYPE:
|
|
546
546
|
} else {
|
547
547
|
if (3 <= klen && '^' == *key && '#' == key[1] && T_ARRAY == rb_type(value)) {
|
548
548
|
long len = RARRAY_LEN(value);
|
549
|
-
volatile VALUE *a =
|
549
|
+
volatile const VALUE *a = RARRAY_CONST_PTR(value);
|
550
550
|
|
551
551
|
if (2 != len) {
|
552
552
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
|
@@ -609,9 +609,7 @@ WHICH_TYPE:
|
|
609
609
|
}
|
610
610
|
|
611
611
|
static VALUE start_hash(ParseInfo pi) {
|
612
|
-
|
613
|
-
oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
|
614
|
-
}
|
612
|
+
TRACE_PARSE_IN(pi->options.trace, "start_hash", pi);
|
615
613
|
return Qnil;
|
616
614
|
}
|
617
615
|
|
@@ -627,9 +625,7 @@ static void end_hash(ParseInfo pi) {
|
|
627
625
|
oj_odd_free(oa);
|
628
626
|
parent->odd_args = NULL;
|
629
627
|
}
|
630
|
-
|
631
|
-
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
632
|
-
}
|
628
|
+
TRACE_PARSE_HASH_END(pi->options.trace, pi);
|
633
629
|
}
|
634
630
|
|
635
631
|
static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
data/ext/oj/odd.c
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
// Copyright (c) 2011 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 "odd.h"
|
5
6
|
|
6
7
|
#include <string.h>
|
@@ -68,7 +69,7 @@ void print_all_odds(const char *label) {
|
|
68
69
|
}
|
69
70
|
|
70
71
|
static Odd odd_create(void) {
|
71
|
-
Odd odd =
|
72
|
+
Odd odd = OJ_R_ALLOC(struct _odd);
|
72
73
|
|
73
74
|
memset(odd, 0, sizeof(struct _odd));
|
74
75
|
odd->next = odds;
|
@@ -172,7 +173,7 @@ Odd oj_get_oddc(const char *classname, size_t len) {
|
|
172
173
|
}
|
173
174
|
|
174
175
|
OddArgs oj_odd_alloc_args(Odd odd) {
|
175
|
-
OddArgs oa =
|
176
|
+
OddArgs oa = OJ_R_ALLOC_N(struct _oddArgs, 1);
|
176
177
|
VALUE *a;
|
177
178
|
int i;
|
178
179
|
|
@@ -184,7 +185,7 @@ OddArgs oj_odd_alloc_args(Odd odd) {
|
|
184
185
|
}
|
185
186
|
|
186
187
|
void oj_odd_free(OddArgs args) {
|
187
|
-
|
188
|
+
OJ_R_FREE(args);
|
188
189
|
}
|
189
190
|
|
190
191
|
int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
|
@@ -210,7 +211,7 @@ void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt,
|
|
210
211
|
odd = odd_create();
|
211
212
|
odd->clas = clas;
|
212
213
|
rb_gc_register_mark_object(odd->clas);
|
213
|
-
if (NULL == (odd->classname =
|
214
|
+
if (NULL == (odd->classname = OJ_STRDUP(rb_class2name(clas)))) {
|
214
215
|
rb_raise(rb_eNoMemError, "for class name.");
|
215
216
|
}
|
216
217
|
odd->clen = strlen(odd->classname);
|
@@ -224,13 +225,13 @@ void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt,
|
|
224
225
|
*fp = 0;
|
225
226
|
switch (rb_type(*members)) {
|
226
227
|
case T_STRING:
|
227
|
-
if (NULL == (*np =
|
228
|
+
if (NULL == (*np = OJ_STRDUP(RSTRING_PTR(*members)))) {
|
228
229
|
rb_raise(rb_eNoMemError, "for attribute name.");
|
229
230
|
}
|
230
231
|
break;
|
231
232
|
case T_SYMBOL:
|
232
233
|
// The symbol can move and invalidate the name so make a copy.
|
233
|
-
if (NULL == (*np =
|
234
|
+
if (NULL == (*np = OJ_STRDUP(rb_id2name(SYM2ID(*members))))) {
|
234
235
|
rb_raise(rb_eNoMemError, "for attribute name.");
|
235
236
|
}
|
236
237
|
break;
|
data/ext/oj/oj.c
CHANGED
@@ -11,6 +11,7 @@
|
|
11
11
|
#include <sys/types.h>
|
12
12
|
#include <unistd.h>
|
13
13
|
|
14
|
+
#include "mem.h"
|
14
15
|
#include "dump.h"
|
15
16
|
#include "encode.h"
|
16
17
|
#include "intern.h"
|
@@ -782,7 +783,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
782
783
|
} else if (create_id_sym == k) {
|
783
784
|
if (Qnil == v) {
|
784
785
|
if (oj_json_class != oj_default_options.create_id && NULL != copts->create_id) {
|
785
|
-
|
786
|
+
OJ_R_FREE((char *)oj_default_options.create_id);
|
786
787
|
}
|
787
788
|
copts->create_id = NULL;
|
788
789
|
copts->create_id_len = 0;
|
@@ -791,7 +792,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
791
792
|
|
792
793
|
len = RSTRING_LEN(v);
|
793
794
|
if (len != copts->create_id_len || 0 != strcmp(copts->create_id, str)) {
|
794
|
-
copts->create_id =
|
795
|
+
copts->create_id = OJ_R_ALLOC_N(char, len + 1);
|
795
796
|
strcpy((char *)copts->create_id, str);
|
796
797
|
copts->create_id_len = len;
|
797
798
|
}
|
@@ -911,7 +912,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
911
912
|
copts->array_class = v;
|
912
913
|
}
|
913
914
|
} else if (ignore_sym == k) {
|
914
|
-
|
915
|
+
OJ_R_FREE(copts->ignore);
|
915
916
|
copts->ignore = NULL;
|
916
917
|
if (Qnil != v) {
|
917
918
|
int cnt;
|
@@ -921,7 +922,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
921
922
|
if (0 < cnt) {
|
922
923
|
int i;
|
923
924
|
|
924
|
-
copts->ignore =
|
925
|
+
copts->ignore = OJ_R_ALLOC_N(VALUE, cnt + 1);
|
925
926
|
for (i = 0; i < cnt; i++) {
|
926
927
|
copts->ignore[i] = RARRAY_AREF(v, i);
|
927
928
|
}
|
@@ -1159,7 +1160,7 @@ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
|
|
1159
1160
|
WCHAR *wide_path;
|
1160
1161
|
wide_path = rb_w32_mbstr_to_wstr(CP_UTF8, path, -1, NULL);
|
1161
1162
|
fd = rb_w32_wopen(wide_path, O_RDONLY);
|
1162
|
-
|
1163
|
+
OJ_FREE(wide_path);
|
1163
1164
|
}
|
1164
1165
|
#else
|
1165
1166
|
fd = open(path, O_RDONLY);
|
@@ -1724,6 +1725,10 @@ debug_odd(VALUE self, VALUE label) {
|
|
1724
1725
|
return Qnil;
|
1725
1726
|
}
|
1726
1727
|
|
1728
|
+
static VALUE mem_report(VALUE self) {
|
1729
|
+
oj_mem_report();
|
1730
|
+
return Qnil;
|
1731
|
+
}
|
1727
1732
|
|
1728
1733
|
/* Document-module: Oj
|
1729
1734
|
*
|
@@ -1812,6 +1817,8 @@ void Init_oj(void) {
|
|
1812
1817
|
|
1813
1818
|
rb_define_module_function(Oj, "optimize_rails", oj_optimize_rails, 0);
|
1814
1819
|
|
1820
|
+
rb_define_module_function(Oj, "mem_report", mem_report, 0);
|
1821
|
+
|
1815
1822
|
oj_add_value_id = rb_intern("add_value");
|
1816
1823
|
oj_array_append_id = rb_intern("array_append");
|
1817
1824
|
oj_array_end_id = rb_intern("array_end");
|
data/ext/oj/oj.h
CHANGED
@@ -379,6 +379,12 @@ extern bool oj_use_hash_alt;
|
|
379
379
|
extern bool oj_use_array_alt;
|
380
380
|
extern bool string_writer_optimized;
|
381
381
|
|
382
|
+
static inline VALUE oj_safe_string_convert(VALUE obj) {
|
383
|
+
VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
384
|
+
StringValue(rstr);
|
385
|
+
return rstr;
|
386
|
+
}
|
387
|
+
|
382
388
|
#define APPEND_CHARS(buffer, chars, size) \
|
383
389
|
{ \
|
384
390
|
memcpy(buffer, chars, size); \
|