oj 3.13.9 → 3.16.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +101 -0
- data/README.md +13 -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 +19 -33
- data/ext/oj/code.h +2 -2
- data/ext/oj/compat.c +20 -60
- data/ext/oj/custom.c +76 -155
- data/ext/oj/debug.c +3 -9
- data/ext/oj/dump.c +203 -213
- data/ext/oj/dump.h +26 -12
- data/ext/oj/dump_compat.c +565 -642
- data/ext/oj/dump_leaf.c +17 -63
- data/ext/oj/dump_object.c +59 -181
- data/ext/oj/dump_strict.c +24 -48
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/err.c +2 -13
- data/ext/oj/err.h +9 -12
- data/ext/oj/extconf.rb +18 -7
- data/ext/oj/fast.c +83 -108
- 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 +104 -81
- data/ext/oj/object.c +50 -67
- data/ext/oj/odd.c +89 -67
- data/ext/oj/odd.h +15 -15
- data/ext/oj/oj.c +171 -106
- data/ext/oj/oj.h +96 -74
- data/ext/oj/parse.c +169 -189
- data/ext/oj/parse.h +23 -24
- data/ext/oj/parser.c +89 -34
- data/ext/oj/parser.h +20 -9
- data/ext/oj/rails.c +86 -151
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +12 -15
- 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 +21 -32
- 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 -22
- 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 +32 -69
- data/lib/oj/active_support_helper.rb +1 -3
- 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 +162 -150
- data/lib/oj/mimic.rb +6 -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/JsonGem.md +15 -0
- data/pages/Modes.md +6 -3
- data/pages/Options.md +10 -0
- data/pages/Rails.md +12 -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 +15 -15
- 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 +8 -6
- 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 +49 -37
- 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 +95 -43
- data/test/test_custom.rb +72 -51
- data/test/test_debian.rb +7 -10
- data/test/test_fast.rb +102 -87
- 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 +40 -32
- data/test/test_various.rb +163 -84
- data/test/test_wab.rb +48 -44
- data/test/test_writer.rb +47 -47
- data/test/tests.rb +13 -5
- data/test/tests_mimic.rb +12 -3
- data/test/tests_mimic_addition.rb +12 -3
- metadata +34 -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/fast.c
CHANGED
@@ -11,13 +11,15 @@
|
|
11
11
|
#include <stdlib.h>
|
12
12
|
#include <string.h>
|
13
13
|
|
14
|
+
#include "dump.h"
|
14
15
|
#include "encode.h"
|
16
|
+
#include "mem.h"
|
15
17
|
#include "oj.h"
|
16
18
|
|
17
19
|
// maximum to allocate on the stack, arbitrary limit
|
18
20
|
#define SMALL_JSON 65536
|
19
21
|
#define MAX_STACK 100
|
20
|
-
|
22
|
+
// #define BATCH_SIZE (4096 / sizeof(struct _leaf) - 1)
|
21
23
|
#define BATCH_SIZE 100
|
22
24
|
|
23
25
|
// Support for compaction
|
@@ -31,25 +33,25 @@ typedef struct _batch {
|
|
31
33
|
struct _batch *next;
|
32
34
|
int next_avail;
|
33
35
|
struct _leaf leaves[BATCH_SIZE];
|
34
|
-
} *
|
36
|
+
} *Batch;
|
35
37
|
|
36
38
|
typedef struct _doc {
|
37
39
|
Leaf data;
|
38
|
-
Leaf
|
40
|
+
Leaf *where; // points to current location
|
39
41
|
Leaf where_path[MAX_STACK]; // points to head of path
|
40
|
-
char
|
41
|
-
unsigned long size;
|
42
|
+
char *json;
|
43
|
+
unsigned long size; // number of leaves/branches in the doc
|
42
44
|
VALUE self;
|
43
45
|
Batch batches;
|
44
46
|
struct _batch batch0;
|
45
|
-
} *
|
47
|
+
} *Doc;
|
46
48
|
|
47
49
|
typedef struct _parseInfo {
|
48
50
|
char *str; // buffer being read from
|
49
51
|
char *s; // current position in buffer
|
50
52
|
Doc doc;
|
51
53
|
void *stack_min;
|
52
|
-
} *
|
54
|
+
} *ParseInfo;
|
53
55
|
|
54
56
|
static void leaf_init(Leaf leaf, int type);
|
55
57
|
static Leaf leaf_new(Doc doc, int type);
|
@@ -73,7 +75,7 @@ static char *read_quoted_value(ParseInfo pi);
|
|
73
75
|
static void skip_comment(ParseInfo pi);
|
74
76
|
|
75
77
|
static VALUE protect_open_proc(VALUE x);
|
76
|
-
static VALUE parse_json(VALUE clas, char *json, bool given
|
78
|
+
static VALUE parse_json(VALUE clas, char *json, bool given);
|
77
79
|
static void each_leaf(Doc doc, VALUE self);
|
78
80
|
static int move_step(Doc doc, const char *path, int loc);
|
79
81
|
static Leaf get_doc_leaf(Doc doc, const char *path);
|
@@ -112,10 +114,7 @@ inline static char *ulong_fill(char *s, size_t num) {
|
|
112
114
|
char *b = buf + sizeof(buf) - 1;
|
113
115
|
|
114
116
|
*b-- = '\0';
|
115
|
-
|
116
|
-
*b = (num % 10) + '0';
|
117
|
-
}
|
118
|
-
b++;
|
117
|
+
b = oj_longlong_to_string((long long)num, false, b);
|
119
118
|
if ('\0' == *b) {
|
120
119
|
b--;
|
121
120
|
*b = '0';
|
@@ -159,7 +158,7 @@ inline static Leaf leaf_new(Doc doc, int type) {
|
|
159
158
|
Leaf leaf;
|
160
159
|
|
161
160
|
if (0 == doc->batches || BATCH_SIZE == doc->batches->next_avail) {
|
162
|
-
Batch b =
|
161
|
+
Batch b = OJ_R_ALLOC(struct _batch);
|
163
162
|
|
164
163
|
// Initializes all leaves with a NO_VAL value_type
|
165
164
|
memset(b, 0, sizeof(struct _batch));
|
@@ -249,7 +248,7 @@ static void skip_comment(ParseInfo pi) {
|
|
249
248
|
#endif
|
250
249
|
|
251
250
|
static void leaf_fixnum_value(Leaf leaf) {
|
252
|
-
char
|
251
|
+
char *s = leaf->str;
|
253
252
|
int64_t n = 0;
|
254
253
|
int neg = 0;
|
255
254
|
int big = 0;
|
@@ -355,7 +354,7 @@ static Leaf read_next(ParseInfo pi) {
|
|
355
354
|
|
356
355
|
static Leaf read_obj(ParseInfo pi) {
|
357
356
|
Leaf h = leaf_new(pi->doc, T_HASH);
|
358
|
-
char
|
357
|
+
char *end;
|
359
358
|
const char *key = 0;
|
360
359
|
Leaf val = 0;
|
361
360
|
|
@@ -574,7 +573,7 @@ static char *read_quoted_value(ParseInfo pi) {
|
|
574
573
|
char *h = pi->s; // head
|
575
574
|
char *t = h; // tail
|
576
575
|
|
577
|
-
h++;
|
576
|
+
h++; // skip quote character
|
578
577
|
t++;
|
579
578
|
value = h;
|
580
579
|
for (; '"' != *h; h++, t++) {
|
@@ -647,10 +646,11 @@ static void doc_free(Doc doc) {
|
|
647
646
|
while (0 != (b = doc->batches)) {
|
648
647
|
doc->batches = doc->batches->next;
|
649
648
|
if (&doc->batch0 != b) {
|
650
|
-
|
649
|
+
OJ_R_FREE(b);
|
651
650
|
}
|
652
651
|
}
|
653
|
-
|
652
|
+
OJ_R_FREE(doc->json);
|
653
|
+
OJ_R_FREE(doc);
|
654
654
|
}
|
655
655
|
}
|
656
656
|
|
@@ -670,27 +670,28 @@ static void free_doc_cb(void *x) {
|
|
670
670
|
Doc doc = (Doc)x;
|
671
671
|
|
672
672
|
if (0 != doc) {
|
673
|
-
xfree(doc->json);
|
674
673
|
doc_free(doc);
|
675
674
|
}
|
676
675
|
}
|
677
676
|
|
678
677
|
static void mark_leaf(Leaf leaf) {
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
678
|
+
if (NULL != leaf) {
|
679
|
+
switch (leaf->value_type) {
|
680
|
+
case COL_VAL:
|
681
|
+
if (NULL != leaf->elements) {
|
682
|
+
Leaf first = leaf->elements->next;
|
683
|
+
Leaf e = first;
|
684
684
|
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
685
|
+
do {
|
686
|
+
mark_leaf(e);
|
687
|
+
e = e->next;
|
688
|
+
} while (e != first);
|
689
|
+
}
|
690
|
+
break;
|
691
|
+
case RUBY_VAL: mark(leaf->value); break;
|
692
692
|
|
693
|
-
|
693
|
+
default: break;
|
694
|
+
}
|
694
695
|
}
|
695
696
|
}
|
696
697
|
|
@@ -746,20 +747,15 @@ static const rb_data_type_t oj_doc_type = {
|
|
746
747
|
0,
|
747
748
|
};
|
748
749
|
|
749
|
-
static VALUE parse_json(VALUE clas, char *json, bool given
|
750
|
+
static VALUE parse_json(VALUE clas, char *json, bool given) {
|
750
751
|
struct _parseInfo pi;
|
751
752
|
volatile VALUE result = Qnil;
|
752
753
|
Doc doc;
|
753
754
|
int ex = 0;
|
754
755
|
volatile VALUE self;
|
755
756
|
|
756
|
-
|
757
|
+
doc = OJ_R_ALLOC_N(struct _doc, 1);
|
757
758
|
|
758
|
-
if (given) {
|
759
|
-
doc = ALLOCA_N(struct _doc, 1);
|
760
|
-
} else {
|
761
|
-
doc = ALLOC(struct _doc);
|
762
|
-
}
|
763
759
|
// skip UTF-8 BOM if present
|
764
760
|
if (0xEF == (uint8_t)*json && 0xBB == (uint8_t)json[1] && 0xBF == (uint8_t)json[2]) {
|
765
761
|
pi.str = json + 3;
|
@@ -771,7 +767,7 @@ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
|
|
771
767
|
pi.doc = doc;
|
772
768
|
#if IS_WINDOWS
|
773
769
|
// assume a 1M stack and give half to ruby
|
774
|
-
pi.stack_min = (void*)((char*)&pi - (
|
770
|
+
pi.stack_min = (void *)((char *)&pi - (512L * 1024L));
|
775
771
|
#else
|
776
772
|
{
|
777
773
|
struct rlimit lim;
|
@@ -784,18 +780,20 @@ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
|
|
784
780
|
}
|
785
781
|
}
|
786
782
|
#endif
|
783
|
+
doc->json = json;
|
787
784
|
self = TypedData_Wrap_Struct(clas, &oj_doc_type, doc);
|
788
785
|
doc->self = self;
|
789
|
-
doc->json = json;
|
790
786
|
DATA_PTR(doc->self) = doc;
|
791
787
|
result = rb_protect(protect_open_proc, (VALUE)&pi, &ex);
|
792
788
|
if (given || 0 != ex) {
|
793
789
|
DATA_PTR(doc->self) = NULL;
|
790
|
+
// TBD is this needed?
|
791
|
+
/*
|
794
792
|
doc_free(pi.doc);
|
795
|
-
if (
|
796
|
-
|
793
|
+
if (0 != ex) { // will jump so caller will not free
|
794
|
+
OJ_R_FREE(json);
|
797
795
|
}
|
798
|
-
|
796
|
+
*/
|
799
797
|
} else {
|
800
798
|
result = doc->self;
|
801
799
|
}
|
@@ -1085,31 +1083,23 @@ static void each_value(Doc doc, Leaf leaf) {
|
|
1085
1083
|
* doc.close()
|
1086
1084
|
*/
|
1087
1085
|
static VALUE doc_open(VALUE clas, VALUE str) {
|
1088
|
-
char
|
1086
|
+
char *json;
|
1089
1087
|
size_t len;
|
1090
1088
|
volatile VALUE obj;
|
1091
1089
|
int given = rb_block_given_p();
|
1092
|
-
int allocate;
|
1093
1090
|
|
1094
1091
|
Check_Type(str, T_STRING);
|
1095
|
-
len
|
1096
|
-
|
1097
|
-
|
1098
|
-
json = ALLOC_N(char, len);
|
1099
|
-
} else {
|
1100
|
-
json = ALLOCA_N(char, len);
|
1101
|
-
}
|
1102
|
-
// It should not be necessaary to stop GC but if it is not stopped and a
|
1103
|
-
// large string is parsed that string is corrupted or freed during
|
1104
|
-
// parsing. I'm not sure what is going on exactly but disabling GC avoids
|
1105
|
-
// the issue.
|
1106
|
-
rb_gc_disable();
|
1092
|
+
len = (int)RSTRING_LEN(str) + 1;
|
1093
|
+
json = OJ_R_ALLOC_N(char, len);
|
1094
|
+
|
1107
1095
|
memcpy(json, StringValuePtr(str), len);
|
1108
|
-
obj = parse_json(clas, json, given
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1096
|
+
obj = parse_json(clas, json, given);
|
1097
|
+
// TBD is this needed
|
1098
|
+
/*
|
1099
|
+
if (given) {
|
1100
|
+
OJ_R_FREE(json);
|
1112
1101
|
}
|
1102
|
+
*/
|
1113
1103
|
return obj;
|
1114
1104
|
}
|
1115
1105
|
|
@@ -1133,27 +1123,21 @@ static VALUE doc_open(VALUE clas, VALUE str) {
|
|
1133
1123
|
* doc.close()
|
1134
1124
|
*/
|
1135
1125
|
static VALUE doc_open_file(VALUE clas, VALUE filename) {
|
1136
|
-
char
|
1137
|
-
char
|
1138
|
-
FILE
|
1126
|
+
char *path;
|
1127
|
+
char *json;
|
1128
|
+
FILE *f;
|
1139
1129
|
size_t len;
|
1140
1130
|
volatile VALUE obj;
|
1141
1131
|
int given = rb_block_given_p();
|
1142
|
-
int allocate;
|
1143
1132
|
|
1144
|
-
Check_Type(filename, T_STRING);
|
1145
1133
|
path = StringValuePtr(filename);
|
1146
1134
|
if (0 == (f = fopen(path, "r"))) {
|
1147
1135
|
rb_raise(rb_eIOError, "%s", strerror(errno));
|
1148
1136
|
}
|
1149
1137
|
fseek(f, 0, SEEK_END);
|
1150
|
-
len
|
1151
|
-
|
1152
|
-
|
1153
|
-
json = ALLOC_N(char, len + 1);
|
1154
|
-
} else {
|
1155
|
-
json = ALLOCA_N(char, len + 1);
|
1156
|
-
}
|
1138
|
+
len = ftell(f);
|
1139
|
+
json = OJ_R_ALLOC_N(char, len + 1);
|
1140
|
+
|
1157
1141
|
fseek(f, 0, SEEK_SET);
|
1158
1142
|
if (len != fread(json, 1, len, f)) {
|
1159
1143
|
fclose(f);
|
@@ -1164,12 +1148,13 @@ static VALUE doc_open_file(VALUE clas, VALUE filename) {
|
|
1164
1148
|
}
|
1165
1149
|
fclose(f);
|
1166
1150
|
json[len] = '\0';
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
if (given
|
1171
|
-
|
1151
|
+
obj = parse_json(clas, json, given);
|
1152
|
+
// TBD is this needed
|
1153
|
+
/*
|
1154
|
+
if (given) {
|
1155
|
+
OJ_R_FREE(json);
|
1172
1156
|
}
|
1157
|
+
*/
|
1173
1158
|
return obj;
|
1174
1159
|
}
|
1175
1160
|
|
@@ -1209,11 +1194,11 @@ static VALUE doc_where(VALUE self) {
|
|
1209
1194
|
if (0 == *doc->where_path || doc->where == doc->where_path) {
|
1210
1195
|
return oj_slash_string;
|
1211
1196
|
} else {
|
1212
|
-
Leaf
|
1197
|
+
Leaf *lp;
|
1213
1198
|
Leaf leaf;
|
1214
1199
|
size_t size = 3; // leading / and terminating \0
|
1215
|
-
char
|
1216
|
-
char
|
1200
|
+
char *path;
|
1201
|
+
char *p;
|
1217
1202
|
|
1218
1203
|
for (lp = doc->where_path; lp <= doc->where; lp++) {
|
1219
1204
|
leaf = *lp;
|
@@ -1316,7 +1301,6 @@ static VALUE doc_type(int argc, VALUE *argv, VALUE self) {
|
|
1316
1301
|
VALUE type = Qnil;
|
1317
1302
|
|
1318
1303
|
if (1 <= argc) {
|
1319
|
-
Check_Type(*argv, T_STRING);
|
1320
1304
|
path = StringValuePtr(*argv);
|
1321
1305
|
}
|
1322
1306
|
if (0 != (leaf = get_doc_leaf(doc, path))) {
|
@@ -1325,11 +1309,7 @@ static VALUE doc_type(int argc, VALUE *argv, VALUE self) {
|
|
1325
1309
|
case T_TRUE: type = rb_cTrueClass; break;
|
1326
1310
|
case T_FALSE: type = rb_cFalseClass; break;
|
1327
1311
|
case T_STRING: type = rb_cString; break;
|
1328
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
1329
1312
|
case T_FIXNUM: type = rb_cInteger; break;
|
1330
|
-
#else
|
1331
|
-
case T_FIXNUM: type = rb_cFixnum; break;
|
1332
|
-
#endif
|
1333
1313
|
case T_FLOAT: type = rb_cFloat; break;
|
1334
1314
|
case T_ARRAY: type = rb_cArray; break;
|
1335
1315
|
case T_HASH: type = rb_cHash; break;
|
@@ -1356,11 +1336,10 @@ static VALUE doc_fetch(int argc, VALUE *argv, VALUE self) {
|
|
1356
1336
|
Doc doc;
|
1357
1337
|
Leaf leaf;
|
1358
1338
|
volatile VALUE val = Qnil;
|
1359
|
-
const char
|
1339
|
+
const char *path = 0;
|
1360
1340
|
|
1361
1341
|
doc = self_doc(self);
|
1362
1342
|
if (1 <= argc) {
|
1363
|
-
Check_Type(*argv, T_STRING);
|
1364
1343
|
path = StringValuePtr(*argv);
|
1365
1344
|
if (2 == argc) {
|
1366
1345
|
val = argv[1];
|
@@ -1385,7 +1364,6 @@ static VALUE doc_exists(VALUE self, VALUE str) {
|
|
1385
1364
|
Leaf leaf;
|
1386
1365
|
|
1387
1366
|
doc = self_doc(self);
|
1388
|
-
Check_Type(str, T_STRING);
|
1389
1367
|
if (0 != (leaf = get_doc_leaf(doc, StringValuePtr(str)))) {
|
1390
1368
|
if (NULL != leaf) {
|
1391
1369
|
return Qtrue;
|
@@ -1422,7 +1400,6 @@ static VALUE doc_each_leaf(int argc, VALUE *argv, VALUE self) {
|
|
1422
1400
|
memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
|
1423
1401
|
}
|
1424
1402
|
if (1 <= argc) {
|
1425
|
-
Check_Type(*argv, T_STRING);
|
1426
1403
|
path = StringValuePtr(*argv);
|
1427
1404
|
if ('/' == *path) {
|
1428
1405
|
doc->where = doc->where_path;
|
@@ -1457,7 +1434,6 @@ static VALUE doc_move(VALUE self, VALUE str) {
|
|
1457
1434
|
const char *path;
|
1458
1435
|
int loc;
|
1459
1436
|
|
1460
|
-
Check_Type(str, T_STRING);
|
1461
1437
|
path = StringValuePtr(str);
|
1462
1438
|
if ('/' == *path) {
|
1463
1439
|
doc->where = doc->where_path;
|
@@ -1492,13 +1468,13 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
|
|
1492
1468
|
Doc doc = self_doc(self);
|
1493
1469
|
const char *path = 0;
|
1494
1470
|
size_t wlen;
|
1471
|
+
Leaf *where_orig = doc->where;
|
1495
1472
|
|
1496
1473
|
wlen = doc->where - doc->where_path;
|
1497
1474
|
if (0 < wlen) {
|
1498
1475
|
memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
|
1499
1476
|
}
|
1500
1477
|
if (1 <= argc) {
|
1501
|
-
Check_Type(*argv, T_STRING);
|
1502
1478
|
path = StringValuePtr(*argv);
|
1503
1479
|
if ('/' == *path) {
|
1504
1480
|
doc->where = doc->where_path;
|
@@ -1508,9 +1484,13 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
|
|
1508
1484
|
if (0 < wlen) {
|
1509
1485
|
memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
|
1510
1486
|
}
|
1487
|
+
doc->where = where_orig;
|
1511
1488
|
return Qnil;
|
1512
1489
|
}
|
1513
1490
|
}
|
1491
|
+
if (NULL == doc->where || NULL == *doc->where) {
|
1492
|
+
return Qnil;
|
1493
|
+
}
|
1514
1494
|
if (COL_VAL == (*doc->where)->value_type && 0 != (*doc->where)->elements) {
|
1515
1495
|
Leaf first = (*doc->where)->elements->next;
|
1516
1496
|
Leaf e = first;
|
@@ -1525,6 +1505,7 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
|
|
1525
1505
|
if (0 < wlen) {
|
1526
1506
|
memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
|
1527
1507
|
}
|
1508
|
+
doc->where = where_orig;
|
1528
1509
|
}
|
1529
1510
|
return Qnil;
|
1530
1511
|
}
|
@@ -1560,7 +1541,6 @@ static VALUE doc_each_value(int argc, VALUE *argv, VALUE self) {
|
|
1560
1541
|
Leaf leaf;
|
1561
1542
|
|
1562
1543
|
if (1 <= argc) {
|
1563
|
-
Check_Type(*argv, T_STRING);
|
1564
1544
|
path = StringValuePtr(*argv);
|
1565
1545
|
}
|
1566
1546
|
if (0 != (leaf = get_doc_leaf(doc, path))) {
|
@@ -1592,11 +1572,9 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
|
|
1592
1572
|
|
1593
1573
|
if (1 <= argc) {
|
1594
1574
|
if (Qnil != *argv) {
|
1595
|
-
Check_Type(*argv, T_STRING);
|
1596
1575
|
path = StringValuePtr(*argv);
|
1597
1576
|
}
|
1598
1577
|
if (2 <= argc) {
|
1599
|
-
Check_Type(argv[1], T_STRING);
|
1600
1578
|
filename = StringValuePtr(argv[1]);
|
1601
1579
|
}
|
1602
1580
|
}
|
@@ -1604,18 +1582,15 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
|
|
1604
1582
|
volatile VALUE rjson;
|
1605
1583
|
|
1606
1584
|
if (0 == filename) {
|
1607
|
-
char buf[4096];
|
1608
1585
|
struct _out out;
|
1609
1586
|
|
1610
|
-
out
|
1611
|
-
|
1612
|
-
out.
|
1613
|
-
out.omit_nil = oj_default_options.dump_opts.omit_nil;
|
1587
|
+
oj_out_init(&out);
|
1588
|
+
|
1589
|
+
out.omit_nil = oj_default_options.dump_opts.omit_nil;
|
1614
1590
|
oj_dump_leaf_to_json(leaf, &oj_default_options, &out);
|
1615
1591
|
rjson = rb_str_new2(out.buf);
|
1616
|
-
|
1617
|
-
|
1618
|
-
}
|
1592
|
+
|
1593
|
+
oj_out_free(&out);
|
1619
1594
|
} else {
|
1620
1595
|
oj_write_leaf_to_file(leaf, filename, &oj_default_options);
|
1621
1596
|
rjson = Qnil;
|
@@ -1650,11 +1625,9 @@ static VALUE doc_close(VALUE self) {
|
|
1650
1625
|
Doc doc = self_doc(self);
|
1651
1626
|
|
1652
1627
|
rb_gc_unregister_address(&doc->self);
|
1653
|
-
DATA_PTR(doc->self) =
|
1628
|
+
DATA_PTR(doc->self) = NULL;
|
1654
1629
|
if (0 != doc) {
|
1655
|
-
xfree(doc->json);
|
1656
1630
|
doc_free(doc);
|
1657
|
-
xfree(doc);
|
1658
1631
|
}
|
1659
1632
|
return Qnil;
|
1660
1633
|
}
|
@@ -1711,8 +1684,10 @@ static VALUE doc_not_implemented(VALUE self) {
|
|
1711
1684
|
* # Now try again using a path to Oj::Doc.fetch() directly and not using a
|
1712
1685
|
* block. doc = Oj::Doc.open(json) doc.fetch('/2/three') #=> 3 doc.close()
|
1713
1686
|
*/
|
1714
|
-
void oj_init_doc() {
|
1687
|
+
void oj_init_doc(void) {
|
1715
1688
|
oj_doc_class = rb_define_class_under(Oj, "Doc", rb_cObject);
|
1689
|
+
rb_gc_register_address(&oj_doc_class);
|
1690
|
+
rb_undef_alloc_func(oj_doc_class);
|
1716
1691
|
rb_define_singleton_method(oj_doc_class, "open", doc_open, 1);
|
1717
1692
|
rb_define_singleton_method(oj_doc_class, "open_file", doc_open_file, 1);
|
1718
1693
|
rb_define_singleton_method(oj_doc_class, "parse", doc_open, 1);
|