oj 3.14.1 → 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 +4 -0
- 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 +2 -1
- data/ext/oj/custom.c +3 -2
- data/ext/oj/dump.c +4 -3
- data/ext/oj/dump_object.c +3 -2
- data/ext/oj/fast.c +11 -10
- 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 +2 -2
- data/ext/oj/odd.c +7 -6
- data/ext/oj/oj.c +12 -5
- data/ext/oj/parse.c +14 -12
- data/ext/oj/parser.c +6 -6
- data/ext/oj/rails.c +9 -8
- data/ext/oj/reader.c +3 -2
- 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 +6 -5
- data/ext/oj/sparse.c +5 -4
- data/ext/oj/stream_writer.c +5 -4
- data/ext/oj/string_writer.c +7 -6
- data/ext/oj/usual.c +28 -27
- data/ext/oj/val_stack.h +4 -3
- data/lib/oj/version.rb +1 -1
- data/test/foo.rb +48 -3
- data/test/perf_parser.rb +1 -0
- metadata +5 -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
@@ -352,7 +352,7 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
|
|
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");
|
@@ -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 = RARRAY_CONST_PTR(value);
|
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");
|
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/parse.c
CHANGED
@@ -10,6 +10,7 @@
|
|
10
10
|
#include <string.h>
|
11
11
|
#include <unistd.h>
|
12
12
|
|
13
|
+
#include "mem.h"
|
13
14
|
#include "buf.h"
|
14
15
|
#include "encode.h"
|
15
16
|
#include "oj.h"
|
@@ -87,7 +88,7 @@ static void add_value(ParseInfo pi, VALUE rval) {
|
|
87
88
|
pi->hash_set_value(pi, parent, rval);
|
88
89
|
if (0 != parent->key && 0 < parent->klen &&
|
89
90
|
(parent->key < pi->json || pi->cur < parent->key)) {
|
90
|
-
|
91
|
+
OJ_R_FREE((char *)parent->key);
|
91
92
|
parent->key = 0;
|
92
93
|
}
|
93
94
|
parent->next = NEXT_HASH_COMMA;
|
@@ -236,7 +237,8 @@ static void read_escaped_str(ParseInfo pi, const char *start) {
|
|
236
237
|
|
237
238
|
for (s = pi->cur; '"' != *s;) {
|
238
239
|
const char *scanned = scan_func(s, pi->end);
|
239
|
-
if (scanned >= pi->end || '\0' == *
|
240
|
+
if (scanned >= pi->end || '\0' == *scanned) {
|
241
|
+
//if (scanned >= pi->end) {
|
240
242
|
oj_set_error_at(pi,
|
241
243
|
oj_parse_error_class,
|
242
244
|
__FILE__,
|
@@ -333,7 +335,7 @@ static void read_escaped_str(ParseInfo pi, const char *start) {
|
|
333
335
|
case NEXT_HASH_KEY:
|
334
336
|
if (Qundef == (parent->key_val = pi->hash_key(pi, buf.head, buf_len(&buf)))) {
|
335
337
|
parent->klen = buf_len(&buf);
|
336
|
-
parent->key =
|
338
|
+
parent->key = OJ_MALLOC(parent->klen + 1);
|
337
339
|
memcpy((char *)parent->key, buf.head, parent->klen);
|
338
340
|
*(char *)(parent->key + parent->klen) = '\0';
|
339
341
|
} else {
|
@@ -347,7 +349,7 @@ static void read_escaped_str(ParseInfo pi, const char *start) {
|
|
347
349
|
pi->hash_set_cstr(pi, parent, buf.head, buf_len(&buf), start);
|
348
350
|
if (0 != parent->key && 0 < parent->klen &&
|
349
351
|
(parent->key < pi->json || pi->cur < parent->key)) {
|
350
|
-
|
352
|
+
OJ_R_FREE((char *)parent->key);
|
351
353
|
parent->key = 0;
|
352
354
|
}
|
353
355
|
parent->next = NEXT_HASH_COMMA;
|
@@ -417,7 +419,7 @@ static void read_str(ParseInfo pi) {
|
|
417
419
|
pi->hash_set_cstr(pi, parent, str, pi->cur - str, str);
|
418
420
|
if (0 != parent->key && 0 < parent->klen &&
|
419
421
|
(parent->key < pi->json || pi->cur < parent->key)) {
|
420
|
-
|
422
|
+
OJ_R_FREE((char *)parent->key);
|
421
423
|
parent->key = 0;
|
422
424
|
}
|
423
425
|
parent->next = NEXT_HASH_COMMA;
|
@@ -616,7 +618,7 @@ static void read_num(ParseInfo pi) {
|
|
616
618
|
pi->hash_set_num(pi, parent, &ni);
|
617
619
|
if (0 != parent->key && 0 < parent->klen &&
|
618
620
|
(parent->key < pi->json || pi->cur < parent->key)) {
|
619
|
-
|
621
|
+
OJ_R_FREE((char *)parent->key);
|
620
622
|
parent->key = 0;
|
621
623
|
}
|
622
624
|
parent->next = NEXT_HASH_COMMA;
|
@@ -870,12 +872,12 @@ oj_num_as_value(NumInfo ni) {
|
|
870
872
|
buf[ni->len] = '\0';
|
871
873
|
rnum = rb_cstr_to_inum(buf, 10, 0);
|
872
874
|
} else {
|
873
|
-
char *buf =
|
875
|
+
char *buf = OJ_R_ALLOC_N(char, ni->len + 1);
|
874
876
|
|
875
877
|
memcpy(buf, ni->str, ni->len);
|
876
878
|
buf[ni->len] = '\0';
|
877
879
|
rnum = rb_cstr_to_inum(buf, 10, 0);
|
878
|
-
|
880
|
+
OJ_R_FREE(buf);
|
879
881
|
}
|
880
882
|
} else {
|
881
883
|
if (ni->neg) {
|
@@ -1076,12 +1078,12 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
|
|
1076
1078
|
size_t len = lseek(fd, 0, SEEK_END);
|
1077
1079
|
|
1078
1080
|
lseek(fd, 0, SEEK_SET);
|
1079
|
-
buf =
|
1081
|
+
buf = OJ_R_ALLOC_N(char, len + 1);
|
1080
1082
|
pi->json = buf;
|
1081
1083
|
pi->end = buf + len;
|
1082
1084
|
if (0 >= (cnt = read(fd, (char *)pi->json, len)) || cnt != (ssize_t)len) {
|
1083
1085
|
if (0 != buf) {
|
1084
|
-
|
1086
|
+
OJ_R_FREE(buf);
|
1085
1087
|
}
|
1086
1088
|
rb_raise(rb_eIOError, "failed to read from IO Object.");
|
1087
1089
|
}
|
@@ -1163,9 +1165,9 @@ CLEANUP:
|
|
1163
1165
|
oj_circ_array_free(pi->circ_array);
|
1164
1166
|
}
|
1165
1167
|
if (0 != buf) {
|
1166
|
-
|
1168
|
+
OJ_R_FREE(buf);
|
1167
1169
|
} else if (free_json) {
|
1168
|
-
|
1170
|
+
OJ_R_FREE(json);
|
1169
1171
|
}
|
1170
1172
|
stack_cleanup(&pi->stack);
|
1171
1173
|
if (pi->str_rx.head != oj_default_options.str_rx.head) {
|