oj 3.17.6 → 3.17.8
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 +67 -0
- data/ext/oj/cache.c +64 -47
- data/ext/oj/cache.h +1 -1
- data/ext/oj/code.c +38 -28
- data/ext/oj/code.h +2 -0
- data/ext/oj/compat.c +61 -29
- data/ext/oj/custom.c +38 -5
- data/ext/oj/dump.c +93 -29
- data/ext/oj/dump_compat.c +8 -11
- data/ext/oj/dump_object.c +18 -2
- data/ext/oj/dump_strict.c +2 -1
- data/ext/oj/extconf.rb +7 -1
- data/ext/oj/fast.c +46 -29
- data/ext/oj/intern.c +75 -77
- data/ext/oj/mimic_json.c +5 -29
- data/ext/oj/object.c +21 -2
- data/ext/oj/oj.c +136 -33
- data/ext/oj/oj.h +9 -7
- data/ext/oj/parse.c +58 -4
- data/ext/oj/parse.h +23 -1
- data/ext/oj/parser.c +99 -36
- data/ext/oj/parser.h +1 -1
- data/ext/oj/rails.c +8 -3
- data/ext/oj/reader.c +4 -0
- data/ext/oj/reader.h +1 -0
- data/ext/oj/resolve.c +5 -4
- data/ext/oj/resolve.h +9 -0
- data/ext/oj/saj.c +14 -7
- data/ext/oj/saj2.c +44 -28
- data/ext/oj/simd.h +5 -3
- data/ext/oj/sparse.c +7 -0
- data/ext/oj/stream_writer.c +3 -0
- data/ext/oj/strict.c +42 -4
- data/ext/oj/string_writer.c +17 -3
- data/ext/oj/usual.c +12 -4
- data/ext/oj/val_stack.c +11 -22
- data/ext/oj/val_stack.h +45 -24
- data/ext/oj/wab.c +3 -0
- data/lib/oj/generic_object.rb +82 -0
- data/lib/oj/json.rb +1 -71
- data/lib/oj/mimic.rb +0 -1
- data/lib/oj/version.rb +1 -1
- metadata +16 -15
data/ext/oj/dump.c
CHANGED
|
@@ -587,6 +587,9 @@ long oj_check_circular(VALUE obj, Out out) {
|
|
|
587
587
|
slot_t *slot;
|
|
588
588
|
|
|
589
589
|
if (Yes == out->opts->circular) {
|
|
590
|
+
if (NULL == out->circ_cache) {
|
|
591
|
+
oj_cache8_new(&out->circ_cache);
|
|
592
|
+
}
|
|
590
593
|
if (0 == (id = oj_cache8_get(out->circ_cache, obj, &slot))) {
|
|
591
594
|
out->circ_cnt++;
|
|
592
595
|
id = out->circ_cnt;
|
|
@@ -831,28 +834,61 @@ void oj_dump_obj_to_json_using_params(VALUE obj, Options copts, Out out, int arg
|
|
|
831
834
|
*out->cur = '\0';
|
|
832
835
|
if (Yes == copts->circular) {
|
|
833
836
|
oj_cache8_delete(out->circ_cache);
|
|
837
|
+
out->circ_cache = NULL;
|
|
834
838
|
}
|
|
835
839
|
}
|
|
836
840
|
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
int
|
|
841
|
+
struct dump_str_arg {
|
|
842
|
+
VALUE obj;
|
|
843
|
+
Options copts;
|
|
844
|
+
Out out;
|
|
845
|
+
int argc;
|
|
846
|
+
VALUE *argv;
|
|
847
|
+
};
|
|
842
848
|
|
|
843
|
-
|
|
849
|
+
static VALUE dump_str_body(VALUE a) {
|
|
850
|
+
struct dump_str_arg *arg = (struct dump_str_arg *)a;
|
|
844
851
|
|
|
845
|
-
out
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
if (0 == (f = fopen(path, "w"))) {
|
|
849
|
-
oj_out_free(&out);
|
|
850
|
-
rb_raise(rb_eIOError, "%s", strerror(errno));
|
|
852
|
+
oj_dump_obj_to_json_using_params(arg->obj, arg->copts, arg->out, arg->argc, arg->argv);
|
|
853
|
+
if (0 == arg->out->buf) {
|
|
854
|
+
rb_raise(rb_eNoMemError, "Not enough memory.");
|
|
851
855
|
}
|
|
852
|
-
|
|
856
|
+
return rb_utf8_str_new_cstr(arg->out->buf);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
static VALUE out_free_ensure(VALUE out) {
|
|
860
|
+
oj_out_free((Out)out);
|
|
861
|
+
|
|
862
|
+
return Qnil;
|
|
863
|
+
}
|
|
853
864
|
|
|
854
|
-
|
|
865
|
+
VALUE oj_dump_obj_to_str(VALUE obj, Options copts, Out out, int argc, VALUE *argv) {
|
|
866
|
+
struct dump_str_arg arg = {obj, copts, out, argc, argv};
|
|
855
867
|
|
|
868
|
+
return rb_ensure(dump_str_body, (VALUE)&arg, out_free_ensure, (VALUE)out);
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
struct write_arg {
|
|
872
|
+
VALUE obj;
|
|
873
|
+
VALUE stream;
|
|
874
|
+
const char *path;
|
|
875
|
+
Options copts;
|
|
876
|
+
Out out;
|
|
877
|
+
};
|
|
878
|
+
|
|
879
|
+
static VALUE write_file_body(VALUE a) {
|
|
880
|
+
struct write_arg *arg = (struct write_arg *)a;
|
|
881
|
+
Out out = arg->out;
|
|
882
|
+
size_t size;
|
|
883
|
+
FILE *f;
|
|
884
|
+
int ok;
|
|
885
|
+
|
|
886
|
+
oj_dump_obj_to_json(arg->obj, arg->copts, out);
|
|
887
|
+
size = out->cur - out->buf;
|
|
888
|
+
if (0 == (f = fopen(arg->path, "w"))) {
|
|
889
|
+
rb_raise(rb_eIOError, "%s", strerror(errno));
|
|
890
|
+
}
|
|
891
|
+
ok = (size == fwrite(out->buf, 1, size, f));
|
|
856
892
|
if (!ok) {
|
|
857
893
|
int err = ferror(f);
|
|
858
894
|
fclose(f);
|
|
@@ -860,6 +896,18 @@ void oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
|
|
860
896
|
rb_raise(rb_eIOError, "Write failed. [%d:%s]", err, strerror(err));
|
|
861
897
|
}
|
|
862
898
|
fclose(f);
|
|
899
|
+
|
|
900
|
+
return Qnil;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
void oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
|
904
|
+
struct _out out;
|
|
905
|
+
struct write_arg arg = {obj, Qnil, path, copts, &out};
|
|
906
|
+
|
|
907
|
+
oj_out_init(&out);
|
|
908
|
+
|
|
909
|
+
out.omit_nil = copts->dump_opts.omit_nil;
|
|
910
|
+
rb_ensure(write_file_body, (VALUE)&arg, out_free_ensure, (VALUE)&out);
|
|
863
911
|
}
|
|
864
912
|
|
|
865
913
|
#if !IS_WINDOWS
|
|
@@ -879,22 +927,21 @@ static void write_ready(int fd) {
|
|
|
879
927
|
}
|
|
880
928
|
#endif
|
|
881
929
|
|
|
882
|
-
|
|
883
|
-
struct
|
|
884
|
-
|
|
885
|
-
VALUE
|
|
930
|
+
static VALUE write_stream_body(VALUE a) {
|
|
931
|
+
struct write_arg *arg = (struct write_arg *)a;
|
|
932
|
+
Out out = arg->out;
|
|
933
|
+
VALUE stream = arg->stream;
|
|
934
|
+
ssize_t size;
|
|
935
|
+
VALUE clas = rb_obj_class(stream);
|
|
886
936
|
#if !IS_WINDOWS
|
|
887
937
|
int fd;
|
|
888
938
|
VALUE s;
|
|
889
939
|
#endif
|
|
890
940
|
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
out.omit_nil = copts->dump_opts.omit_nil;
|
|
894
|
-
oj_dump_obj_to_json(obj, copts, &out);
|
|
895
|
-
size = out.cur - out.buf;
|
|
941
|
+
oj_dump_obj_to_json(arg->obj, arg->copts, out);
|
|
942
|
+
size = out->cur - out->buf;
|
|
896
943
|
if (oj_stringio_class == clas) {
|
|
897
|
-
rb_funcall(stream, oj_write_id, 1, rb_str_new(out
|
|
944
|
+
rb_funcall(stream, oj_write_id, 1, rb_str_new(out->buf, size));
|
|
898
945
|
#if !IS_WINDOWS
|
|
899
946
|
} else if (rb_respond_to(stream, oj_fileno_id) && Qnil != (s = rb_funcall(stream, oj_fileno_id, 0)) &&
|
|
900
947
|
0 != (fd = FIX2INT(s))) {
|
|
@@ -902,7 +949,7 @@ void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
|
902
949
|
ssize_t total = 0;
|
|
903
950
|
|
|
904
951
|
while (true) {
|
|
905
|
-
if (0 > (cnt = write(fd, out
|
|
952
|
+
if (0 > (cnt = write(fd, out->buf + total, size - total))) {
|
|
906
953
|
if (EAGAIN != errno) {
|
|
907
954
|
rb_raise(rb_eIOError, "write failed. %d %s.", errno, strerror(errno));
|
|
908
955
|
break;
|
|
@@ -917,22 +964,32 @@ void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
|
917
964
|
}
|
|
918
965
|
#endif
|
|
919
966
|
} else if (rb_respond_to(stream, oj_write_id)) {
|
|
920
|
-
rb_funcall(stream, oj_write_id, 1, rb_str_new(out
|
|
967
|
+
rb_funcall(stream, oj_write_id, 1, rb_str_new(out->buf, size));
|
|
921
968
|
} else {
|
|
922
|
-
oj_out_free(&out);
|
|
923
969
|
rb_raise(rb_eArgError, "to_stream() expected an IO Object.");
|
|
924
970
|
}
|
|
925
|
-
|
|
971
|
+
return Qnil;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
975
|
+
struct _out out;
|
|
976
|
+
struct write_arg arg = {obj, stream, NULL, copts, &out};
|
|
977
|
+
|
|
978
|
+
oj_out_init(&out);
|
|
979
|
+
|
|
980
|
+
out.omit_nil = copts->dump_opts.omit_nil;
|
|
981
|
+
rb_ensure(write_stream_body, (VALUE)&arg, out_free_ensure, (VALUE)&out);
|
|
926
982
|
}
|
|
927
983
|
|
|
928
984
|
void oj_dump_str(VALUE obj, int depth, Out out, bool as_ok) {
|
|
929
985
|
int idx = RB_ENCODING_GET(obj);
|
|
930
986
|
|
|
931
|
-
if (oj_utf8_encoding_index != idx) {
|
|
987
|
+
if (oj_utf8_encoding_index != idx && !rb_enc_str_asciionly_p(obj)) {
|
|
932
988
|
rb_encoding *enc = rb_enc_from_index(idx);
|
|
933
989
|
obj = rb_str_conv_enc(obj, enc, oj_utf8_encoding);
|
|
934
990
|
}
|
|
935
991
|
oj_dump_cstr(RSTRING_PTR(obj), RSTRING_LEN(obj), 0, 0, out);
|
|
992
|
+
RB_GC_GUARD(obj);
|
|
936
993
|
}
|
|
937
994
|
|
|
938
995
|
void oj_dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
|
|
@@ -968,6 +1025,7 @@ void oj_dump_raw_json(VALUE obj, int depth, Out out) {
|
|
|
968
1025
|
if (0 < len) {
|
|
969
1026
|
len--;
|
|
970
1027
|
}
|
|
1028
|
+
assure_size(out, len + 10);
|
|
971
1029
|
oj_dump_raw(sw->out.buf, len, out);
|
|
972
1030
|
} else {
|
|
973
1031
|
volatile VALUE jv;
|
|
@@ -975,6 +1033,7 @@ void oj_dump_raw_json(VALUE obj, int depth, Out out) {
|
|
|
975
1033
|
TRACE(out->opts->trace, "raw_json", obj, depth + 1, TraceRubyIn);
|
|
976
1034
|
jv = rb_funcall(obj, oj_raw_json_id, 2, RB_INT2NUM(depth), RB_INT2NUM(out->indent));
|
|
977
1035
|
TRACE(out->opts->trace, "raw_json", obj, depth + 1, TraceRubyOut);
|
|
1036
|
+
StringValue(jv);
|
|
978
1037
|
oj_dump_raw(RSTRING_PTR(jv), (size_t)RSTRING_LEN(jv), out);
|
|
979
1038
|
}
|
|
980
1039
|
}
|
|
@@ -1461,12 +1520,17 @@ void oj_out_init(Out out) {
|
|
|
1461
1520
|
out->end = out->buf + sizeof(out->stack_buffer) - BUFFER_EXTRA;
|
|
1462
1521
|
out->allocated = false;
|
|
1463
1522
|
out->key_filter_off = false;
|
|
1523
|
+
out->circ_cache = NULL;
|
|
1464
1524
|
}
|
|
1465
1525
|
|
|
1466
1526
|
void oj_out_free(Out out) {
|
|
1467
1527
|
if (out->allocated) {
|
|
1468
1528
|
OJ_R_FREE(out->buf); // TBD
|
|
1469
1529
|
}
|
|
1530
|
+
if (NULL != out->circ_cache) {
|
|
1531
|
+
oj_cache8_delete(out->circ_cache);
|
|
1532
|
+
out->circ_cache = NULL;
|
|
1533
|
+
}
|
|
1470
1534
|
}
|
|
1471
1535
|
|
|
1472
1536
|
void oj_grow_out(Out out, size_t len) {
|
data/ext/oj/dump_compat.c
CHANGED
|
@@ -321,7 +321,7 @@ static void exception_alt(VALUE obj, int depth, Out out) {
|
|
|
321
321
|
if (0 < out->opts->dump_opts.after_size) {
|
|
322
322
|
APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
|
|
323
323
|
}
|
|
324
|
-
|
|
324
|
+
oj_dump_compat_val(rb_funcall(obj, message_id, 0), depth + 1, out, true);
|
|
325
325
|
assure_size(out, size + sep_len + 6);
|
|
326
326
|
*out->cur++ = ',';
|
|
327
327
|
fill_indent(out, d3);
|
|
@@ -470,9 +470,6 @@ oj_add_to_json(int argc, VALUE *argv, VALUE self) {
|
|
|
470
470
|
|
|
471
471
|
if (0 == argc) {
|
|
472
472
|
for (a = oj_compat_codes; NULL != a->name; a++) {
|
|
473
|
-
if (Qnil == a->clas || Qundef == a->clas) {
|
|
474
|
-
a->clas = rb_const_get_at(rb_cObject, rb_intern(a->name));
|
|
475
|
-
}
|
|
476
473
|
a->active = true;
|
|
477
474
|
}
|
|
478
475
|
use_struct_alt = true;
|
|
@@ -503,10 +500,7 @@ oj_add_to_json(int argc, VALUE *argv, VALUE self) {
|
|
|
503
500
|
continue;
|
|
504
501
|
}
|
|
505
502
|
for (a = oj_compat_codes; NULL != a->name; a++) {
|
|
506
|
-
if (
|
|
507
|
-
a->clas = rb_const_get_at(rb_cObject, rb_intern(a->name));
|
|
508
|
-
}
|
|
509
|
-
if (*argv == a->clas) {
|
|
503
|
+
if (*argv == oj_code_class(a)) {
|
|
510
504
|
a->active = true;
|
|
511
505
|
break;
|
|
512
506
|
}
|
|
@@ -563,12 +557,15 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
563
557
|
size_t cnt = 0;
|
|
564
558
|
|
|
565
559
|
if (0.0 == d) {
|
|
566
|
-
b
|
|
560
|
+
b = buf;
|
|
561
|
+
if (signbit(d)) {
|
|
562
|
+
*b++ = '-';
|
|
563
|
+
}
|
|
567
564
|
*b++ = '0';
|
|
568
565
|
*b++ = '.';
|
|
569
566
|
*b++ = '0';
|
|
570
|
-
*b
|
|
571
|
-
cnt =
|
|
567
|
+
*b = '\0';
|
|
568
|
+
cnt = b - buf;
|
|
572
569
|
} else if (OJ_INFINITY == d) {
|
|
573
570
|
if (WordNan == out->opts->dump_opts.nan_dump) {
|
|
574
571
|
strcpy(buf, "Infinity");
|
data/ext/oj/dump_object.c
CHANGED
|
@@ -143,6 +143,7 @@ static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
|
|
|
143
143
|
cnt--;
|
|
144
144
|
for (i = 0; i <= cnt; i++) {
|
|
145
145
|
if (out->opts->dump_opts.use) {
|
|
146
|
+
assure_size(out, size);
|
|
146
147
|
if (0 < out->opts->dump_opts.array_size) {
|
|
147
148
|
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
|
148
149
|
}
|
|
@@ -160,7 +161,7 @@ static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
|
|
|
160
161
|
*out->cur++ = ',';
|
|
161
162
|
}
|
|
162
163
|
}
|
|
163
|
-
size = depth
|
|
164
|
+
size = indent_len(out, depth, out->opts->dump_opts.array_size) + 1;
|
|
164
165
|
assure_size(out, size);
|
|
165
166
|
if (out->opts->dump_opts.use) {
|
|
166
167
|
// printf("*** d2: %u indent: %u '%s'\n", d2, out->opts->dump_opts->indent_size,
|
|
@@ -350,7 +351,7 @@ static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
|
|
|
350
351
|
} else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
|
|
351
352
|
return ST_CONTINUE;
|
|
352
353
|
}
|
|
353
|
-
if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
|
|
354
|
+
if ('@' != *attr && (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr) || 0 == strcmp("bt_locations", attr))) {
|
|
354
355
|
return ST_CONTINUE;
|
|
355
356
|
}
|
|
356
357
|
assure_size(out, size);
|
|
@@ -611,6 +612,10 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
611
612
|
APPEND_CHARS(out->cur, name, len);
|
|
612
613
|
*out->cur++ = '"';
|
|
613
614
|
}
|
|
615
|
+
if (2 == cnt && rb_obj_is_kind_of(obj, rb_cRange)) {
|
|
616
|
+
assure_size(out, 8);
|
|
617
|
+
APPEND_CHARS(out->cur, ",\"excl\"", 7);
|
|
618
|
+
}
|
|
614
619
|
*out->cur++ = ']';
|
|
615
620
|
} else {
|
|
616
621
|
fill_indent(out, d3);
|
|
@@ -644,6 +649,17 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
644
649
|
oj_dump_obj_val(v, d3, out);
|
|
645
650
|
*out->cur++ = ',';
|
|
646
651
|
}
|
|
652
|
+
if (2 == cnt && rb_obj_is_kind_of(obj, rb_cRange)) {
|
|
653
|
+
VALUE beg;
|
|
654
|
+
VALUE end;
|
|
655
|
+
int excl;
|
|
656
|
+
|
|
657
|
+
rb_range_values(obj, &beg, &end, &excl);
|
|
658
|
+
assure_size(out, size);
|
|
659
|
+
fill_indent(out, d3);
|
|
660
|
+
oj_dump_obj_val(excl ? Qtrue : Qfalse, d3, out);
|
|
661
|
+
*out->cur++ = ',';
|
|
662
|
+
}
|
|
647
663
|
}
|
|
648
664
|
#else
|
|
649
665
|
{
|
data/ext/oj/dump_strict.c
CHANGED
|
@@ -135,6 +135,7 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
|
135
135
|
cnt--;
|
|
136
136
|
for (i = 0; i <= cnt; i++) {
|
|
137
137
|
if (out->opts->dump_opts.use) {
|
|
138
|
+
assure_size(out, size);
|
|
138
139
|
if (0 < out->opts->dump_opts.array_size) {
|
|
139
140
|
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
|
140
141
|
}
|
|
@@ -156,7 +157,7 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
|
156
157
|
*out->cur++ = ',';
|
|
157
158
|
}
|
|
158
159
|
}
|
|
159
|
-
size = depth
|
|
160
|
+
size = indent_len(out, depth, out->opts->dump_opts.array_size) + 1;
|
|
160
161
|
assure_size(out, size);
|
|
161
162
|
if (out->opts->dump_opts.use) {
|
|
162
163
|
// printf("*** d2: %u indent: %u '%s'\n", d2, out->opts->dump_opts->indent_size,
|
data/ext/oj/extconf.rb
CHANGED
|
@@ -31,8 +31,8 @@ have_func('stpcpy')
|
|
|
31
31
|
have_func('pthread_mutex_init')
|
|
32
32
|
have_func('getrlimit', 'sys/resource.h')
|
|
33
33
|
have_func('rb_enc_interned_str')
|
|
34
|
+
have_func('rb_hash_new_capa', 'ruby.h')
|
|
34
35
|
have_func('rb_ext_ractor_safe', 'ruby.h')
|
|
35
|
-
have_func('rb_hash_start', 'ruby.h')
|
|
36
36
|
|
|
37
37
|
dflags['OJ_DEBUG'] = true unless ENV['OJ_DEBUG'].nil?
|
|
38
38
|
|
|
@@ -48,6 +48,12 @@ if try_cflags('-msse2')
|
|
|
48
48
|
$CPPFLAGS += ' -msse2'
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
+
# Ensure C99 mode for compilers that default to C90 (e.g. GCC 4.x).
|
|
52
|
+
# simd.h uses C99 for-loop declarations that fail under -std=gnu90.
|
|
53
|
+
if !$CFLAGS.include?('-std=') && try_cflags('-std=gnu99')
|
|
54
|
+
$CFLAGS += ' -std=gnu99'
|
|
55
|
+
end
|
|
56
|
+
|
|
51
57
|
if enable_config('trace-log', false)
|
|
52
58
|
dflags['OJ_ENABLE_TRACE_LOG'] = 1
|
|
53
59
|
end
|
data/ext/oj/fast.c
CHANGED
|
@@ -838,8 +838,10 @@ static VALUE parse_json(VALUE clas, char *json, bool given) {
|
|
|
838
838
|
// The doc is detached from its wrapper so the GC will not free it.
|
|
839
839
|
// doc_free() releases both the doc and its json buffer (doc->json), so
|
|
840
840
|
// the caller must not free json separately.
|
|
841
|
-
DATA_PTR(
|
|
842
|
-
|
|
841
|
+
if (NULL != DATA_PTR(self)) {
|
|
842
|
+
DATA_PTR(self) = NULL;
|
|
843
|
+
doc_free(doc);
|
|
844
|
+
}
|
|
843
845
|
} else {
|
|
844
846
|
result = doc->self;
|
|
845
847
|
}
|
|
@@ -1034,8 +1036,8 @@ static int move_step(Doc doc, const char *path, int loc) {
|
|
|
1034
1036
|
doc->where--;
|
|
1035
1037
|
loc = move_step(doc, path, loc + 1);
|
|
1036
1038
|
if (0 != loc) {
|
|
1037
|
-
*doc->where = init;
|
|
1038
1039
|
doc->where++;
|
|
1040
|
+
*doc->where = init;
|
|
1039
1041
|
}
|
|
1040
1042
|
} else if (COL_VAL == leaf->value_type && 0 != leaf->elements) {
|
|
1041
1043
|
Leaf first = leaf->elements->next;
|
|
@@ -1179,19 +1181,24 @@ static VALUE doc_open_file(VALUE clas, VALUE filename) {
|
|
|
1179
1181
|
volatile VALUE obj;
|
|
1180
1182
|
int given = rb_block_given_p();
|
|
1181
1183
|
|
|
1182
|
-
path =
|
|
1184
|
+
path = StringValueCStr(filename);
|
|
1183
1185
|
// Open in binary mode. On Windows a text mode read translates CRLF into LF
|
|
1184
1186
|
// so fewer bytes are read than the file size reported by ftell().
|
|
1185
1187
|
if (0 == (f = fopen(path, "rb"))) {
|
|
1186
1188
|
rb_raise(rb_eIOError, "%s", strerror(errno));
|
|
1187
1189
|
}
|
|
1188
1190
|
fseek(f, 0, SEEK_END);
|
|
1189
|
-
len
|
|
1191
|
+
len = ftell(f);
|
|
1192
|
+
if ((size_t)-1 == len) {
|
|
1193
|
+
fclose(f);
|
|
1194
|
+
rb_raise(rb_const_get_at(Oj, rb_intern("LoadError")), "Failed to get the size of %s.", path);
|
|
1195
|
+
}
|
|
1190
1196
|
json = OJ_R_ALLOC_N(char, len + 1);
|
|
1191
1197
|
|
|
1192
1198
|
fseek(f, 0, SEEK_SET);
|
|
1193
1199
|
if (len != fread(json, 1, len, f)) {
|
|
1194
1200
|
fclose(f);
|
|
1201
|
+
OJ_R_FREE(json);
|
|
1195
1202
|
rb_raise(rb_const_get_at(Oj, rb_intern("LoadError")),
|
|
1196
1203
|
"Failed to read %lu bytes from %s.",
|
|
1197
1204
|
(unsigned long)len,
|
|
@@ -1344,7 +1351,7 @@ static VALUE doc_home(VALUE self) {
|
|
|
1344
1351
|
* Oj::Doc.open('[1,2]') { |doc| doc.type('/1') } #=> Fixnum
|
|
1345
1352
|
*/
|
|
1346
1353
|
static VALUE doc_type(int argc, VALUE *argv, VALUE self) {
|
|
1347
|
-
Doc doc
|
|
1354
|
+
Doc doc;
|
|
1348
1355
|
Leaf leaf;
|
|
1349
1356
|
const char *path = 0;
|
|
1350
1357
|
VALUE type = Qnil;
|
|
@@ -1352,6 +1359,7 @@ static VALUE doc_type(int argc, VALUE *argv, VALUE self) {
|
|
|
1352
1359
|
if (1 <= argc) {
|
|
1353
1360
|
path = StringValuePtr(*argv);
|
|
1354
1361
|
}
|
|
1362
|
+
doc = self_doc(self);
|
|
1355
1363
|
if (0 != (leaf = get_doc_leaf(doc, path))) {
|
|
1356
1364
|
switch (leaf->rtype) {
|
|
1357
1365
|
case T_NIL: type = rb_cNilClass; break;
|
|
@@ -1387,13 +1395,13 @@ static VALUE doc_fetch(int argc, VALUE *argv, VALUE self) {
|
|
|
1387
1395
|
volatile VALUE val = Qnil;
|
|
1388
1396
|
const char *path = 0;
|
|
1389
1397
|
|
|
1390
|
-
doc = self_doc(self);
|
|
1391
1398
|
if (1 <= argc) {
|
|
1392
1399
|
path = StringValuePtr(*argv);
|
|
1393
1400
|
if (2 == argc) {
|
|
1394
1401
|
val = argv[1];
|
|
1395
1402
|
}
|
|
1396
1403
|
}
|
|
1404
|
+
doc = self_doc(self);
|
|
1397
1405
|
if (0 != (leaf = get_doc_leaf(doc, path))) {
|
|
1398
1406
|
val = leaf_value(doc, leaf);
|
|
1399
1407
|
}
|
|
@@ -1409,11 +1417,11 @@ static VALUE doc_fetch(int argc, VALUE *argv, VALUE self) {
|
|
|
1409
1417
|
* Oj::Doc.open('[1,2]') { |doc| doc.exists?('/3') } #=> false
|
|
1410
1418
|
*/
|
|
1411
1419
|
static VALUE doc_exists(VALUE self, VALUE str) {
|
|
1412
|
-
|
|
1413
|
-
|
|
1420
|
+
const char *path = StringValuePtr(str);
|
|
1421
|
+
Doc doc = self_doc(self);
|
|
1422
|
+
Leaf leaf;
|
|
1414
1423
|
|
|
1415
|
-
|
|
1416
|
-
if (0 != (leaf = get_doc_leaf(doc, StringValuePtr(str)))) {
|
|
1424
|
+
if (0 != (leaf = get_doc_leaf(doc, path))) {
|
|
1417
1425
|
if (NULL != leaf) {
|
|
1418
1426
|
return Qtrue;
|
|
1419
1427
|
}
|
|
@@ -1440,16 +1448,19 @@ static VALUE doc_exists(VALUE self, VALUE str) {
|
|
|
1440
1448
|
static VALUE doc_each_leaf(int argc, VALUE *argv, VALUE self) {
|
|
1441
1449
|
if (rb_block_given_p()) {
|
|
1442
1450
|
Leaf save_path[MAX_STACK];
|
|
1443
|
-
Doc doc
|
|
1451
|
+
Doc doc;
|
|
1444
1452
|
const char *path = 0;
|
|
1445
1453
|
size_t wlen;
|
|
1446
1454
|
|
|
1455
|
+
if (1 <= argc) {
|
|
1456
|
+
path = StringValuePtr(*argv);
|
|
1457
|
+
}
|
|
1458
|
+
doc = self_doc(self);
|
|
1447
1459
|
wlen = doc->where - doc->where_path;
|
|
1448
1460
|
if (0 < wlen) {
|
|
1449
1461
|
memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
|
|
1450
1462
|
}
|
|
1451
|
-
if (
|
|
1452
|
-
path = StringValuePtr(*argv);
|
|
1463
|
+
if (0 != path) {
|
|
1453
1464
|
if ('/' == *path) {
|
|
1454
1465
|
doc->where = doc->where_path;
|
|
1455
1466
|
path++;
|
|
@@ -1482,11 +1493,10 @@ static VALUE doc_each_leaf(int argc, VALUE *argv, VALUE self) {
|
|
|
1482
1493
|
* "/one/2"
|
|
1483
1494
|
*/
|
|
1484
1495
|
static VALUE doc_move(VALUE self, VALUE str) {
|
|
1485
|
-
|
|
1486
|
-
|
|
1496
|
+
const char *path = StringValuePtr(str);
|
|
1497
|
+
Doc doc = self_doc(self);
|
|
1487
1498
|
int loc;
|
|
1488
1499
|
|
|
1489
|
-
path = StringValuePtr(str);
|
|
1490
1500
|
if ('/' == *path) {
|
|
1491
1501
|
doc->where = doc->where_path;
|
|
1492
1502
|
path++;
|
|
@@ -1517,17 +1527,21 @@ static VALUE doc_move(VALUE self, VALUE str) {
|
|
|
1517
1527
|
static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
|
|
1518
1528
|
if (rb_block_given_p()) {
|
|
1519
1529
|
Leaf save_path[MAX_STACK];
|
|
1520
|
-
Doc doc
|
|
1530
|
+
Doc doc;
|
|
1521
1531
|
const char *path = 0;
|
|
1522
1532
|
size_t wlen;
|
|
1523
|
-
Leaf *where_orig
|
|
1533
|
+
Leaf *where_orig;
|
|
1524
1534
|
|
|
1525
|
-
|
|
1535
|
+
if (1 <= argc) {
|
|
1536
|
+
path = StringValuePtr(*argv);
|
|
1537
|
+
}
|
|
1538
|
+
doc = self_doc(self);
|
|
1539
|
+
where_orig = doc->where;
|
|
1540
|
+
wlen = doc->where - doc->where_path;
|
|
1526
1541
|
if (0 < wlen) {
|
|
1527
1542
|
memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
|
|
1528
1543
|
}
|
|
1529
|
-
if (
|
|
1530
|
-
path = StringValuePtr(*argv);
|
|
1544
|
+
if (0 != path) {
|
|
1531
1545
|
if ('/' == *path) {
|
|
1532
1546
|
doc->where = doc->where_path;
|
|
1533
1547
|
path++;
|
|
@@ -1595,13 +1609,14 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
|
|
|
1595
1609
|
*/
|
|
1596
1610
|
static VALUE doc_each_value(int argc, VALUE *argv, VALUE self) {
|
|
1597
1611
|
if (rb_block_given_p()) {
|
|
1598
|
-
Doc doc
|
|
1612
|
+
Doc doc;
|
|
1599
1613
|
const char *path = 0;
|
|
1600
1614
|
Leaf leaf;
|
|
1601
1615
|
|
|
1602
1616
|
if (1 <= argc) {
|
|
1603
1617
|
path = StringValuePtr(*argv);
|
|
1604
1618
|
}
|
|
1619
|
+
doc = self_doc(self);
|
|
1605
1620
|
if (0 != (leaf = get_doc_leaf(doc, path))) {
|
|
1606
1621
|
each_value(doc, leaf, self);
|
|
1607
1622
|
}
|
|
@@ -1624,19 +1639,23 @@ static VALUE doc_each_value(int argc, VALUE *argv, VALUE self) {
|
|
|
1624
1639
|
* #=> "[2,1]"
|
|
1625
1640
|
*/
|
|
1626
1641
|
static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
|
|
1627
|
-
Doc doc
|
|
1642
|
+
Doc doc;
|
|
1628
1643
|
Leaf leaf;
|
|
1629
1644
|
const char *path = 0;
|
|
1630
1645
|
const char *filename = 0;
|
|
1631
1646
|
|
|
1632
1647
|
if (1 <= argc) {
|
|
1633
1648
|
if (Qnil != *argv) {
|
|
1634
|
-
|
|
1649
|
+
StringValue(*argv);
|
|
1635
1650
|
}
|
|
1636
1651
|
if (2 <= argc) {
|
|
1637
|
-
filename =
|
|
1652
|
+
filename = StringValueCStr(argv[1]);
|
|
1653
|
+
}
|
|
1654
|
+
if (Qnil != *argv) {
|
|
1655
|
+
path = RSTRING_PTR(*argv);
|
|
1638
1656
|
}
|
|
1639
1657
|
}
|
|
1658
|
+
doc = self_doc(self);
|
|
1640
1659
|
if (0 != (leaf = get_doc_leaf(doc, path))) {
|
|
1641
1660
|
volatile VALUE rjson;
|
|
1642
1661
|
|
|
@@ -1668,9 +1687,7 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
|
|
|
1668
1687
|
* Oj::Doc.open('[1,2,3]') { |doc| doc.size() } #=> 4
|
|
1669
1688
|
*/
|
|
1670
1689
|
static VALUE doc_size(VALUE self) {
|
|
1671
|
-
|
|
1672
|
-
TypedData_Get_Struct(self, struct _doc, &oj_doc_type, d);
|
|
1673
|
-
return ULONG2NUM(d->size);
|
|
1690
|
+
return ULONG2NUM(self_doc(self)->size);
|
|
1674
1691
|
}
|
|
1675
1692
|
|
|
1676
1693
|
/* @overload close() => nil
|