oj 3.13.23 → 3.16.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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