oj 3.13.23 → 3.16.10

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 (178) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -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 +63 -98
  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 +54 -38
  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 +245 -216
  35. data/ext/oj/oj.h +83 -81
  36. data/ext/oj/parse.c +109 -153
  37. data/ext/oj/parse.h +21 -24
  38. data/ext/oj/parser.c +80 -67
  39. data/ext/oj/parser.h +9 -8
  40. data/ext/oj/rails.c +71 -94
  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 +13 -15
  47. data/ext/oj/saj2.c +37 -49
  48. data/ext/oj/saj2.h +1 -1
  49. data/ext/oj/scp.c +6 -20
  50. data/ext/oj/sparse.c +22 -70
  51. data/ext/oj/stream_writer.c +46 -48
  52. data/ext/oj/strict.c +22 -56
  53. data/ext/oj/string_writer.c +64 -40
  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. metadata +46 -121
  74. data/test/_test_active.rb +0 -76
  75. data/test/_test_active_mimic.rb +0 -96
  76. data/test/_test_mimic_rails.rb +0 -126
  77. data/test/activerecord/result_test.rb +0 -32
  78. data/test/activesupport4/decoding_test.rb +0 -108
  79. data/test/activesupport4/encoding_test.rb +0 -531
  80. data/test/activesupport4/test_helper.rb +0 -41
  81. data/test/activesupport5/abstract_unit.rb +0 -45
  82. data/test/activesupport5/decoding_test.rb +0 -133
  83. data/test/activesupport5/encoding_test.rb +0 -500
  84. data/test/activesupport5/encoding_test_cases.rb +0 -98
  85. data/test/activesupport5/test_helper.rb +0 -72
  86. data/test/activesupport5/time_zone_test_helpers.rb +0 -39
  87. data/test/activesupport6/abstract_unit.rb +0 -44
  88. data/test/activesupport6/decoding_test.rb +0 -133
  89. data/test/activesupport6/encoding_test.rb +0 -507
  90. data/test/activesupport6/encoding_test_cases.rb +0 -98
  91. data/test/activesupport6/test_common.rb +0 -17
  92. data/test/activesupport6/test_helper.rb +0 -163
  93. data/test/activesupport6/time_zone_test_helpers.rb +0 -39
  94. data/test/activesupport7/abstract_unit.rb +0 -49
  95. data/test/activesupport7/decoding_test.rb +0 -125
  96. data/test/activesupport7/encoding_test.rb +0 -486
  97. data/test/activesupport7/encoding_test_cases.rb +0 -104
  98. data/test/activesupport7/time_zone_test_helpers.rb +0 -47
  99. data/test/bar.rb +0 -11
  100. data/test/baz.rb +0 -16
  101. data/test/bug.rb +0 -16
  102. data/test/files.rb +0 -29
  103. data/test/foo.rb +0 -77
  104. data/test/helper.rb +0 -42
  105. data/test/isolated/shared.rb +0 -308
  106. data/test/isolated/test_mimic_after.rb +0 -13
  107. data/test/isolated/test_mimic_alone.rb +0 -12
  108. data/test/isolated/test_mimic_as_json.rb +0 -45
  109. data/test/isolated/test_mimic_before.rb +0 -13
  110. data/test/isolated/test_mimic_define.rb +0 -28
  111. data/test/isolated/test_mimic_rails_after.rb +0 -22
  112. data/test/isolated/test_mimic_rails_before.rb +0 -21
  113. data/test/isolated/test_mimic_redefine.rb +0 -15
  114. data/test/json_gem/json_addition_test.rb +0 -216
  115. data/test/json_gem/json_common_interface_test.rb +0 -153
  116. data/test/json_gem/json_encoding_test.rb +0 -107
  117. data/test/json_gem/json_ext_parser_test.rb +0 -20
  118. data/test/json_gem/json_fixtures_test.rb +0 -35
  119. data/test/json_gem/json_generator_test.rb +0 -396
  120. data/test/json_gem/json_generic_object_test.rb +0 -90
  121. data/test/json_gem/json_parser_test.rb +0 -477
  122. data/test/json_gem/json_string_matching_test.rb +0 -42
  123. data/test/json_gem/test_helper.rb +0 -30
  124. data/test/mem.rb +0 -33
  125. data/test/perf.rb +0 -107
  126. data/test/perf_compat.rb +0 -130
  127. data/test/perf_dump.rb +0 -50
  128. data/test/perf_fast.rb +0 -164
  129. data/test/perf_file.rb +0 -64
  130. data/test/perf_object.rb +0 -138
  131. data/test/perf_once.rb +0 -58
  132. data/test/perf_parser.rb +0 -189
  133. data/test/perf_saj.rb +0 -109
  134. data/test/perf_scp.rb +0 -152
  135. data/test/perf_simple.rb +0 -287
  136. data/test/perf_strict.rb +0 -139
  137. data/test/perf_wab.rb +0 -131
  138. data/test/prec.rb +0 -23
  139. data/test/sample/change.rb +0 -14
  140. data/test/sample/dir.rb +0 -19
  141. data/test/sample/doc.rb +0 -36
  142. data/test/sample/file.rb +0 -48
  143. data/test/sample/group.rb +0 -16
  144. data/test/sample/hasprops.rb +0 -16
  145. data/test/sample/layer.rb +0 -12
  146. data/test/sample/line.rb +0 -20
  147. data/test/sample/oval.rb +0 -10
  148. data/test/sample/rect.rb +0 -10
  149. data/test/sample/shape.rb +0 -35
  150. data/test/sample/text.rb +0 -20
  151. data/test/sample.rb +0 -54
  152. data/test/sample_json.rb +0 -37
  153. data/test/test_compat.rb +0 -540
  154. data/test/test_custom.rb +0 -544
  155. data/test/test_debian.rb +0 -53
  156. data/test/test_fast.rb +0 -530
  157. data/test/test_file.rb +0 -255
  158. data/test/test_gc.rb +0 -60
  159. data/test/test_generate.rb +0 -21
  160. data/test/test_hash.rb +0 -39
  161. data/test/test_integer_range.rb +0 -72
  162. data/test/test_null.rb +0 -376
  163. data/test/test_object.rb +0 -1025
  164. data/test/test_parser.rb +0 -11
  165. data/test/test_parser_debug.rb +0 -27
  166. data/test/test_parser_saj.rb +0 -335
  167. data/test/test_parser_usual.rb +0 -217
  168. data/test/test_rails.rb +0 -35
  169. data/test/test_saj.rb +0 -186
  170. data/test/test_scp.rb +0 -431
  171. data/test/test_strict.rb +0 -435
  172. data/test/test_various.rb +0 -752
  173. data/test/test_wab.rb +0 -309
  174. data/test/test_writer.rb +0 -380
  175. data/test/tests.rb +0 -33
  176. data/test/tests_mimic.rb +0 -23
  177. data/test/tests_mimic_addition.rb +0 -16
  178. 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
 
@@ -246,8 +246,7 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
246
246
  if (0 == out.buf) {
247
247
  rb_raise(rb_eNoMemError, "Not enough memory.");
248
248
  }
249
- rstr = rb_str_new2(out.buf);
250
- rstr = oj_encode(rstr);
249
+ rstr = rb_utf8_str_new_cstr(out.buf);
251
250
  if (2 <= argc && Qnil != argv[1] && rb_respond_to(argv[1], oj_write_id)) {
252
251
  VALUE io = argv[1];
253
252
  VALUE args[1];
@@ -348,12 +347,11 @@ static VALUE mimic_load(int argc, VALUE *argv, VALUE self) {
348
347
  static VALUE mimic_dump_load(int argc, VALUE *argv, VALUE self) {
349
348
  if (1 > argc) {
350
349
  rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
351
- } else if (T_STRING == rb_type(*argv)) {
350
+ }
351
+ if (T_STRING == rb_type(*argv)) {
352
352
  return mimic_load(argc, argv, self);
353
- } else {
354
- return mimic_dump(argc, argv, self);
355
353
  }
356
- return Qnil;
354
+ return mimic_dump(argc, argv, self);
357
355
  }
358
356
 
359
357
  static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
@@ -367,8 +365,7 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
367
365
 
368
366
  oj_out_init(&out);
369
367
 
370
- out.omit_nil = copts->dump_opts.omit_nil;
371
- out.caller = CALLER_GENERATE;
368
+ out.omit_nil = copts->dump_opts.omit_nil;
372
369
  // For obj.to_json or generate nan is not allowed but if called from dump
373
370
  // it is.
374
371
  copts->dump_opts.nan_dump = RaiseNan;
@@ -388,10 +385,8 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
388
385
  VALUE active_hack[1];
389
386
 
390
387
  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
- );
388
+ rb_warn("Oj::Rails.mimic_JSON was called implicitly. "
389
+ "Call it explicitly beforehand if you want to remove this warning.");
395
390
  oj_define_mimic_json(0, NULL, Qnil);
396
391
  }
397
392
  active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
@@ -400,8 +395,7 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
400
395
  if (0 == out.buf) {
401
396
  rb_raise(rb_eNoMemError, "Not enough memory.");
402
397
  }
403
- rstr = rb_str_new2(out.buf);
404
- rstr = oj_encode(rstr);
398
+ rstr = rb_utf8_str_new_cstr(out.buf);
405
399
 
406
400
  oj_out_free(&out);
407
401
 
@@ -429,7 +423,7 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
429
423
  * - *:object_nl* [_String_] String placed after a JSON object
430
424
  * - *:array_nl* [_String_] String placed after a JSON array
431
425
  * - *: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.
426
+ * Note JSON.generate does support this even if it is not documented.
433
427
  *
434
428
  * Returns [_String_] generated JSON.
435
429
  */
@@ -466,7 +460,7 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
466
460
  }
467
461
  if (1 == argc || Qnil == argv[1]) {
468
462
  h = rb_hash_new();
469
- } else {
463
+ } else {
470
464
  h = argv[1];
471
465
  }
472
466
  if (!oj_hash_has_key(h, oj_indent_sym)) {
@@ -485,10 +479,8 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
485
479
  rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
486
480
  }
487
481
  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
- );
482
+ rb_warn("Oj::Rails.mimic_JSON was called implicitly. "
483
+ "Call it explicitly beforehand if you want to remove this warning.");
492
484
  oj_define_mimic_json(0, NULL, Qnil);
493
485
  }
494
486
  rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
@@ -578,7 +570,6 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
578
570
  if (T_HASH != rb_type(ropts)) {
579
571
  rb_raise(rb_eArgError, "options must be a hash.");
580
572
  }
581
-
582
573
  rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
583
574
  v = rb_hash_lookup(ropts, oj_max_nesting_sym);
584
575
  if (Qtrue == v) {
@@ -612,9 +603,9 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
612
603
  * - *source* [_String_|IO] source to parse
613
604
  * - *opts* [_Hash_] options
614
605
  * - *:symbolize* [Boolean] _names flag indicating JSON object keys should be Symbols instead of
615
- * Strings
606
+ * Strings
616
607
  * - *:create_additions* [Boolean] flag indicating a key matching +create_id+ in a JSON object
617
- * should trigger the creation of Ruby Object
608
+ * should trigger the creation of Ruby Object
618
609
  *
619
610
  * Returns [Object]
620
611
  * @see create_id=
@@ -657,23 +648,22 @@ static VALUE mimic_recurse_proc(VALUE self, VALUE obj) {
657
648
  *
658
649
  * - *id* [_nil_|String] new create_id
659
650
  *
660
- * Returns [_String_] the id.
651
+ * Returns [_nil_|_String_] the id.
661
652
  */
662
653
  static VALUE mimic_set_create_id(VALUE self, VALUE id) {
663
- Check_Type(id, T_STRING);
664
-
665
654
  if (NULL != oj_default_options.create_id) {
666
655
  if (oj_json_class != oj_default_options.create_id) {
667
- xfree((char *)oj_default_options.create_id);
656
+ OJ_R_FREE((char *)oj_default_options.create_id);
668
657
  }
669
658
  oj_default_options.create_id = NULL;
670
659
  oj_default_options.create_id_len = 0;
671
660
  }
672
661
  if (Qnil != id) {
673
- size_t len = RSTRING_LEN(id) + 1;
662
+ const char *ptr = StringValueCStr(id);
663
+ size_t len = RSTRING_LEN(id) + 1;
674
664
 
675
- oj_default_options.create_id = ALLOC_N(char, len);
676
- strcpy((char *)oj_default_options.create_id, StringValuePtr(id));
665
+ oj_default_options.create_id = OJ_R_ALLOC_N(char, len);
666
+ strcpy((char *)oj_default_options.create_id, ptr);
677
667
  oj_default_options.create_id_len = len - 1;
678
668
  }
679
669
  return id;
@@ -743,6 +733,7 @@ static struct _options mimic_object_to_json_options = {0, // indent
743
733
  0, // array_size
744
734
  RaiseNan, // nan_dump
745
735
  false, // omit_nil
736
+ false, // omit_null_byte
746
737
  100, // max_depth
747
738
  },
748
739
  {
@@ -762,9 +753,9 @@ static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
762
753
 
763
754
  oj_out_init(&out);
764
755
 
765
- out.omit_nil = copts.dump_opts.omit_nil;
766
- copts.mode = CompatMode;
767
- copts.to_json = No;
756
+ out.omit_nil = copts.dump_opts.omit_nil;
757
+ copts.mode = CompatMode;
758
+ copts.to_json = No;
768
759
  if (1 <= argc && Qnil != argv[0]) {
769
760
  oj_parse_mimic_dump_options(argv[0], &copts);
770
761
  }
@@ -775,8 +766,7 @@ static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
775
766
  if (NULL == out.buf) {
776
767
  rb_raise(rb_eNoMemError, "Not enough memory.");
777
768
  }
778
- rstr = rb_str_new2(out.buf);
779
- rstr = oj_encode(rstr);
769
+ rstr = rb_utf8_str_new_cstr(out.buf);
780
770
 
781
771
  oj_out_free(&out);
782
772
 
@@ -796,39 +786,63 @@ void oj_mimic_json_methods(VALUE json) {
796
786
  VALUE json_error;
797
787
  VALUE generator;
798
788
  VALUE ext;
789
+ VALUE verbose;
799
790
 
791
+ // rb_undef_method doesn't work for modules or maybe sometimes
792
+ // doesn't. Anyway setting verbose should hide the warning.
793
+ verbose = rb_gv_get("$VERBOSE");
794
+ rb_gv_set("$VERBOSE", Qfalse);
795
+
796
+ rb_undef_method(json, "create_id=");
800
797
  rb_define_module_function(json, "create_id=", mimic_set_create_id, 1);
798
+ rb_undef_method(json, "create_id");
801
799
  rb_define_module_function(json, "create_id", mimic_create_id, 0);
802
800
 
801
+ rb_undef_method(json, "dump");
803
802
  rb_define_module_function(json, "dump", mimic_dump, -1);
803
+ rb_undef_method(json, "load");
804
804
  rb_define_module_function(json, "load", mimic_load, -1);
805
805
  rb_define_module_function(json, "restore", mimic_load, -1);
806
+ rb_undef_method(json, "recurse_proc");
806
807
  rb_define_module_function(json, "recurse_proc", mimic_recurse_proc, 1);
808
+ rb_undef_method(json, "[]");
807
809
  rb_define_module_function(json, "[]", mimic_dump_load, -1);
808
810
 
811
+ rb_undef_method(json, "generate");
809
812
  rb_define_module_function(json, "generate", oj_mimic_generate, -1);
813
+ rb_undef_method(json, "fast_generate");
810
814
  rb_define_module_function(json, "fast_generate", oj_mimic_generate, -1);
815
+ rb_undef_method(json, "pretty_generate");
811
816
  rb_define_module_function(json, "pretty_generate", oj_mimic_pretty_generate, -1);
812
817
  // For older versions of JSON, the deprecated unparse methods.
818
+ rb_undef_method(json, "unparse");
813
819
  rb_define_module_function(json, "unparse", oj_mimic_generate, -1);
814
820
  rb_define_module_function(json, "fast_unparse", oj_mimic_generate, -1);
815
821
  rb_define_module_function(json, "pretty_unparse", oj_mimic_pretty_generate, -1);
816
822
 
823
+ rb_undef_method(json, "parse");
817
824
  rb_define_module_function(json, "parse", oj_mimic_parse, -1);
825
+ rb_undef_method(json, "parse!");
818
826
  rb_define_module_function(json, "parse!", mimic_parse_bang, -1);
819
827
 
828
+ rb_undef_method(json, "state");
820
829
  rb_define_module_function(json, "state", mimic_state, 0);
830
+ rb_gv_set("$VERBOSE", verbose);
821
831
 
822
832
  if (rb_const_defined_at(json, rb_intern("JSONError"))) {
823
833
  json_error = rb_const_get(json, rb_intern("JSONError"));
824
834
  } else {
825
835
  json_error = rb_define_class_under(json, "JSONError", rb_eStandardError);
826
836
  }
837
+
838
+ rb_global_variable(&oj_json_parser_error_class);
827
839
  if (rb_const_defined_at(json, rb_intern("ParserError"))) {
828
840
  oj_json_parser_error_class = rb_const_get(json, rb_intern("ParserError"));
829
841
  } else {
830
842
  oj_json_parser_error_class = rb_define_class_under(json, "ParserError", json_error);
831
843
  }
844
+
845
+ rb_global_variable(&oj_json_generator_error_class);
832
846
  if (rb_const_defined_at(json, rb_intern("GeneratorError"))) {
833
847
  oj_json_generator_error_class = rb_const_get(json, rb_intern("GeneratorError"));
834
848
  } else {
@@ -854,8 +868,8 @@ void oj_mimic_json_methods(VALUE json) {
854
868
  rb_require("oj/state");
855
869
  }
856
870
  // Pull in the JSON::State mimic file.
871
+ rb_global_variable(&state_class);
857
872
  state_class = rb_const_get_at(generator, rb_intern("State"));
858
- rb_gc_register_mark_object(state_class);
859
873
  }
860
874
 
861
875
  /* Document-module: JSON
@@ -892,7 +906,9 @@ oj_define_mimic_json(int argc, VALUE *argv, VALUE self) {
892
906
  }
893
907
  oj_mimic_json_methods(json);
894
908
 
895
- rb_define_method(rb_cObject, "to_json", mimic_object_to_json, -1);
909
+ if (!rb_const_defined(rb_cObject, rb_intern("ActiveSupport"))) {
910
+ rb_define_method(rb_cObject, "to_json", mimic_object_to_json, -1);
911
+ }
896
912
 
897
913
  rb_gv_set("$VERBOSE", verbose);
898
914