oj 3.13.9 → 3.13.12
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +9 -0
- data/ext/oj/circarray.c +1 -1
- data/ext/oj/code.c +15 -22
- data/ext/oj/custom.c +32 -59
- data/ext/oj/dump.c +129 -175
- data/ext/oj/dump.h +25 -8
- data/ext/oj/dump_compat.c +44 -81
- data/ext/oj/dump_leaf.c +14 -58
- data/ext/oj/dump_object.c +68 -129
- data/ext/oj/dump_strict.c +14 -26
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/fast.c +15 -9
- data/ext/oj/intern.c +9 -2
- data/ext/oj/intern.h +1 -1
- data/ext/oj/mimic_json.c +73 -73
- data/ext/oj/object.c +1 -1
- data/ext/oj/odd.c +83 -63
- data/ext/oj/odd.h +13 -13
- data/ext/oj/oj.c +29 -17
- data/ext/oj/oj.h +20 -2
- data/ext/oj/parse.c +3 -2
- data/ext/oj/parser.c +10 -15
- data/ext/oj/rails.c +43 -62
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +2 -0
- data/ext/oj/saj.c +11 -23
- data/ext/oj/stream_writer.c +3 -1
- data/ext/oj/string_writer.c +12 -5
- data/ext/oj/wab.c +9 -9
- data/lib/oj/version.rb +1 -1
- data/pages/JsonGem.md +15 -0
- data/pages/Modes.md +6 -3
- data/pages/Rails.md +12 -0
- data/test/bar.rb +1 -8
- data/test/foo.rb +70 -13
- data/test/perf_dump.rb +50 -0
- data/test/test_fast.rb +19 -0
- data/test/test_object.rb +12 -7
- data/test/test_saj.rb +1 -1
- data/test/test_various.rb +27 -2
- data/test/tests.rb +0 -1
- metadata +6 -3
data/ext/oj/dump_object.c
CHANGED
@@ -24,12 +24,7 @@ static void dump_data(VALUE obj, int depth, Out out, bool as_ok) {
|
|
24
24
|
|
25
25
|
if (rb_cTime == clas) {
|
26
26
|
assure_size(out, 6);
|
27
|
-
|
28
|
-
*out->cur++ = '"';
|
29
|
-
*out->cur++ = '^';
|
30
|
-
*out->cur++ = 't';
|
31
|
-
*out->cur++ = '"';
|
32
|
-
*out->cur++ = ':';
|
27
|
+
APPEND_CHARS(out->cur, "{\"^t\":", 6);
|
33
28
|
dump_time(obj, out);
|
34
29
|
*out->cur++ = '}';
|
35
30
|
*out->cur = '\0';
|
@@ -91,12 +86,7 @@ static void dump_class(VALUE obj, int depth, Out out, bool as_ok) {
|
|
91
86
|
size_t len = strlen(s);
|
92
87
|
|
93
88
|
assure_size(out, 6);
|
94
|
-
|
95
|
-
*out->cur++ = '"';
|
96
|
-
*out->cur++ = '^';
|
97
|
-
*out->cur++ = 'c';
|
98
|
-
*out->cur++ = '"';
|
99
|
-
*out->cur++ = ':';
|
89
|
+
APPEND_CHARS(out->cur, "{\"^c\":", 6);
|
100
90
|
oj_dump_cstr(s, len, 0, 0, out);
|
101
91
|
*out->cur++ = '}';
|
102
92
|
*out->cur = '\0';
|
@@ -120,9 +110,7 @@ static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
|
|
120
110
|
if (0 < id) {
|
121
111
|
assure_size(out, d2 * out->indent + 16);
|
122
112
|
fill_indent(out, d2);
|
123
|
-
|
124
|
-
*out->cur++ = '^';
|
125
|
-
*out->cur++ = 'i';
|
113
|
+
APPEND_CHARS(out->cur, "\"^i", 3);
|
126
114
|
dump_ulong(id, out);
|
127
115
|
*out->cur++ = '"';
|
128
116
|
}
|
@@ -139,25 +127,23 @@ static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
|
|
139
127
|
} else {
|
140
128
|
size = d2 * out->indent + 2;
|
141
129
|
}
|
130
|
+
assure_size(out, size * cnt);
|
142
131
|
cnt--;
|
143
132
|
for (i = 0; i <= cnt; i++) {
|
144
|
-
assure_size(out, size);
|
145
133
|
if (out->opts->dump_opts.use) {
|
146
134
|
if (0 < out->opts->dump_opts.array_size) {
|
147
|
-
|
148
|
-
out->cur += out->opts->dump_opts.array_size;
|
135
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
149
136
|
}
|
150
137
|
if (0 < out->opts->dump_opts.indent_size) {
|
151
138
|
int i;
|
152
139
|
for (i = d2; 0 < i; i--) {
|
153
|
-
|
154
|
-
out->cur += out->opts->dump_opts.indent_size;
|
140
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
155
141
|
}
|
156
142
|
}
|
157
143
|
} else {
|
158
144
|
fill_indent(out, d2);
|
159
145
|
}
|
160
|
-
oj_dump_obj_val(
|
146
|
+
oj_dump_obj_val(RARRAY_AREF(a, i), d2, out);
|
161
147
|
if (i < cnt) {
|
162
148
|
*out->cur++ = ',';
|
163
149
|
}
|
@@ -168,15 +154,13 @@ static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
|
|
168
154
|
// printf("*** d2: %u indent: %u '%s'\n", d2, out->opts->dump_opts->indent_size,
|
169
155
|
// out->opts->dump_opts->indent);
|
170
156
|
if (0 < out->opts->dump_opts.array_size) {
|
171
|
-
|
172
|
-
out->cur += out->opts->dump_opts.array_size;
|
157
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
173
158
|
}
|
174
159
|
if (0 < out->opts->dump_opts.indent_size) {
|
175
160
|
int i;
|
176
161
|
|
177
162
|
for (i = depth; 0 < i; i--) {
|
178
|
-
|
179
|
-
out->cur += out->opts->dump_opts.indent_size;
|
163
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
180
164
|
}
|
181
165
|
}
|
182
166
|
} else {
|
@@ -218,7 +202,7 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
218
202
|
int depth = out->depth;
|
219
203
|
long size = depth * out->indent + 1;
|
220
204
|
|
221
|
-
if (
|
205
|
+
if (dump_ignore(out->opts, value)) {
|
222
206
|
return ST_CONTINUE;
|
223
207
|
}
|
224
208
|
if (out->omit_nil && Qnil == value) {
|
@@ -226,47 +210,50 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
226
210
|
}
|
227
211
|
assure_size(out, size);
|
228
212
|
fill_indent(out, depth);
|
229
|
-
|
213
|
+
switch (rb_type(key)) {
|
214
|
+
case T_STRING:
|
230
215
|
dump_str_class(key, Qundef, depth, out);
|
231
216
|
*out->cur++ = ':';
|
232
217
|
oj_dump_obj_val(value, depth, out);
|
233
|
-
|
218
|
+
break;
|
219
|
+
|
220
|
+
case T_SYMBOL:
|
234
221
|
dump_sym(key, 0, out, false);
|
235
222
|
*out->cur++ = ':';
|
236
223
|
oj_dump_obj_val(value, depth, out);
|
237
|
-
|
238
|
-
int d2 = depth + 1;
|
239
|
-
long s2 = size + out->indent + 1;
|
240
|
-
int i;
|
241
|
-
int started = 0;
|
242
|
-
uint8_t b;
|
224
|
+
break;
|
243
225
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
226
|
+
default:
|
227
|
+
{
|
228
|
+
int d2 = depth + 1;
|
229
|
+
long s2 = size + out->indent + 1;
|
230
|
+
int i;
|
231
|
+
int started = 0;
|
232
|
+
uint8_t b;
|
233
|
+
|
234
|
+
assure_size(out, s2 + 15);
|
235
|
+
APPEND_CHARS(out->cur, "\"^#", 3);
|
236
|
+
out->hash_cnt++;
|
237
|
+
for (i = 28; 0 <= i; i -= 4) {
|
238
|
+
b = (uint8_t)((out->hash_cnt >> i) & 0x0000000F);
|
239
|
+
if ('\0' != b) {
|
240
|
+
started = 1;
|
241
|
+
}
|
242
|
+
if (started) {
|
243
|
+
*out->cur++ = hex_chars[b];
|
244
|
+
}
|
256
245
|
}
|
246
|
+
APPEND_CHARS(out->cur, "\":[", 3);
|
247
|
+
fill_indent(out, d2);
|
248
|
+
oj_dump_obj_val(key, d2, out);
|
249
|
+
assure_size(out, s2);
|
250
|
+
*out->cur++ = ',';
|
251
|
+
fill_indent(out, d2);
|
252
|
+
oj_dump_obj_val(value, d2, out);
|
253
|
+
assure_size(out, size);
|
254
|
+
fill_indent(out, depth);
|
255
|
+
*out->cur++ = ']';
|
257
256
|
}
|
258
|
-
*out->cur++ = '"';
|
259
|
-
*out->cur++ = ':';
|
260
|
-
*out->cur++ = '[';
|
261
|
-
fill_indent(out, d2);
|
262
|
-
oj_dump_obj_val(key, d2, out);
|
263
|
-
assure_size(out, s2);
|
264
|
-
*out->cur++ = ',';
|
265
|
-
fill_indent(out, d2);
|
266
|
-
oj_dump_obj_val(value, d2, out);
|
267
|
-
assure_size(out, size);
|
268
|
-
fill_indent(out, depth);
|
269
|
-
*out->cur++ = ']';
|
270
257
|
}
|
271
258
|
out->depth = depth;
|
272
259
|
*out->cur++ = ',';
|
@@ -286,8 +273,7 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
|
|
286
273
|
size = depth * out->indent + 2;
|
287
274
|
assure_size(out, 2);
|
288
275
|
if (0 == cnt) {
|
289
|
-
|
290
|
-
*out->cur++ = '}';
|
276
|
+
APPEND_CHARS(out->cur, "{}", 2);
|
291
277
|
} else {
|
292
278
|
long id = oj_check_circular(obj, out);
|
293
279
|
|
@@ -298,11 +284,7 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
|
|
298
284
|
if (0 < id) {
|
299
285
|
assure_size(out, size + 16);
|
300
286
|
fill_indent(out, depth + 1);
|
301
|
-
|
302
|
-
*out->cur++ = '^';
|
303
|
-
*out->cur++ = 'i';
|
304
|
-
*out->cur++ = '"';
|
305
|
-
*out->cur++ = ':';
|
287
|
+
APPEND_CHARS(out->cur, "\"^i\":", 5);
|
306
288
|
dump_ulong(id, out);
|
307
289
|
*out->cur++ = ',';
|
308
290
|
}
|
@@ -318,15 +300,13 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
|
|
318
300
|
size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
|
319
301
|
assure_size(out, size);
|
320
302
|
if (0 < out->opts->dump_opts.hash_size) {
|
321
|
-
|
322
|
-
out->cur += out->opts->dump_opts.hash_size;
|
303
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
|
323
304
|
}
|
324
305
|
if (0 < out->opts->dump_opts.indent_size) {
|
325
306
|
int i;
|
326
307
|
|
327
308
|
for (i = depth; 0 < i; i--) {
|
328
|
-
|
329
|
-
out->cur += out->opts->dump_opts.indent_size;
|
309
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
330
310
|
}
|
331
311
|
}
|
332
312
|
}
|
@@ -342,7 +322,7 @@ static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
|
|
342
322
|
size_t size = depth * out->indent + 1;
|
343
323
|
const char *attr = rb_id2name(key);
|
344
324
|
|
345
|
-
if (
|
325
|
+
if (dump_ignore(out->opts, value)) {
|
346
326
|
return ST_CONTINUE;
|
347
327
|
}
|
348
328
|
if (out->omit_nil && Qnil == value) {
|
@@ -401,11 +381,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
401
381
|
size = d2 * out->indent + clen + 10;
|
402
382
|
assure_size(out, size);
|
403
383
|
fill_indent(out, d2);
|
404
|
-
|
405
|
-
*out->cur++ = '^';
|
406
|
-
*out->cur++ = 'O';
|
407
|
-
*out->cur++ = '"';
|
408
|
-
*out->cur++ = ':';
|
384
|
+
APPEND_CHARS(out->cur, "\"^O\":", 5);
|
409
385
|
oj_dump_cstr(class_name, clen, 0, 0, out);
|
410
386
|
*out->cur++ = ',';
|
411
387
|
}
|
@@ -423,12 +399,9 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
423
399
|
assure_size(out, size);
|
424
400
|
fill_indent(out, d2);
|
425
401
|
*out->cur++ = '"';
|
426
|
-
|
427
|
-
out->cur
|
428
|
-
|
429
|
-
*out->cur++ = ':';
|
430
|
-
memcpy(out->cur, s, len);
|
431
|
-
out->cur += len;
|
402
|
+
APPEND_CHARS(out->cur, name, nlen);
|
403
|
+
APPEND_CHARS(out->cur, "\":", 2);
|
404
|
+
APPEND_CHARS(out->cur, s, len);
|
432
405
|
*out->cur = '\0';
|
433
406
|
}
|
434
407
|
} else {
|
@@ -439,7 +412,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
439
412
|
assure_size(out, size);
|
440
413
|
name = rb_id2name(*idp);
|
441
414
|
nlen = strlen(name);
|
442
|
-
if (
|
415
|
+
if (NULL != *fp) {
|
443
416
|
v = (*fp)(obj);
|
444
417
|
} else if (0 == strchr(name, '.')) {
|
445
418
|
v = rb_funcall(obj, *idp, 0);
|
@@ -502,22 +475,14 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
|
|
502
475
|
|
503
476
|
assure_size(out, d2 * out->indent + clen + 10);
|
504
477
|
fill_indent(out, d2);
|
505
|
-
|
506
|
-
*out->cur++ = '^';
|
507
|
-
*out->cur++ = 'o';
|
508
|
-
*out->cur++ = '"';
|
509
|
-
*out->cur++ = ':';
|
478
|
+
APPEND_CHARS(out->cur, "\"^o\":", 5);
|
510
479
|
oj_dump_cstr(class_name, clen, 0, 0, out);
|
511
480
|
}
|
512
481
|
if (0 < id) {
|
513
482
|
assure_size(out, d2 * out->indent + 16);
|
514
483
|
*out->cur++ = ',';
|
515
484
|
fill_indent(out, d2);
|
516
|
-
|
517
|
-
*out->cur++ = '^';
|
518
|
-
*out->cur++ = 'i';
|
519
|
-
*out->cur++ = '"';
|
520
|
-
*out->cur++ = ':';
|
485
|
+
APPEND_CHARS(out->cur, "\"^i\":", 5);
|
521
486
|
dump_ulong(id, out);
|
522
487
|
}
|
523
488
|
switch (type) {
|
@@ -525,39 +490,21 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
|
|
525
490
|
assure_size(out, d2 * out->indent + 14);
|
526
491
|
*out->cur++ = ',';
|
527
492
|
fill_indent(out, d2);
|
528
|
-
|
529
|
-
*out->cur++ = 's';
|
530
|
-
*out->cur++ = 'e';
|
531
|
-
*out->cur++ = 'l';
|
532
|
-
*out->cur++ = 'f';
|
533
|
-
*out->cur++ = '"';
|
534
|
-
*out->cur++ = ':';
|
493
|
+
APPEND_CHARS(out->cur, "\"self\":", 7);
|
535
494
|
oj_dump_cstr(RSTRING_PTR(obj), (int)RSTRING_LEN(obj), 0, 0, out);
|
536
495
|
break;
|
537
496
|
case T_ARRAY:
|
538
497
|
assure_size(out, d2 * out->indent + 14);
|
539
498
|
*out->cur++ = ',';
|
540
499
|
fill_indent(out, d2);
|
541
|
-
|
542
|
-
*out->cur++ = 's';
|
543
|
-
*out->cur++ = 'e';
|
544
|
-
*out->cur++ = 'l';
|
545
|
-
*out->cur++ = 'f';
|
546
|
-
*out->cur++ = '"';
|
547
|
-
*out->cur++ = ':';
|
500
|
+
APPEND_CHARS(out->cur, "\"self\":", 7);
|
548
501
|
dump_array_class(obj, Qundef, depth + 1, out);
|
549
502
|
break;
|
550
503
|
case T_HASH:
|
551
504
|
assure_size(out, d2 * out->indent + 14);
|
552
505
|
*out->cur++ = ',';
|
553
506
|
fill_indent(out, d2);
|
554
|
-
|
555
|
-
*out->cur++ = 's';
|
556
|
-
*out->cur++ = 'e';
|
557
|
-
*out->cur++ = 'l';
|
558
|
-
*out->cur++ = 'f';
|
559
|
-
*out->cur++ = '"';
|
560
|
-
*out->cur++ = ':';
|
507
|
+
APPEND_CHARS(out->cur, "\"self\":", 7);
|
561
508
|
dump_hash_class(obj, Qundef, depth + 1, out);
|
562
509
|
break;
|
563
510
|
default: break;
|
@@ -605,7 +552,7 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
|
|
605
552
|
}
|
606
553
|
value = rb_ivar_get(obj, vid);
|
607
554
|
|
608
|
-
if (
|
555
|
+
if (dump_ignore(out->opts, value)) {
|
609
556
|
continue;
|
610
557
|
}
|
611
558
|
if (out->omit_nil && Qnil == value) {
|
@@ -681,12 +628,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
681
628
|
assure_size(out, size);
|
682
629
|
*out->cur++ = '{';
|
683
630
|
fill_indent(out, d2);
|
684
|
-
|
685
|
-
*out->cur++ = '^';
|
686
|
-
*out->cur++ = 'u';
|
687
|
-
*out->cur++ = '"';
|
688
|
-
*out->cur++ = ':';
|
689
|
-
*out->cur++ = '[';
|
631
|
+
APPEND_CHARS(out->cur, "\"^u\":[", 6);
|
690
632
|
if ('#' == *class_name) {
|
691
633
|
VALUE ma = rb_struct_s_members(clas);
|
692
634
|
const char *name;
|
@@ -694,7 +636,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
694
636
|
|
695
637
|
*out->cur++ = '[';
|
696
638
|
for (i = 0; i < cnt; i++) {
|
697
|
-
volatile VALUE s = rb_sym2str(
|
639
|
+
volatile VALUE s = rb_sym2str(RARRAY_AREF(ma, i));
|
698
640
|
|
699
641
|
name = RSTRING_PTR(s);
|
700
642
|
len = (int)RSTRING_LEN(s);
|
@@ -704,16 +646,14 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
704
646
|
*out->cur++ = ',';
|
705
647
|
}
|
706
648
|
*out->cur++ = '"';
|
707
|
-
|
708
|
-
out->cur += len;
|
649
|
+
APPEND_CHARS(out->cur, name, len);
|
709
650
|
*out->cur++ = '"';
|
710
651
|
}
|
711
652
|
*out->cur++ = ']';
|
712
653
|
} else {
|
713
654
|
fill_indent(out, d3);
|
714
655
|
*out->cur++ = '"';
|
715
|
-
|
716
|
-
out->cur += len;
|
656
|
+
APPEND_CHARS(out->cur, class_name, len);
|
717
657
|
*out->cur++ = '"';
|
718
658
|
}
|
719
659
|
*out->cur++ = ',';
|
@@ -730,7 +670,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
730
670
|
|
731
671
|
for (i = 0; i < cnt; i++) {
|
732
672
|
v = RSTRUCT_GET(obj, i);
|
733
|
-
if (
|
673
|
+
if (dump_ignore(out->opts, v)) {
|
734
674
|
v = Qnil;
|
735
675
|
}
|
736
676
|
assure_size(out, size);
|
@@ -748,7 +688,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
748
688
|
for (i = 0; i < slen; i++) {
|
749
689
|
assure_size(out, size);
|
750
690
|
fill_indent(out, d3);
|
751
|
-
if (
|
691
|
+
if (dump_ignore(out->opts, v)) {
|
752
692
|
v = Qnil;
|
753
693
|
}
|
754
694
|
oj_dump_obj_val(rb_struct_aref(obj, INT2FIX(i)), d3, out, 0, 0, true);
|
@@ -757,8 +697,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
757
697
|
}
|
758
698
|
#endif
|
759
699
|
out->cur--;
|
760
|
-
|
761
|
-
*out->cur++ = '}';
|
700
|
+
APPEND_CHARS(out->cur, "]}", 2);
|
762
701
|
*out->cur = '\0';
|
763
702
|
}
|
764
703
|
|
data/ext/oj/dump_strict.c
CHANGED
@@ -105,9 +105,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
105
105
|
}
|
106
106
|
}
|
107
107
|
assure_size(out, cnt);
|
108
|
-
|
109
|
-
*out->cur++ = *b;
|
110
|
-
}
|
108
|
+
APPEND_CHARS(out->cur, buf, cnt);
|
111
109
|
*out->cur = '\0';
|
112
110
|
}
|
113
111
|
|
@@ -134,28 +132,26 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
134
132
|
} else {
|
135
133
|
size = d2 * out->indent + 2;
|
136
134
|
}
|
135
|
+
assure_size(out, size * cnt);
|
137
136
|
cnt--;
|
138
137
|
for (i = 0; i <= cnt; i++) {
|
139
|
-
assure_size(out, size);
|
140
138
|
if (out->opts->dump_opts.use) {
|
141
139
|
if (0 < out->opts->dump_opts.array_size) {
|
142
|
-
|
143
|
-
out->cur += out->opts->dump_opts.array_size;
|
140
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
144
141
|
}
|
145
142
|
if (0 < out->opts->dump_opts.indent_size) {
|
146
143
|
int i;
|
147
144
|
for (i = d2; 0 < i; i--) {
|
148
|
-
|
149
|
-
out->cur += out->opts->dump_opts.indent_size;
|
145
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
150
146
|
}
|
151
147
|
}
|
152
148
|
} else {
|
153
149
|
fill_indent(out, d2);
|
154
150
|
}
|
155
151
|
if (NullMode == out->opts->mode) {
|
156
|
-
oj_dump_null_val(
|
152
|
+
oj_dump_null_val(RARRAY_AREF(a, i), d2, out);
|
157
153
|
} else {
|
158
|
-
oj_dump_strict_val(
|
154
|
+
oj_dump_strict_val(RARRAY_AREF(a, i), d2, out);
|
159
155
|
}
|
160
156
|
if (i < cnt) {
|
161
157
|
*out->cur++ = ',';
|
@@ -167,15 +163,13 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
167
163
|
// printf("*** d2: %u indent: %u '%s'\n", d2, out->opts->dump_opts->indent_size,
|
168
164
|
// out->opts->dump_opts->indent);
|
169
165
|
if (0 < out->opts->dump_opts.array_size) {
|
170
|
-
|
171
|
-
out->cur += out->opts->dump_opts.array_size;
|
166
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
172
167
|
}
|
173
168
|
if (0 < out->opts->dump_opts.indent_size) {
|
174
169
|
int i;
|
175
170
|
|
176
171
|
for (i = depth; 0 < i; i--) {
|
177
|
-
|
178
|
-
out->cur += out->opts->dump_opts.indent_size;
|
172
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
179
173
|
}
|
180
174
|
}
|
181
175
|
} else {
|
@@ -214,14 +208,12 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
214
208
|
size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
|
215
209
|
assure_size(out, size);
|
216
210
|
if (0 < out->opts->dump_opts.hash_size) {
|
217
|
-
|
218
|
-
out->cur += out->opts->dump_opts.hash_size;
|
211
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
|
219
212
|
}
|
220
213
|
if (0 < out->opts->dump_opts.indent_size) {
|
221
214
|
int i;
|
222
215
|
for (i = depth; 0 < i; i--) {
|
223
|
-
|
224
|
-
out->cur += out->opts->dump_opts.indent_size;
|
216
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
225
217
|
}
|
226
218
|
}
|
227
219
|
if (rtype == T_STRING) {
|
@@ -232,13 +224,11 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
232
224
|
size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
|
233
225
|
assure_size(out, size);
|
234
226
|
if (0 < out->opts->dump_opts.before_size) {
|
235
|
-
|
236
|
-
out->cur += out->opts->dump_opts.before_size;
|
227
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
|
237
228
|
}
|
238
229
|
*out->cur++ = ':';
|
239
230
|
if (0 < out->opts->dump_opts.after_size) {
|
240
|
-
|
241
|
-
out->cur += out->opts->dump_opts.after_size;
|
231
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
|
242
232
|
}
|
243
233
|
}
|
244
234
|
if (NullMode == out->opts->mode) {
|
@@ -281,15 +271,13 @@ static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
|
|
281
271
|
size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
|
282
272
|
assure_size(out, size);
|
283
273
|
if (0 < out->opts->dump_opts.hash_size) {
|
284
|
-
|
285
|
-
out->cur += out->opts->dump_opts.hash_size;
|
274
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
|
286
275
|
}
|
287
276
|
if (0 < out->opts->dump_opts.indent_size) {
|
288
277
|
int i;
|
289
278
|
|
290
279
|
for (i = depth; 0 < i; i--) {
|
291
|
-
|
292
|
-
out->cur += out->opts->dump_opts.indent_size;
|
280
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
293
281
|
}
|
294
282
|
}
|
295
283
|
}
|
data/ext/oj/encoder.c
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
// Copyright (c) 2011, 2022 Peter Ohler. All rights reserved.
|
2
|
+
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
3
|
+
|
4
|
+
#include "oj.h"
|
5
|
+
|
6
|
+
typedef struct _encoder {
|
7
|
+
int indent; // indention for dump, default 2
|
8
|
+
char circular; // YesNo
|
9
|
+
char escape_mode; // Escape_Mode
|
10
|
+
char mode; // Mode
|
11
|
+
char time_format; // TimeFormat
|
12
|
+
char bigdec_as_num; // YesNo
|
13
|
+
char to_hash; // YesNo
|
14
|
+
char to_json; // YesNo
|
15
|
+
char as_json; // YesNo
|
16
|
+
char raw_json; // YesNo
|
17
|
+
char trace; // YesNo
|
18
|
+
char sec_prec_set; // boolean (0 or 1)
|
19
|
+
char ignore_under; // YesNo - ignore attrs starting with _ if true in object and custom modes
|
20
|
+
int64_t int_range_min; // dump numbers below as string
|
21
|
+
int64_t int_range_max; // dump numbers above as string
|
22
|
+
const char* create_id; // 0 or string
|
23
|
+
size_t create_id_len; // length of create_id
|
24
|
+
int sec_prec; // second precision when dumping time
|
25
|
+
char float_prec; // float precision, linked to float_fmt
|
26
|
+
char float_fmt[7]; // float format for dumping, if empty use Ruby
|
27
|
+
struct _dumpOpts dump_opts;
|
28
|
+
struct _rxClass str_rx;
|
29
|
+
VALUE* ignore; // Qnil terminated array of classes or NULL
|
30
|
+
} * Encoder;
|
31
|
+
|
32
|
+
/*
|
33
|
+
rb_define_module_function(Oj, "encode", encode, -1);
|
34
|
+
rb_define_module_function(Oj, "to_file", to_file, -1); // or maybe just write
|
35
|
+
rb_define_module_function(Oj, "to_stream", to_stream, -1);
|
36
|
+
*/
|
37
|
+
|
38
|
+
// write(to, obj)
|
39
|
+
// if to is a string then open file
|
40
|
+
// else if stream then write to stream
|
41
|
+
// handle non-blocking
|
42
|
+
|
43
|
+
// should each mode have a different encoder or use delegates like the parser?
|
data/ext/oj/fast.c
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
|
14
14
|
#include "encode.h"
|
15
15
|
#include "oj.h"
|
16
|
+
#include "dump.h"
|
16
17
|
|
17
18
|
// maximum to allocate on the stack, arbitrary limit
|
18
19
|
#define SMALL_JSON 65536
|
@@ -771,7 +772,7 @@ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
|
|
771
772
|
pi.doc = doc;
|
772
773
|
#if IS_WINDOWS
|
773
774
|
// assume a 1M stack and give half to ruby
|
774
|
-
pi.stack_min = (void*)((char*)&pi - (
|
775
|
+
pi.stack_min = (void *)((char *)&pi - (512L * 1024L));
|
775
776
|
#else
|
776
777
|
{
|
777
778
|
struct rlimit lim;
|
@@ -1492,6 +1493,7 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
|
|
1492
1493
|
Doc doc = self_doc(self);
|
1493
1494
|
const char *path = 0;
|
1494
1495
|
size_t wlen;
|
1496
|
+
Leaf * where_orig = doc->where;
|
1495
1497
|
|
1496
1498
|
wlen = doc->where - doc->where_path;
|
1497
1499
|
if (0 < wlen) {
|
@@ -1508,9 +1510,13 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
|
|
1508
1510
|
if (0 < wlen) {
|
1509
1511
|
memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
|
1510
1512
|
}
|
1513
|
+
doc->where = where_orig;
|
1511
1514
|
return Qnil;
|
1512
1515
|
}
|
1513
1516
|
}
|
1517
|
+
if (NULL == doc->where || NULL == *doc->where) {
|
1518
|
+
return Qnil;
|
1519
|
+
}
|
1514
1520
|
if (COL_VAL == (*doc->where)->value_type && 0 != (*doc->where)->elements) {
|
1515
1521
|
Leaf first = (*doc->where)->elements->next;
|
1516
1522
|
Leaf e = first;
|
@@ -1525,6 +1531,7 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
|
|
1525
1531
|
if (0 < wlen) {
|
1526
1532
|
memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
|
1527
1533
|
}
|
1534
|
+
doc->where = where_orig;
|
1528
1535
|
}
|
1529
1536
|
return Qnil;
|
1530
1537
|
}
|
@@ -1604,18 +1611,15 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
|
|
1604
1611
|
volatile VALUE rjson;
|
1605
1612
|
|
1606
1613
|
if (0 == filename) {
|
1607
|
-
char buf[4096];
|
1608
1614
|
struct _out out;
|
1609
1615
|
|
1610
|
-
out
|
1611
|
-
|
1612
|
-
out.allocated = false;
|
1616
|
+
oj_out_init(&out);
|
1617
|
+
|
1613
1618
|
out.omit_nil = oj_default_options.dump_opts.omit_nil;
|
1614
1619
|
oj_dump_leaf_to_json(leaf, &oj_default_options, &out);
|
1615
1620
|
rjson = rb_str_new2(out.buf);
|
1616
|
-
|
1617
|
-
|
1618
|
-
}
|
1621
|
+
|
1622
|
+
oj_out_free(&out);
|
1619
1623
|
} else {
|
1620
1624
|
oj_write_leaf_to_file(leaf, filename, &oj_default_options);
|
1621
1625
|
rjson = Qnil;
|
@@ -1711,8 +1715,10 @@ static VALUE doc_not_implemented(VALUE self) {
|
|
1711
1715
|
* # Now try again using a path to Oj::Doc.fetch() directly and not using a
|
1712
1716
|
* block. doc = Oj::Doc.open(json) doc.fetch('/2/three') #=> 3 doc.close()
|
1713
1717
|
*/
|
1714
|
-
void oj_init_doc() {
|
1718
|
+
void oj_init_doc(void) {
|
1715
1719
|
oj_doc_class = rb_define_class_under(Oj, "Doc", rb_cObject);
|
1720
|
+
rb_gc_register_address(&oj_doc_class);
|
1721
|
+
rb_undef_alloc_func(oj_doc_class);
|
1716
1722
|
rb_define_singleton_method(oj_doc_class, "open", doc_open, 1);
|
1717
1723
|
rb_define_singleton_method(oj_doc_class, "open_file", doc_open_file, 1);
|
1718
1724
|
rb_define_singleton_method(oj_doc_class, "parse", doc_open, 1);
|
data/ext/oj/intern.c
CHANGED
@@ -86,8 +86,12 @@ static VALUE form_attr(const char *str, size_t len) {
|
|
86
86
|
return (VALUE)rb_intern3(buf, len + 1, oj_utf8_encoding);
|
87
87
|
}
|
88
88
|
|
89
|
-
void oj_hash_init() {
|
89
|
+
void oj_hash_init(void) {
|
90
90
|
VALUE cache_class = rb_define_class_under(Oj, "Cache", rb_cObject);
|
91
|
+
rb_undef_alloc_func(cache_class);
|
92
|
+
|
93
|
+
rb_gc_register_address(&cache_class);
|
94
|
+
rb_undef_alloc_func(cache_class);
|
91
95
|
|
92
96
|
str_cache = cache_create(0, form_str, true, true);
|
93
97
|
str_cache_obj = Data_Wrap_Struct(cache_class, cache_mark, cache_free, str_cache);
|
@@ -275,6 +279,7 @@ VALUE oj_class_intern(const char *key, size_t len, bool safe, ParseInfo pi, int
|
|
275
279
|
bucket->len = len;
|
276
280
|
bucket->val = resolve_classpath(pi, key, len, auto_define, error_class);
|
277
281
|
}
|
282
|
+
rb_gc_register_mark_object(bucket->val);
|
278
283
|
return bucket->val;
|
279
284
|
}
|
280
285
|
|
@@ -287,8 +292,10 @@ char *oj_strndup(const char *s, size_t len) {
|
|
287
292
|
return d;
|
288
293
|
}
|
289
294
|
|
290
|
-
|
295
|
+
/*
|
296
|
+
void intern_cleanup(void) {
|
291
297
|
cache_free(str_cache);
|
292
298
|
cache_free(sym_cache);
|
293
299
|
cache_free(attr_cache);
|
294
300
|
}
|
301
|
+
*/
|