oj 3.13.11 → 3.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +74 -0
  3. data/README.md +4 -2
  4. data/ext/oj/buf.h +11 -6
  5. data/ext/oj/cache.c +25 -24
  6. data/ext/oj/cache8.c +10 -9
  7. data/ext/oj/circarray.c +8 -6
  8. data/ext/oj/circarray.h +2 -2
  9. data/ext/oj/code.c +17 -24
  10. data/ext/oj/code.h +2 -2
  11. data/ext/oj/compat.c +17 -44
  12. data/ext/oj/custom.c +70 -141
  13. data/ext/oj/debug.c +3 -9
  14. data/ext/oj/dump.c +128 -118
  15. data/ext/oj/dump.h +12 -8
  16. data/ext/oj/dump_compat.c +564 -641
  17. data/ext/oj/dump_leaf.c +17 -63
  18. data/ext/oj/dump_object.c +70 -199
  19. data/ext/oj/dump_strict.c +22 -46
  20. data/ext/oj/encoder.c +1 -1
  21. data/ext/oj/err.c +2 -13
  22. data/ext/oj/err.h +9 -12
  23. data/ext/oj/extconf.rb +14 -5
  24. data/ext/oj/fast.c +75 -103
  25. data/ext/oj/intern.c +52 -50
  26. data/ext/oj/intern.h +4 -8
  27. data/ext/oj/mem.c +318 -0
  28. data/ext/oj/mem.h +53 -0
  29. data/ext/oj/mimic_json.c +75 -47
  30. data/ext/oj/object.c +49 -66
  31. data/ext/oj/odd.c +89 -67
  32. data/ext/oj/odd.h +15 -15
  33. data/ext/oj/oj.c +140 -99
  34. data/ext/oj/oj.h +80 -51
  35. data/ext/oj/parse.c +162 -184
  36. data/ext/oj/parse.h +7 -10
  37. data/ext/oj/parser.c +89 -34
  38. data/ext/oj/parser.h +18 -7
  39. data/ext/oj/rails.c +82 -146
  40. data/ext/oj/rails.h +1 -1
  41. data/ext/oj/reader.c +11 -12
  42. data/ext/oj/reader.h +4 -2
  43. data/ext/oj/resolve.c +3 -4
  44. data/ext/oj/rxclass.c +6 -5
  45. data/ext/oj/rxclass.h +1 -1
  46. data/ext/oj/saj.c +20 -31
  47. data/ext/oj/saj2.c +329 -93
  48. data/ext/oj/saj2.h +23 -0
  49. data/ext/oj/scp.c +3 -14
  50. data/ext/oj/sparse.c +26 -70
  51. data/ext/oj/stream_writer.c +12 -22
  52. data/ext/oj/strict.c +20 -52
  53. data/ext/oj/string_writer.c +21 -21
  54. data/ext/oj/trace.h +31 -4
  55. data/ext/oj/usual.c +105 -150
  56. data/ext/oj/usual.h +68 -0
  57. data/ext/oj/util.h +1 -1
  58. data/ext/oj/val_stack.c +1 -1
  59. data/ext/oj/val_stack.h +8 -7
  60. data/ext/oj/validate.c +21 -26
  61. data/ext/oj/wab.c +31 -68
  62. data/lib/oj/active_support_helper.rb +0 -1
  63. data/lib/oj/bag.rb +7 -1
  64. data/lib/oj/easy_hash.rb +4 -5
  65. data/lib/oj/error.rb +0 -1
  66. data/lib/oj/json.rb +4 -2
  67. data/lib/oj/mimic.rb +4 -2
  68. data/lib/oj/saj.rb +20 -6
  69. data/lib/oj/state.rb +9 -6
  70. data/lib/oj/version.rb +1 -2
  71. data/lib/oj.rb +2 -0
  72. data/pages/Compatibility.md +1 -1
  73. data/pages/InstallOptions.md +20 -0
  74. data/pages/Options.md +10 -0
  75. data/test/_test_active.rb +8 -9
  76. data/test/_test_active_mimic.rb +7 -8
  77. data/test/_test_mimic_rails.rb +17 -20
  78. data/test/activerecord/result_test.rb +5 -6
  79. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  80. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  81. data/test/{activesupport5 → activesupport7}/encoding_test.rb +20 -34
  82. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  83. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  84. data/test/files.rb +15 -15
  85. data/test/foo.rb +9 -71
  86. data/test/helper.rb +11 -8
  87. data/test/isolated/shared.rb +3 -2
  88. data/test/json_gem/json_addition_test.rb +2 -2
  89. data/test/json_gem/json_common_interface_test.rb +4 -4
  90. data/test/json_gem/json_encoding_test.rb +0 -0
  91. data/test/json_gem/json_ext_parser_test.rb +1 -0
  92. data/test/json_gem/json_fixtures_test.rb +3 -2
  93. data/test/json_gem/json_generator_test.rb +48 -36
  94. data/test/json_gem/json_generic_object_test.rb +11 -11
  95. data/test/json_gem/json_parser_test.rb +54 -47
  96. data/test/json_gem/json_string_matching_test.rb +9 -9
  97. data/test/json_gem/test_helper.rb +7 -3
  98. data/test/mem.rb +13 -12
  99. data/test/perf.rb +21 -26
  100. data/test/perf_compat.rb +31 -33
  101. data/test/perf_dump.rb +50 -0
  102. data/test/perf_fast.rb +80 -82
  103. data/test/perf_file.rb +27 -29
  104. data/test/perf_object.rb +65 -69
  105. data/test/perf_once.rb +12 -11
  106. data/test/perf_parser.rb +42 -48
  107. data/test/perf_saj.rb +46 -54
  108. data/test/perf_scp.rb +57 -69
  109. data/test/perf_simple.rb +41 -39
  110. data/test/perf_strict.rb +68 -70
  111. data/test/perf_wab.rb +67 -69
  112. data/test/prec.rb +3 -3
  113. data/test/sample/change.rb +0 -1
  114. data/test/sample/dir.rb +0 -1
  115. data/test/sample/doc.rb +0 -1
  116. data/test/sample/file.rb +0 -1
  117. data/test/sample/group.rb +0 -1
  118. data/test/sample/hasprops.rb +0 -1
  119. data/test/sample/layer.rb +0 -1
  120. data/test/sample/rect.rb +0 -1
  121. data/test/sample/shape.rb +0 -1
  122. data/test/sample/text.rb +0 -1
  123. data/test/sample.rb +16 -16
  124. data/test/sample_json.rb +8 -8
  125. data/test/test_compat.rb +76 -42
  126. data/test/test_custom.rb +72 -51
  127. data/test/test_debian.rb +7 -10
  128. data/test/test_fast.rb +86 -90
  129. data/test/test_file.rb +41 -30
  130. data/test/test_gc.rb +16 -5
  131. data/test/test_generate.rb +5 -5
  132. data/test/test_hash.rb +4 -4
  133. data/test/test_integer_range.rb +9 -9
  134. data/test/test_null.rb +20 -20
  135. data/test/test_object.rb +85 -96
  136. data/test/test_parser.rb +6 -22
  137. data/test/test_parser_debug.rb +27 -0
  138. data/test/test_parser_saj.rb +115 -23
  139. data/test/test_parser_usual.rb +6 -6
  140. data/test/test_rails.rb +2 -2
  141. data/test/test_saj.rb +10 -8
  142. data/test/test_scp.rb +37 -39
  143. data/test/test_strict.rb +30 -32
  144. data/test/test_various.rb +147 -99
  145. data/test/test_wab.rb +48 -44
  146. data/test/test_writer.rb +47 -47
  147. data/test/tests.rb +13 -4
  148. data/test/tests_mimic.rb +12 -3
  149. data/test/tests_mimic_addition.rb +12 -3
  150. metadata +33 -144
  151. data/test/activesupport4/decoding_test.rb +0 -108
  152. data/test/activesupport4/encoding_test.rb +0 -531
  153. data/test/activesupport4/test_helper.rb +0 -41
  154. data/test/activesupport5/test_helper.rb +0 -72
  155. data/test/bar.rb +0 -16
  156. data/test/baz.rb +0 -16
  157. data/test/bug.rb +0 -16
  158. 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
- out.buf = buf;
210
- out.end = buf + sizeof(buf) - 10;
211
- out.allocated = false;
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
- if (out.allocated) {
261
- xfree(out.buf);
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
- } else if (T_STRING == rb_type(*argv)) {
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 Qnil;
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
- memset(buf, 0, sizeof(buf));
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.buf = buf;
368
- out.end = buf + sizeof(buf) - 10;
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
- if (out.allocated) {
402
- xfree(out.buf);
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 (1 == argc) {
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
- xfree((char *)oj_default_options.create_id);
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
- size_t len = RSTRING_LEN(id) + 1;
667
+ const char *ptr = StringValueCStr(id);
668
+ size_t len = RSTRING_LEN(id) + 1;
661
669
 
662
- oj_default_options.create_id = ALLOC_N(char, len);
663
- strcpy((char *)oj_default_options.create_id, StringValuePtr(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
- out.buf = buf;
751
- out.end = buf + sizeof(buf) - 10;
752
- out.allocated = false;
753
- out.omit_nil = copts.dump_opts.omit_nil;
754
- copts.mode = CompatMode;
755
- copts.to_json = No;
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
- if (out.allocated) {
769
- xfree(out.buf);
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"));