oj 3.13.9 → 3.16.1
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 +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);
|