oj 3.13.23 → 3.16.9

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 +81 -0
  3. data/README.md +2 -2
  4. data/ext/oj/buf.h +7 -6
  5. data/ext/oj/cache.c +29 -26
  6. data/ext/oj/cache.h +3 -2
  7. data/ext/oj/cache8.c +10 -9
  8. data/ext/oj/circarray.c +7 -5
  9. data/ext/oj/circarray.h +2 -2
  10. data/ext/oj/code.c +5 -12
  11. data/ext/oj/code.h +2 -2
  12. data/ext/oj/compat.c +20 -60
  13. data/ext/oj/custom.c +26 -59
  14. data/ext/oj/debug.c +3 -9
  15. data/ext/oj/dump.c +103 -53
  16. data/ext/oj/dump.h +1 -4
  17. data/ext/oj/dump_compat.c +557 -592
  18. data/ext/oj/dump_leaf.c +3 -5
  19. data/ext/oj/dump_object.c +42 -48
  20. data/ext/oj/dump_strict.c +10 -22
  21. data/ext/oj/encoder.c +1 -1
  22. data/ext/oj/err.c +2 -13
  23. data/ext/oj/err.h +9 -12
  24. data/ext/oj/extconf.rb +16 -7
  25. data/ext/oj/fast.c +60 -92
  26. data/ext/oj/intern.c +62 -47
  27. data/ext/oj/intern.h +3 -7
  28. data/ext/oj/mem.c +318 -0
  29. data/ext/oj/mem.h +53 -0
  30. data/ext/oj/mimic_json.c +51 -32
  31. data/ext/oj/object.c +33 -43
  32. data/ext/oj/odd.c +8 -6
  33. data/ext/oj/odd.h +4 -4
  34. data/ext/oj/oj.c +243 -212
  35. data/ext/oj/oj.h +83 -81
  36. data/ext/oj/parse.c +94 -148
  37. data/ext/oj/parse.h +21 -24
  38. data/ext/oj/parser.c +80 -67
  39. data/ext/oj/parser.h +7 -8
  40. data/ext/oj/rails.c +70 -92
  41. data/ext/oj/reader.c +9 -14
  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 +10 -9
  47. data/ext/oj/saj2.c +37 -49
  48. data/ext/oj/saj2.h +1 -1
  49. data/ext/oj/scp.c +3 -14
  50. data/ext/oj/sparse.c +22 -70
  51. data/ext/oj/stream_writer.c +45 -41
  52. data/ext/oj/strict.c +20 -52
  53. data/ext/oj/string_writer.c +64 -38
  54. data/ext/oj/trace.h +31 -4
  55. data/ext/oj/usual.c +125 -114
  56. data/ext/oj/usual.h +7 -6
  57. data/ext/oj/util.h +1 -1
  58. data/ext/oj/val_stack.c +13 -2
  59. data/ext/oj/val_stack.h +8 -7
  60. data/ext/oj/wab.c +25 -57
  61. data/lib/oj/active_support_helper.rb +1 -3
  62. data/lib/oj/bag.rb +7 -1
  63. data/lib/oj/easy_hash.rb +4 -5
  64. data/lib/oj/error.rb +0 -1
  65. data/lib/oj/json.rb +162 -150
  66. data/lib/oj/mimic.rb +7 -7
  67. data/lib/oj/schandler.rb +5 -4
  68. data/lib/oj/state.rb +8 -5
  69. data/lib/oj/version.rb +1 -2
  70. data/lib/oj.rb +2 -0
  71. data/pages/InstallOptions.md +20 -0
  72. data/pages/Options.md +4 -0
  73. data/test/_test_active.rb +8 -9
  74. data/test/_test_active_mimic.rb +7 -8
  75. data/test/_test_mimic_rails.rb +17 -20
  76. data/test/activerecord/result_test.rb +5 -6
  77. data/test/activesupport6/encoding_test.rb +63 -28
  78. data/test/activesupport7/abstract_unit.rb +4 -1
  79. data/test/activesupport7/encoding_test.rb +72 -22
  80. data/test/files.rb +15 -15
  81. data/test/foo.rb +18 -69
  82. data/test/helper.rb +5 -8
  83. data/test/isolated/shared.rb +3 -2
  84. data/test/json_gem/json_addition_test.rb +2 -2
  85. data/test/json_gem/json_common_interface_test.rb +8 -6
  86. data/test/json_gem/json_encoding_test.rb +0 -0
  87. data/test/json_gem/json_ext_parser_test.rb +1 -0
  88. data/test/json_gem/json_fixtures_test.rb +3 -2
  89. data/test/json_gem/json_generator_test.rb +50 -33
  90. data/test/json_gem/json_generic_object_test.rb +11 -11
  91. data/test/json_gem/json_parser_test.rb +46 -46
  92. data/test/json_gem/json_string_matching_test.rb +9 -9
  93. data/test/mem.rb +13 -12
  94. data/test/perf.rb +21 -26
  95. data/test/perf_compat.rb +31 -33
  96. data/test/perf_dump.rb +28 -28
  97. data/test/perf_fast.rb +80 -82
  98. data/test/perf_file.rb +27 -29
  99. data/test/perf_object.rb +65 -69
  100. data/test/perf_once.rb +12 -11
  101. data/test/perf_parser.rb +42 -48
  102. data/test/perf_saj.rb +46 -54
  103. data/test/perf_scp.rb +57 -69
  104. data/test/perf_simple.rb +41 -39
  105. data/test/perf_strict.rb +68 -70
  106. data/test/perf_wab.rb +67 -69
  107. data/test/prec.rb +5 -5
  108. data/test/sample/change.rb +0 -1
  109. data/test/sample/dir.rb +0 -1
  110. data/test/sample/doc.rb +0 -1
  111. data/test/sample/file.rb +0 -1
  112. data/test/sample/group.rb +0 -1
  113. data/test/sample/hasprops.rb +0 -1
  114. data/test/sample/layer.rb +0 -1
  115. data/test/sample/rect.rb +0 -1
  116. data/test/sample/shape.rb +0 -1
  117. data/test/sample/text.rb +0 -1
  118. data/test/sample.rb +16 -16
  119. data/test/sample_json.rb +8 -8
  120. data/test/test_compat.rb +81 -54
  121. data/test/test_custom.rb +63 -52
  122. data/test/test_debian.rb +7 -10
  123. data/test/test_fast.rb +86 -90
  124. data/test/test_file.rb +24 -29
  125. data/test/test_gc.rb +5 -5
  126. data/test/test_generate.rb +5 -5
  127. data/test/test_hash.rb +4 -4
  128. data/test/test_integer_range.rb +9 -9
  129. data/test/test_null.rb +20 -20
  130. data/test/test_object.rb +92 -87
  131. data/test/test_parser.rb +4 -4
  132. data/test/test_parser_debug.rb +5 -5
  133. data/test/test_parser_saj.rb +27 -25
  134. data/test/test_parser_usual.rb +44 -6
  135. data/test/test_rails.rb +2 -2
  136. data/test/test_saj.rb +10 -8
  137. data/test/test_scp.rb +35 -35
  138. data/test/test_strict.rb +38 -32
  139. data/test/test_various.rb +146 -97
  140. data/test/test_wab.rb +46 -44
  141. data/test/test_writer.rb +63 -47
  142. data/test/tests.rb +7 -7
  143. data/test/tests_mimic.rb +6 -6
  144. data/test/tests_mimic_addition.rb +6 -6
  145. metadata +46 -26
  146. data/test/activesupport4/decoding_test.rb +0 -108
  147. data/test/activesupport4/encoding_test.rb +0 -531
  148. data/test/activesupport4/test_helper.rb +0 -41
  149. data/test/activesupport5/abstract_unit.rb +0 -45
  150. data/test/activesupport5/decoding_test.rb +0 -133
  151. data/test/activesupport5/encoding_test.rb +0 -500
  152. data/test/activesupport5/encoding_test_cases.rb +0 -98
  153. data/test/activesupport5/test_helper.rb +0 -72
  154. data/test/activesupport5/time_zone_test_helpers.rb +0 -39
  155. data/test/bar.rb +0 -11
  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
 
@@ -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
- } else if (T_STRING == rb_type(*argv)) {
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 Qnil;
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 = copts->dump_opts.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
- "Oj::Rails.mimic_JSON was called implicitly. "
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
- * Note JSON.generate does support this even if it is not documented.
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
- "Oj::Rails.mimic_JSON was called implicitly. "
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
- * Strings
608
+ * Strings
616
609
  * - *:create_additions* [Boolean] flag indicating a key matching +create_id+ in a JSON object
617
- * should trigger the creation of Ruby Object
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
- xfree((char *)oj_default_options.create_id);
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
- size_t len = RSTRING_LEN(id) + 1;
664
+ const char *ptr = StringValueCStr(id);
665
+ size_t len = RSTRING_LEN(id) + 1;
674
666
 
675
- oj_default_options.create_id = ALLOC_N(char, len);
676
- strcpy((char *)oj_default_options.create_id, StringValuePtr(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 = copts.dump_opts.omit_nil;
766
- copts.mode = CompatMode;
767
- copts.to_json = No;
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
- rb_define_method(rb_cObject, "to_json", mimic_object_to_json, -1);
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