oj 3.13.11 → 3.15.0
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 +74 -0
- data/README.md +4 -2
- data/ext/oj/buf.h +11 -6
- data/ext/oj/cache.c +25 -24
- data/ext/oj/cache8.c +10 -9
- data/ext/oj/circarray.c +8 -6
- data/ext/oj/circarray.h +2 -2
- data/ext/oj/code.c +17 -24
- data/ext/oj/code.h +2 -2
- data/ext/oj/compat.c +17 -44
- data/ext/oj/custom.c +70 -141
- data/ext/oj/debug.c +3 -9
- data/ext/oj/dump.c +128 -118
- data/ext/oj/dump.h +12 -8
- data/ext/oj/dump_compat.c +564 -641
- data/ext/oj/dump_leaf.c +17 -63
- data/ext/oj/dump_object.c +70 -199
- data/ext/oj/dump_strict.c +22 -46
- data/ext/oj/encoder.c +1 -1
- data/ext/oj/err.c +2 -13
- data/ext/oj/err.h +9 -12
- data/ext/oj/extconf.rb +14 -5
- data/ext/oj/fast.c +75 -103
- data/ext/oj/intern.c +52 -50
- data/ext/oj/intern.h +4 -8
- data/ext/oj/mem.c +318 -0
- data/ext/oj/mem.h +53 -0
- data/ext/oj/mimic_json.c +75 -47
- data/ext/oj/object.c +49 -66
- data/ext/oj/odd.c +89 -67
- data/ext/oj/odd.h +15 -15
- data/ext/oj/oj.c +140 -99
- data/ext/oj/oj.h +80 -51
- data/ext/oj/parse.c +162 -184
- data/ext/oj/parse.h +7 -10
- data/ext/oj/parser.c +89 -34
- data/ext/oj/parser.h +18 -7
- data/ext/oj/rails.c +82 -146
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +11 -12
- data/ext/oj/reader.h +4 -2
- data/ext/oj/resolve.c +3 -4
- data/ext/oj/rxclass.c +6 -5
- data/ext/oj/rxclass.h +1 -1
- data/ext/oj/saj.c +20 -31
- data/ext/oj/saj2.c +329 -93
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/scp.c +3 -14
- data/ext/oj/sparse.c +26 -70
- data/ext/oj/stream_writer.c +12 -22
- data/ext/oj/strict.c +20 -52
- data/ext/oj/string_writer.c +21 -21
- data/ext/oj/trace.h +31 -4
- data/ext/oj/usual.c +105 -150
- data/ext/oj/usual.h +68 -0
- data/ext/oj/util.h +1 -1
- data/ext/oj/val_stack.c +1 -1
- data/ext/oj/val_stack.h +8 -7
- data/ext/oj/validate.c +21 -26
- data/ext/oj/wab.c +31 -68
- data/lib/oj/active_support_helper.rb +0 -1
- data/lib/oj/bag.rb +7 -1
- data/lib/oj/easy_hash.rb +4 -5
- data/lib/oj/error.rb +0 -1
- data/lib/oj/json.rb +4 -2
- data/lib/oj/mimic.rb +4 -2
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/state.rb +9 -6
- data/lib/oj/version.rb +1 -2
- data/lib/oj.rb +2 -0
- data/pages/Compatibility.md +1 -1
- data/pages/InstallOptions.md +20 -0
- data/pages/Options.md +10 -0
- data/test/_test_active.rb +8 -9
- data/test/_test_active_mimic.rb +7 -8
- data/test/_test_mimic_rails.rb +17 -20
- data/test/activerecord/result_test.rb +5 -6
- data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
- data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
- data/test/{activesupport5 → activesupport7}/encoding_test.rb +20 -34
- data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
- data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
- data/test/files.rb +15 -15
- data/test/foo.rb +9 -71
- data/test/helper.rb +11 -8
- data/test/isolated/shared.rb +3 -2
- data/test/json_gem/json_addition_test.rb +2 -2
- data/test/json_gem/json_common_interface_test.rb +4 -4
- data/test/json_gem/json_encoding_test.rb +0 -0
- data/test/json_gem/json_ext_parser_test.rb +1 -0
- data/test/json_gem/json_fixtures_test.rb +3 -2
- data/test/json_gem/json_generator_test.rb +48 -36
- data/test/json_gem/json_generic_object_test.rb +11 -11
- data/test/json_gem/json_parser_test.rb +54 -47
- data/test/json_gem/json_string_matching_test.rb +9 -9
- data/test/json_gem/test_helper.rb +7 -3
- data/test/mem.rb +13 -12
- data/test/perf.rb +21 -26
- data/test/perf_compat.rb +31 -33
- data/test/perf_dump.rb +50 -0
- data/test/perf_fast.rb +80 -82
- data/test/perf_file.rb +27 -29
- data/test/perf_object.rb +65 -69
- data/test/perf_once.rb +12 -11
- data/test/perf_parser.rb +42 -48
- data/test/perf_saj.rb +46 -54
- data/test/perf_scp.rb +57 -69
- data/test/perf_simple.rb +41 -39
- data/test/perf_strict.rb +68 -70
- data/test/perf_wab.rb +67 -69
- data/test/prec.rb +3 -3
- data/test/sample/change.rb +0 -1
- data/test/sample/dir.rb +0 -1
- data/test/sample/doc.rb +0 -1
- data/test/sample/file.rb +0 -1
- data/test/sample/group.rb +0 -1
- data/test/sample/hasprops.rb +0 -1
- data/test/sample/layer.rb +0 -1
- data/test/sample/rect.rb +0 -1
- data/test/sample/shape.rb +0 -1
- data/test/sample/text.rb +0 -1
- data/test/sample.rb +16 -16
- data/test/sample_json.rb +8 -8
- data/test/test_compat.rb +76 -42
- data/test/test_custom.rb +72 -51
- data/test/test_debian.rb +7 -10
- data/test/test_fast.rb +86 -90
- data/test/test_file.rb +41 -30
- data/test/test_gc.rb +16 -5
- data/test/test_generate.rb +5 -5
- data/test/test_hash.rb +4 -4
- data/test/test_integer_range.rb +9 -9
- data/test/test_null.rb +20 -20
- data/test/test_object.rb +85 -96
- data/test/test_parser.rb +6 -22
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +115 -23
- data/test/test_parser_usual.rb +6 -6
- data/test/test_rails.rb +2 -2
- data/test/test_saj.rb +10 -8
- data/test/test_scp.rb +37 -39
- data/test/test_strict.rb +30 -32
- data/test/test_various.rb +147 -99
- data/test/test_wab.rb +48 -44
- data/test/test_writer.rb +47 -47
- data/test/tests.rb +13 -4
- data/test/tests_mimic.rb +12 -3
- data/test/tests_mimic_addition.rb +12 -3
- metadata +33 -144
- data/test/activesupport4/decoding_test.rb +0 -108
- data/test/activesupport4/encoding_test.rb +0 -531
- data/test/activesupport4/test_helper.rb +0 -41
- data/test/activesupport5/test_helper.rb +0 -72
- data/test/bar.rb +0 -16
- data/test/baz.rb +0 -16
- data/test/bug.rb +0 -16
- data/test/zoo.rb +0 -13
data/ext/oj/sparse.c
CHANGED
@@ -10,6 +10,7 @@
|
|
10
10
|
#include "buf.h"
|
11
11
|
#include "encode.h"
|
12
12
|
#include "intern.h" // for oj_strndup()
|
13
|
+
#include "mem.h"
|
13
14
|
#include "oj.h"
|
14
15
|
#include "parse.h"
|
15
16
|
#include "val_stack.h"
|
@@ -71,7 +72,7 @@ static void add_value(ParseInfo pi, VALUE rval) {
|
|
71
72
|
case NEXT_HASH_VALUE:
|
72
73
|
pi->hash_set_value(pi, parent, rval);
|
73
74
|
if (parent->kalloc) {
|
74
|
-
|
75
|
+
OJ_R_FREE((char *)parent->key);
|
75
76
|
}
|
76
77
|
parent->key = 0;
|
77
78
|
parent->kalloc = 0;
|
@@ -110,7 +111,7 @@ static void add_num_value(ParseInfo pi, NumInfo ni) {
|
|
110
111
|
case NEXT_HASH_VALUE:
|
111
112
|
pi->hash_set_num(pi, parent, ni);
|
112
113
|
if (parent->kalloc) {
|
113
|
-
|
114
|
+
OJ_R_FREE((char *)parent->key);
|
114
115
|
}
|
115
116
|
parent->key = 0;
|
116
117
|
parent->kalloc = 0;
|
@@ -212,11 +213,7 @@ static void read_escaped_str(ParseInfo pi) {
|
|
212
213
|
}
|
213
214
|
while ('\"' != (c = reader_get(&pi->rd))) {
|
214
215
|
if ('\0' == c) {
|
215
|
-
oj_set_error_at(pi,
|
216
|
-
oj_parse_error_class,
|
217
|
-
__FILE__,
|
218
|
-
__LINE__,
|
219
|
-
"quoted string not terminated");
|
216
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "quoted string not terminated");
|
220
217
|
buf_cleanup(&buf);
|
221
218
|
return;
|
222
219
|
} else if ('\\' == c) {
|
@@ -249,11 +246,7 @@ static void read_escaped_str(ParseInfo pi) {
|
|
249
246
|
reader_backup(&pi->rd);
|
250
247
|
break;
|
251
248
|
}
|
252
|
-
oj_set_error_at(pi,
|
253
|
-
oj_parse_error_class,
|
254
|
-
__FILE__,
|
255
|
-
__LINE__,
|
256
|
-
"invalid escaped character");
|
249
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
|
257
250
|
buf_cleanup(&buf);
|
258
251
|
return;
|
259
252
|
}
|
@@ -277,11 +270,7 @@ static void read_escaped_str(ParseInfo pi) {
|
|
277
270
|
buf_append(&buf, c);
|
278
271
|
break;
|
279
272
|
}
|
280
|
-
oj_set_error_at(pi,
|
281
|
-
oj_parse_error_class,
|
282
|
-
__FILE__,
|
283
|
-
__LINE__,
|
284
|
-
"invalid escaped character");
|
273
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
|
285
274
|
buf_cleanup(&buf);
|
286
275
|
return;
|
287
276
|
}
|
@@ -315,7 +304,7 @@ static void read_escaped_str(ParseInfo pi) {
|
|
315
304
|
case NEXT_HASH_VALUE:
|
316
305
|
pi->hash_set_cstr(pi, parent, buf.head, buf_len(&buf), pi->rd.str);
|
317
306
|
if (parent->kalloc) {
|
318
|
-
|
307
|
+
OJ_R_FREE((char *)parent->key);
|
319
308
|
}
|
320
309
|
parent->key = 0;
|
321
310
|
parent->kalloc = 0;
|
@@ -345,11 +334,7 @@ static void read_str(ParseInfo pi) {
|
|
345
334
|
reader_protect(&pi->rd);
|
346
335
|
while ('\"' != (c = reader_get(&pi->rd))) {
|
347
336
|
if ('\0' == c) {
|
348
|
-
oj_set_error_at(pi,
|
349
|
-
oj_parse_error_class,
|
350
|
-
__FILE__,
|
351
|
-
__LINE__,
|
352
|
-
"quoted string not terminated");
|
337
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "quoted string not terminated");
|
353
338
|
return;
|
354
339
|
} else if ('\\' == c) {
|
355
340
|
reader_backup(&pi->rd);
|
@@ -386,7 +371,7 @@ static void read_str(ParseInfo pi) {
|
|
386
371
|
case NEXT_HASH_VALUE:
|
387
372
|
pi->hash_set_cstr(pi, parent, pi->rd.str, pi->rd.tail - pi->rd.str - 1, pi->rd.str);
|
388
373
|
if (parent->kalloc) {
|
389
|
-
|
374
|
+
OJ_R_FREE((char *)parent->key);
|
390
375
|
}
|
391
376
|
parent->key = 0;
|
392
377
|
parent->kalloc = 0;
|
@@ -429,7 +414,7 @@ static void read_num(ParseInfo pi) {
|
|
429
414
|
ni.no_big = !pi->options.compat_bigdec;
|
430
415
|
ni.bigdec_load = pi->options.compat_bigdec;
|
431
416
|
} else {
|
432
|
-
ni.no_big
|
417
|
+
ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
|
433
418
|
RubyDec == pi->options.bigdec_load);
|
434
419
|
ni.bigdec_load = pi->options.bigdec_load;
|
435
420
|
}
|
@@ -443,18 +428,10 @@ static void read_num(ParseInfo pi) {
|
|
443
428
|
}
|
444
429
|
if ('I' == c) {
|
445
430
|
if (No == pi->options.allow_nan) {
|
446
|
-
oj_set_error_at(pi,
|
447
|
-
oj_parse_error_class,
|
448
|
-
__FILE__,
|
449
|
-
__LINE__,
|
450
|
-
"not a number or other value");
|
431
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
451
432
|
return;
|
452
433
|
} else if (0 != reader_expect(&pi->rd, "nfinity")) {
|
453
|
-
oj_set_error_at(pi,
|
454
|
-
oj_parse_error_class,
|
455
|
-
__FILE__,
|
456
|
-
__LINE__,
|
457
|
-
"not a number or other value");
|
434
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
458
435
|
return;
|
459
436
|
}
|
460
437
|
ni.infinity = 1;
|
@@ -476,11 +453,7 @@ static void read_num(ParseInfo pi) {
|
|
476
453
|
|
477
454
|
if (0 < d) {
|
478
455
|
if (zero1 && CompatMode == pi->options.mode) {
|
479
|
-
oj_set_error_at(pi,
|
480
|
-
oj_parse_error_class,
|
481
|
-
__FILE__,
|
482
|
-
__LINE__,
|
483
|
-
"not a number");
|
456
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
|
484
457
|
return;
|
485
458
|
}
|
486
459
|
zero1 = false;
|
@@ -591,7 +564,7 @@ static void read_nan(ParseInfo pi) {
|
|
591
564
|
ni.no_big = !pi->options.compat_bigdec;
|
592
565
|
ni.bigdec_load = pi->options.compat_bigdec;
|
593
566
|
} else {
|
594
|
-
ni.no_big
|
567
|
+
ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
|
595
568
|
RubyDec == pi->options.bigdec_load);
|
596
569
|
ni.bigdec_load = pi->options.bigdec_load;
|
597
570
|
}
|
@@ -716,11 +689,7 @@ void oj_sparse2(ParseInfo pi) {
|
|
716
689
|
case '"': read_str(pi); break;
|
717
690
|
case '+':
|
718
691
|
if (CompatMode == pi->options.mode) {
|
719
|
-
oj_set_error_at(pi,
|
720
|
-
oj_parse_error_class,
|
721
|
-
__FILE__,
|
722
|
-
__LINE__,
|
723
|
-
"unexpected character");
|
692
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
|
724
693
|
return;
|
725
694
|
}
|
726
695
|
pi->cur--;
|
@@ -745,11 +714,7 @@ void oj_sparse2(ParseInfo pi) {
|
|
745
714
|
reader_backup(&pi->rd);
|
746
715
|
read_num(pi);
|
747
716
|
} else {
|
748
|
-
oj_set_error_at(pi,
|
749
|
-
oj_parse_error_class,
|
750
|
-
__FILE__,
|
751
|
-
__LINE__,
|
752
|
-
"unexpected character");
|
717
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
|
753
718
|
return;
|
754
719
|
}
|
755
720
|
break;
|
@@ -757,11 +722,7 @@ void oj_sparse2(ParseInfo pi) {
|
|
757
722
|
if (Yes == pi->options.allow_nan) {
|
758
723
|
read_nan(pi);
|
759
724
|
} else {
|
760
|
-
oj_set_error_at(pi,
|
761
|
-
oj_parse_error_class,
|
762
|
-
__FILE__,
|
763
|
-
__LINE__,
|
764
|
-
"unexpected character");
|
725
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
|
765
726
|
return;
|
766
727
|
}
|
767
728
|
break;
|
@@ -799,8 +760,7 @@ void oj_sparse2(ParseInfo pi) {
|
|
799
760
|
ni.no_big = !pi->options.compat_bigdec;
|
800
761
|
ni.bigdec_load = pi->options.compat_bigdec;
|
801
762
|
} else {
|
802
|
-
ni.no_big = (FloatDec == pi->options.bigdec_load ||
|
803
|
-
FastDec == pi->options.bigdec_load ||
|
763
|
+
ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
|
804
764
|
RubyDec == pi->options.bigdec_load);
|
805
765
|
ni.bigdec_load = pi->options.bigdec_load;
|
806
766
|
}
|
@@ -813,13 +773,7 @@ void oj_sparse2(ParseInfo pi) {
|
|
813
773
|
case '/': skip_comment(pi); break;
|
814
774
|
case '\0': return;
|
815
775
|
default:
|
816
|
-
oj_set_error_at(pi,
|
817
|
-
oj_parse_error_class,
|
818
|
-
__FILE__,
|
819
|
-
__LINE__,
|
820
|
-
"unexpected character '%c' [0x%02x]",
|
821
|
-
c,
|
822
|
-
c);
|
776
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character '%c' [0x%02x]", c, c);
|
823
777
|
return;
|
824
778
|
}
|
825
779
|
if (err_has(&pi->err)) {
|
@@ -878,8 +832,8 @@ oj_pi_sparse(int argc, VALUE *argv, ParseInfo pi, int fd) {
|
|
878
832
|
} else {
|
879
833
|
rb_raise(rb_eTypeError, "Nil is not a valid JSON source.");
|
880
834
|
}
|
881
|
-
} else if (CompatMode == pi->options.mode && T_STRING == rb_type(input) &&
|
882
|
-
|
835
|
+
} else if (CompatMode == pi->options.mode && T_STRING == rb_type(input) && No == pi->options.nilnil &&
|
836
|
+
0 == RSTRING_LEN(input)) {
|
883
837
|
rb_raise(oj_json_parser_error_class, "An empty string is not a valid JSON string.");
|
884
838
|
}
|
885
839
|
if (rb_block_given_p()) {
|
@@ -932,9 +886,7 @@ oj_pi_sparse(int argc, VALUE *argv, ParseInfo pi, int fd) {
|
|
932
886
|
switch (v->next) {
|
933
887
|
case NEXT_ARRAY_NEW:
|
934
888
|
case NEXT_ARRAY_ELEMENT:
|
935
|
-
case NEXT_ARRAY_COMMA:
|
936
|
-
oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Array not terminated");
|
937
|
-
break;
|
889
|
+
case NEXT_ARRAY_COMMA: oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Array not terminated"); break;
|
938
890
|
case NEXT_HASH_NEW:
|
939
891
|
case NEXT_HASH_KEY:
|
940
892
|
case NEXT_HASH_COLON:
|
@@ -953,7 +905,11 @@ CLEANUP:
|
|
953
905
|
}
|
954
906
|
stack_cleanup(&pi->stack);
|
955
907
|
if (0 != fd) {
|
908
|
+
#ifdef _WIN32
|
909
|
+
rb_w32_close(fd);
|
910
|
+
#else
|
956
911
|
close(fd);
|
912
|
+
#endif
|
957
913
|
}
|
958
914
|
if (err_has(&pi->err)) {
|
959
915
|
rb_set_errinfo(Qnil);
|
data/ext/oj/stream_writer.c
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
#include <ruby.h>
|
6
6
|
|
7
7
|
#include "encode.h"
|
8
|
+
#include "mem.h"
|
8
9
|
|
9
10
|
extern VALUE Oj;
|
10
11
|
|
@@ -15,9 +16,9 @@ static void stream_writer_free(void *ptr) {
|
|
15
16
|
return;
|
16
17
|
}
|
17
18
|
sw = (StreamWriter)ptr;
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
OJ_R_FREE(sw->sw.out.buf);
|
20
|
+
OJ_R_FREE(sw->sw.types);
|
21
|
+
OJ_R_FREE(ptr);
|
21
22
|
}
|
22
23
|
|
23
24
|
static void stream_writer_reset_buf(StreamWriter sw) {
|
@@ -82,8 +83,8 @@ static VALUE stream_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
82
83
|
if (oj_stringio_class == clas) {
|
83
84
|
type = STRING_IO;
|
84
85
|
#if !IS_WINDOWS
|
85
|
-
} else if (rb_respond_to(stream, oj_fileno_id) &&
|
86
|
-
|
86
|
+
} else if (rb_respond_to(stream, oj_fileno_id) && Qnil != (s = rb_funcall(stream, oj_fileno_id, 0)) &&
|
87
|
+
0 != (fd = FIX2INT(s))) {
|
87
88
|
type = FILE_IO;
|
88
89
|
#endif
|
89
90
|
} else if (rb_respond_to(stream, oj_write_id)) {
|
@@ -91,7 +92,7 @@ static VALUE stream_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
91
92
|
} else {
|
92
93
|
rb_raise(rb_eArgError, "expected an IO Object.");
|
93
94
|
}
|
94
|
-
sw =
|
95
|
+
sw = OJ_R_ALLOC(struct _streamWriter);
|
95
96
|
if (2 == argc && T_HASH == rb_type(argv[1])) {
|
96
97
|
volatile VALUE v;
|
97
98
|
int buf_size = 0;
|
@@ -101,15 +102,10 @@ static VALUE stream_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
101
102
|
rb_gc_register_address(&buffer_size_sym);
|
102
103
|
}
|
103
104
|
if (Qnil != (v = rb_hash_lookup(argv[1], buffer_size_sym))) {
|
104
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
105
105
|
if (rb_cInteger != rb_obj_class(v)) {
|
106
|
+
OJ_R_FREE(sw);
|
106
107
|
rb_raise(rb_eArgError, ":buffer size must be a Integer.");
|
107
108
|
}
|
108
|
-
#else
|
109
|
-
if (T_FIXNUM != rb_type(v)) {
|
110
|
-
rb_raise(rb_eArgError, ":buffer size must be a Integer.");
|
111
|
-
}
|
112
|
-
#endif
|
113
109
|
buf_size = FIX2INT(v);
|
114
110
|
}
|
115
111
|
oj_str_writer_init(&sw->sw, buf_size);
|
@@ -139,7 +135,6 @@ static VALUE stream_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
139
135
|
static VALUE stream_writer_push_key(VALUE self, VALUE key) {
|
140
136
|
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
141
137
|
|
142
|
-
rb_check_type(key, T_STRING);
|
143
138
|
oj_str_writer_push_key(&sw->sw, StringValuePtr(key));
|
144
139
|
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
145
140
|
stream_writer_write(sw);
|
@@ -164,7 +159,6 @@ static VALUE stream_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
|
164
159
|
if (Qnil == argv[0]) {
|
165
160
|
oj_str_writer_push_object(&sw->sw, 0);
|
166
161
|
} else {
|
167
|
-
rb_check_type(argv[0], T_STRING);
|
168
162
|
oj_str_writer_push_object(&sw->sw, StringValuePtr(argv[0]));
|
169
163
|
}
|
170
164
|
break;
|
@@ -193,7 +187,6 @@ static VALUE stream_writer_push_array(int argc, VALUE *argv, VALUE self) {
|
|
193
187
|
if (Qnil == argv[0]) {
|
194
188
|
oj_str_writer_push_array(&sw->sw, 0);
|
195
189
|
} else {
|
196
|
-
rb_check_type(argv[0], T_STRING);
|
197
190
|
oj_str_writer_push_array(&sw->sw, StringValuePtr(argv[0]));
|
198
191
|
}
|
199
192
|
break;
|
@@ -221,7 +214,6 @@ static VALUE stream_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
|
221
214
|
if (Qnil == argv[1]) {
|
222
215
|
oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
|
223
216
|
} else {
|
224
|
-
rb_check_type(argv[1], T_STRING);
|
225
217
|
oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, StringValuePtr(argv[1]));
|
226
218
|
}
|
227
219
|
break;
|
@@ -245,17 +237,13 @@ static VALUE stream_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
|
245
237
|
static VALUE stream_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
246
238
|
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
247
239
|
|
248
|
-
rb_check_type(argv[0], T_STRING);
|
249
240
|
switch (argc) {
|
250
241
|
case 1: oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0); break;
|
251
242
|
case 2:
|
252
243
|
if (Qnil == argv[1]) {
|
253
244
|
oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
|
254
245
|
} else {
|
255
|
-
|
256
|
-
oj_str_writer_push_json((StrWriter)DATA_PTR(self),
|
257
|
-
StringValuePtr(*argv),
|
258
|
-
StringValuePtr(argv[1]));
|
246
|
+
oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), StringValuePtr(argv[1]));
|
259
247
|
}
|
260
248
|
break;
|
261
249
|
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_json'."); break;
|
@@ -315,8 +303,10 @@ static VALUE stream_writer_flush(VALUE self) {
|
|
315
303
|
* will create that element in the JSON document and subsequent pushes will add
|
316
304
|
* the elements to that array or object until a pop() is called.
|
317
305
|
*/
|
318
|
-
void oj_stream_writer_init() {
|
306
|
+
void oj_stream_writer_init(void) {
|
319
307
|
oj_stream_writer_class = rb_define_class_under(Oj, "StreamWriter", rb_cObject);
|
308
|
+
rb_gc_register_address(&oj_stream_writer_class);
|
309
|
+
rb_undef_alloc_func(oj_stream_writer_class);
|
320
310
|
rb_define_module_function(oj_stream_writer_class, "new", stream_writer_new, -1);
|
321
311
|
rb_define_method(oj_stream_writer_class, "push_key", stream_writer_push_key, 1);
|
322
312
|
rb_define_method(oj_stream_writer_class, "push_object", stream_writer_push_object, -1);
|
data/ext/oj/strict.c
CHANGED
@@ -17,7 +17,7 @@ VALUE oj_cstr_to_value(const char *str, size_t len, size_t cache_str) {
|
|
17
17
|
volatile VALUE rstr = Qnil;
|
18
18
|
|
19
19
|
if (len < cache_str) {
|
20
|
-
|
20
|
+
rstr = oj_str_intern(str, len);
|
21
21
|
} else {
|
22
22
|
rstr = rb_str_new(str, len);
|
23
23
|
rstr = oj_encode(rstr);
|
@@ -37,28 +37,24 @@ VALUE oj_calc_hash_key(ParseInfo pi, Val parent) {
|
|
37
37
|
} else {
|
38
38
|
rkey = rb_str_new(parent->key, parent->klen);
|
39
39
|
rkey = oj_encode(rkey);
|
40
|
-
|
40
|
+
OBJ_FREEZE(rkey); // frozen when used as a Hash key anyway
|
41
41
|
}
|
42
42
|
return rkey;
|
43
43
|
}
|
44
44
|
if (Yes == pi->options.sym_key) {
|
45
|
-
|
45
|
+
rkey = oj_sym_intern(parent->key, parent->klen);
|
46
46
|
} else {
|
47
|
-
|
47
|
+
rkey = oj_str_intern(parent->key, parent->klen);
|
48
48
|
}
|
49
49
|
return rkey;
|
50
50
|
}
|
51
51
|
|
52
52
|
static void hash_end(ParseInfo pi) {
|
53
|
-
|
54
|
-
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
55
|
-
}
|
53
|
+
TRACE_PARSE_HASH_END(pi->options.trace, pi);
|
56
54
|
}
|
57
55
|
|
58
56
|
static void array_end(ParseInfo pi) {
|
59
|
-
|
60
|
-
oj_trace_parse_array_end(pi, __FILE__, __LINE__);
|
61
|
-
}
|
57
|
+
TRACE_PARSE_ARRAY_END(pi->options.trace, pi);
|
62
58
|
}
|
63
59
|
|
64
60
|
static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
|
@@ -66,9 +62,7 @@ static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
|
|
66
62
|
}
|
67
63
|
|
68
64
|
static void add_value(ParseInfo pi, VALUE val) {
|
69
|
-
|
70
|
-
oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, val);
|
71
|
-
}
|
65
|
+
TRACE_PARSE_CALL(pi->options.trace, "add_value", pi, val);
|
72
66
|
pi->stack.head->val = val;
|
73
67
|
}
|
74
68
|
|
@@ -76,9 +70,7 @@ static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig
|
|
76
70
|
volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
77
71
|
|
78
72
|
pi->stack.head->val = rstr;
|
79
|
-
|
80
|
-
oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
|
81
|
-
}
|
73
|
+
TRACE_PARSE_CALL(pi->options.trace, "add_string", pi, rstr);
|
82
74
|
}
|
83
75
|
|
84
76
|
static void add_num(ParseInfo pi, NumInfo ni) {
|
@@ -86,30 +78,22 @@ static void add_num(ParseInfo pi, NumInfo ni) {
|
|
86
78
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
87
79
|
}
|
88
80
|
pi->stack.head->val = oj_num_as_value(ni);
|
89
|
-
|
90
|
-
oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
|
91
|
-
}
|
81
|
+
TRACE_PARSE_CALL(pi->options.trace, "add_number", pi, pi->stack.head->val);
|
92
82
|
}
|
93
83
|
|
94
84
|
static VALUE start_hash(ParseInfo pi) {
|
95
85
|
if (Qnil != pi->options.hash_class) {
|
96
86
|
return rb_class_new_instance(0, NULL, pi->options.hash_class);
|
97
87
|
}
|
98
|
-
|
99
|
-
oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
|
100
|
-
}
|
88
|
+
TRACE_PARSE_IN(pi->options.trace, "start_hash", pi);
|
101
89
|
return rb_hash_new();
|
102
90
|
}
|
103
91
|
|
104
92
|
static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
|
105
93
|
volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
106
94
|
|
107
|
-
rb_hash_aset(stack_peek(&pi->stack)->val,
|
108
|
-
|
109
|
-
rstr);
|
110
|
-
if (Yes == pi->options.trace) {
|
111
|
-
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
|
112
|
-
}
|
95
|
+
rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), rstr);
|
96
|
+
TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rstr);
|
113
97
|
}
|
114
98
|
|
115
99
|
static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
|
@@ -119,27 +103,17 @@ static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
|
|
119
103
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
120
104
|
}
|
121
105
|
v = oj_num_as_value(ni);
|
122
|
-
rb_hash_aset(stack_peek(&pi->stack)->val,
|
123
|
-
|
124
|
-
v);
|
125
|
-
if (Yes == pi->options.trace) {
|
126
|
-
oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, v);
|
127
|
-
}
|
106
|
+
rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), v);
|
107
|
+
TRACE_PARSE_CALL(pi->options.trace, "set_number", pi, v);
|
128
108
|
}
|
129
109
|
|
130
110
|
static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
|
131
|
-
rb_hash_aset(stack_peek(&pi->stack)->val,
|
132
|
-
|
133
|
-
value);
|
134
|
-
if (Yes == pi->options.trace) {
|
135
|
-
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
|
136
|
-
}
|
111
|
+
rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), value);
|
112
|
+
TRACE_PARSE_CALL(pi->options.trace, "set_value", pi, value);
|
137
113
|
}
|
138
114
|
|
139
115
|
static VALUE start_array(ParseInfo pi) {
|
140
|
-
|
141
|
-
oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
|
142
|
-
}
|
116
|
+
TRACE_PARSE_IN(pi->options.trace, "start_array", pi);
|
143
117
|
return rb_ary_new();
|
144
118
|
}
|
145
119
|
|
@@ -147,9 +121,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
|
|
147
121
|
volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
148
122
|
|
149
123
|
rb_ary_push(stack_peek(&pi->stack)->val, rstr);
|
150
|
-
|
151
|
-
oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
|
152
|
-
}
|
124
|
+
TRACE_PARSE_CALL(pi->options.trace, "append_string", pi, rstr);
|
153
125
|
}
|
154
126
|
|
155
127
|
static void array_append_num(ParseInfo pi, NumInfo ni) {
|
@@ -160,16 +132,12 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
|
|
160
132
|
}
|
161
133
|
v = oj_num_as_value(ni);
|
162
134
|
rb_ary_push(stack_peek(&pi->stack)->val, v);
|
163
|
-
|
164
|
-
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, v);
|
165
|
-
}
|
135
|
+
TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, v);
|
166
136
|
}
|
167
137
|
|
168
138
|
static void array_append_value(ParseInfo pi, VALUE value) {
|
169
139
|
rb_ary_push(stack_peek(&pi->stack)->val, value);
|
170
|
-
|
171
|
-
oj_trace_parse_call("append_value", pi, __FILE__, __LINE__, value);
|
172
|
-
}
|
140
|
+
TRACE_PARSE_CALL(pi->options.trace, "append_value", pi, value);
|
173
141
|
}
|
174
142
|
|
175
143
|
void oj_set_strict_callbacks(ParseInfo pi) {
|
data/ext/oj/string_writer.c
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
#include "dump.h"
|
5
5
|
#include "encode.h"
|
6
|
+
#include "mem.h"
|
6
7
|
|
7
8
|
extern VALUE Oj;
|
8
9
|
|
@@ -20,7 +21,7 @@ static void push_type(StrWriter sw, DumpType type) {
|
|
20
21
|
if (sw->types_end <= sw->types + sw->depth + 1) {
|
21
22
|
size_t size = (sw->types_end - sw->types) * 2;
|
22
23
|
|
23
|
-
|
24
|
+
OJ_R_REALLOC_N(sw->types, char, size);
|
24
25
|
sw->types_end = sw->types + size;
|
25
26
|
}
|
26
27
|
sw->depth++;
|
@@ -43,7 +44,7 @@ static void maybe_comma(StrWriter sw) {
|
|
43
44
|
void oj_str_writer_init(StrWriter sw, int buf_size) {
|
44
45
|
sw->opts = oj_default_options;
|
45
46
|
sw->depth = 0;
|
46
|
-
sw->types =
|
47
|
+
sw->types = OJ_R_ALLOC_N(char, 256);
|
47
48
|
sw->types_end = sw->types + 256;
|
48
49
|
*sw->types = '\0';
|
49
50
|
sw->keyWritten = 0;
|
@@ -53,10 +54,13 @@ void oj_str_writer_init(StrWriter sw, int buf_size) {
|
|
53
54
|
} else if (buf_size < 1024) {
|
54
55
|
buf_size = 1024;
|
55
56
|
}
|
56
|
-
|
57
|
-
|
58
|
-
sw->out.
|
59
|
-
sw->out.cur
|
57
|
+
// Must be allocated. Using the out.stack_buffer results in double frees
|
58
|
+
// and I haven't figured out why yet.
|
59
|
+
sw->out.buf = OJ_R_ALLOC_N(char, buf_size);
|
60
|
+
sw->out.cur = sw->out.buf;
|
61
|
+
sw->out.end = sw->out.buf + buf_size - BUFFER_EXTRA;
|
62
|
+
sw->out.allocated = true;
|
63
|
+
|
60
64
|
*sw->out.cur = '\0';
|
61
65
|
sw->out.circ_cache = NULL;
|
62
66
|
sw->out.circ_cnt = 0;
|
@@ -229,9 +233,11 @@ static void str_writer_free(void *ptr) {
|
|
229
233
|
return;
|
230
234
|
}
|
231
235
|
sw = (StrWriter)ptr;
|
232
|
-
|
233
|
-
|
234
|
-
|
236
|
+
|
237
|
+
oj_out_free(&sw->out);
|
238
|
+
|
239
|
+
OJ_R_FREE(sw->types);
|
240
|
+
OJ_R_FREE(ptr);
|
235
241
|
}
|
236
242
|
|
237
243
|
/* Document-method: new
|
@@ -251,7 +257,7 @@ static void str_writer_free(void *ptr) {
|
|
251
257
|
* - *options* [_Hash_] formatting options
|
252
258
|
*/
|
253
259
|
static VALUE str_writer_new(int argc, VALUE *argv, VALUE self) {
|
254
|
-
StrWriter sw =
|
260
|
+
StrWriter sw = OJ_R_ALLOC(struct _strWriter);
|
255
261
|
|
256
262
|
oj_str_writer_init(sw, 0);
|
257
263
|
if (1 == argc) {
|
@@ -275,7 +281,6 @@ static VALUE str_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
275
281
|
static VALUE str_writer_push_key(VALUE self, VALUE key) {
|
276
282
|
StrWriter sw = (StrWriter)DATA_PTR(self);
|
277
283
|
|
278
|
-
rb_check_type(key, T_STRING);
|
279
284
|
oj_str_writer_push_key(sw, StringValuePtr(key));
|
280
285
|
|
281
286
|
return Qnil;
|
@@ -297,7 +302,6 @@ static VALUE str_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
|
297
302
|
if (Qnil == argv[0]) {
|
298
303
|
oj_str_writer_push_object(sw, 0);
|
299
304
|
} else {
|
300
|
-
rb_check_type(argv[0], T_STRING);
|
301
305
|
oj_str_writer_push_object(sw, StringValuePtr(argv[0]));
|
302
306
|
}
|
303
307
|
break;
|
@@ -326,7 +330,6 @@ static VALUE str_writer_push_array(int argc, VALUE *argv, VALUE self) {
|
|
326
330
|
if (Qnil == argv[0]) {
|
327
331
|
oj_str_writer_push_array(sw, 0);
|
328
332
|
} else {
|
329
|
-
rb_check_type(argv[0], T_STRING);
|
330
333
|
oj_str_writer_push_array(sw, StringValuePtr(argv[0]));
|
331
334
|
}
|
332
335
|
break;
|
@@ -353,7 +356,6 @@ static VALUE str_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
|
353
356
|
if (Qnil == argv[1]) {
|
354
357
|
oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
|
355
358
|
} else {
|
356
|
-
rb_check_type(argv[1], T_STRING);
|
357
359
|
oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, StringValuePtr(argv[1]));
|
358
360
|
}
|
359
361
|
break;
|
@@ -372,17 +374,13 @@ static VALUE str_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
|
372
374
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
373
375
|
*/
|
374
376
|
static VALUE str_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
375
|
-
rb_check_type(argv[0], T_STRING);
|
376
377
|
switch (argc) {
|
377
378
|
case 1: oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0); break;
|
378
379
|
case 2:
|
379
380
|
if (Qnil == argv[1]) {
|
380
381
|
oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
|
381
382
|
} else {
|
382
|
-
|
383
|
-
oj_str_writer_push_json((StrWriter)DATA_PTR(self),
|
384
|
-
StringValuePtr(*argv),
|
385
|
-
StringValuePtr(argv[1]));
|
383
|
+
oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), StringValuePtr(argv[1]));
|
386
384
|
}
|
387
385
|
break;
|
388
386
|
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_json'."); break;
|
@@ -449,7 +447,7 @@ static VALUE str_writer_to_s(VALUE self) {
|
|
449
447
|
* Returns the contents of the writer as a JSON element. If called from inside
|
450
448
|
* an array or hash by Oj the raw buffer will be used othersize a more
|
451
449
|
* inefficient parse of the contents and a return of the result is
|
452
|
-
* completed. The parse uses the
|
450
|
+
* completed. The parse uses the strict mode.
|
453
451
|
*
|
454
452
|
* *return* [_Hash_|_Array_|_String_|_Integer_|_Float_|_True_|_False_|_nil|)
|
455
453
|
*/
|
@@ -469,8 +467,10 @@ static VALUE str_writer_as_json(VALUE self) {
|
|
469
467
|
* calling to_s() will return the JSON document. Note that calling to_s() before
|
470
468
|
* construction is complete will return the document in it's current state.
|
471
469
|
*/
|
472
|
-
void oj_string_writer_init() {
|
470
|
+
void oj_string_writer_init(void) {
|
473
471
|
oj_string_writer_class = rb_define_class_under(Oj, "StringWriter", rb_cObject);
|
472
|
+
rb_gc_register_address(&oj_string_writer_class);
|
473
|
+
rb_undef_alloc_func(oj_string_writer_class);
|
474
474
|
rb_define_module_function(oj_string_writer_class, "new", str_writer_new, -1);
|
475
475
|
rb_define_method(oj_string_writer_class, "push_key", str_writer_push_key, 1);
|
476
476
|
rb_define_method(oj_string_writer_class, "push_object", str_writer_push_object, -1);
|