oj 2.0.14 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of oj might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +47 -332
- data/ext/oj/buf.h +103 -0
- data/ext/oj/circarray.c +93 -0
- data/ext/oj/circarray.h +48 -0
- data/ext/oj/compat.c +112 -0
- data/ext/oj/dump.c +2 -1
- data/ext/oj/err.c +82 -0
- data/ext/oj/err.h +64 -0
- data/ext/oj/extconf.rb +1 -0
- data/ext/oj/hash.c +149 -0
- data/ext/oj/{cache.h → hash.h} +9 -10
- data/ext/oj/hash_test.c +501 -0
- data/ext/oj/object.c +514 -0
- data/ext/oj/odd.c +159 -0
- data/ext/oj/odd.h +61 -0
- data/ext/oj/oj.c +235 -305
- data/ext/oj/oj.h +18 -23
- data/ext/oj/parse.c +798 -0
- data/ext/oj/parse.h +88 -0
- data/ext/oj/resolve.c +117 -0
- data/ext/oj/resolve.h +38 -0
- data/ext/oj/saj.c +58 -86
- data/ext/oj/scp.c +308 -0
- data/ext/oj/strict.c +166 -0
- data/ext/oj/val_stack.c +48 -0
- data/ext/oj/val_stack.h +167 -0
- data/lib/oj.rb +1 -0
- data/lib/oj/saj.rb +11 -8
- data/lib/oj/schandler.rb +70 -0
- data/lib/oj/version.rb +1 -1
- data/test/bug.rb +14 -22
- data/test/perf_compat.rb +128 -0
- data/test/{perf_obj.rb → perf_object.rb} +18 -6
- data/test/perf_scp.rb +151 -0
- data/test/perf_strict.rb +23 -122
- data/test/sample.rb +2 -2
- data/test/test_compat.rb +342 -0
- data/test/test_object.rb +390 -0
- data/test/test_saj.rb +1 -1
- data/test/test_scp.rb +224 -0
- data/test/test_strict.rb +250 -0
- data/test/tests.rb +8 -18
- metadata +31 -10
- data/ext/oj/cache.c +0 -148
- data/ext/oj/load.c +0 -1089
- data/test/perf1.rb +0 -64
- data/test/perf2.rb +0 -76
- data/test/perf_obj_old.rb +0 -213
data/ext/oj/odd.c
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
/* odd.c
|
2
|
+
* Copyright (c) 2011, Peter Ohler
|
3
|
+
* All rights reserved.
|
4
|
+
*
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
6
|
+
* modification, are permitted provided that the following conditions are met:
|
7
|
+
*
|
8
|
+
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
+
* list of conditions and the following disclaimer.
|
10
|
+
*
|
11
|
+
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
* this list of conditions and the following disclaimer in the documentation
|
13
|
+
* and/or other materials provided with the distribution.
|
14
|
+
*
|
15
|
+
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
+
* used to endorse or promote products derived from this software without
|
17
|
+
* specific prior written permission.
|
18
|
+
*
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
*/
|
30
|
+
|
31
|
+
#include "odd.h"
|
32
|
+
|
33
|
+
struct _Odd odds[5]; // bump up if new Odd classes are added
|
34
|
+
|
35
|
+
static void
|
36
|
+
set_class(Odd odd, const char *classname) {
|
37
|
+
const char **np;
|
38
|
+
ID *idp;
|
39
|
+
|
40
|
+
odd->classname = classname;
|
41
|
+
odd->clen = strlen(classname);
|
42
|
+
odd->clas = rb_const_get(rb_cObject, rb_intern(classname));
|
43
|
+
odd->create_obj = odd->clas;
|
44
|
+
odd->create_op = rb_intern("new");
|
45
|
+
for (np = odd->attr_names, idp = odd->attrs; 0 != *np; np++, idp++) {
|
46
|
+
*idp = rb_intern(*np);
|
47
|
+
}
|
48
|
+
*idp = 0;
|
49
|
+
}
|
50
|
+
|
51
|
+
void
|
52
|
+
oj_odd_init() {
|
53
|
+
Odd odd;
|
54
|
+
const char **np;
|
55
|
+
|
56
|
+
odd = odds;
|
57
|
+
// Rational
|
58
|
+
np = odd->attr_names;
|
59
|
+
*np++ = "numerator";
|
60
|
+
*np++ = "denominator";
|
61
|
+
*np = 0;
|
62
|
+
set_class(odd, "Rational");
|
63
|
+
odd->create_obj = rb_cObject;
|
64
|
+
odd->create_op = rb_intern("Rational");
|
65
|
+
odd->attr_cnt = 2;
|
66
|
+
// Date
|
67
|
+
odd++;
|
68
|
+
np = odd->attr_names;
|
69
|
+
*np++ = "year";
|
70
|
+
*np++ = "month";
|
71
|
+
*np++ = "day";
|
72
|
+
*np++ = "start";
|
73
|
+
*np++ = 0;
|
74
|
+
set_class(odd, "Date");
|
75
|
+
odd->attr_cnt = 4;
|
76
|
+
// DateTime
|
77
|
+
odd++;
|
78
|
+
np = odd->attr_names;
|
79
|
+
*np++ = "year";
|
80
|
+
*np++ = "month";
|
81
|
+
*np++ = "day";
|
82
|
+
*np++ = "hour";
|
83
|
+
*np++ = "min";
|
84
|
+
*np++ = "sec";
|
85
|
+
*np++ = "offset";
|
86
|
+
*np++ = "start";
|
87
|
+
*np++ = 0;
|
88
|
+
set_class(odd, "DateTime");
|
89
|
+
odd->attr_cnt = 8;
|
90
|
+
// Range
|
91
|
+
odd++;
|
92
|
+
np = odd->attr_names;
|
93
|
+
*np++ = "begin";
|
94
|
+
*np++ = "end";
|
95
|
+
*np++ = "exclude_end?";
|
96
|
+
*np++ = 0;
|
97
|
+
set_class(odd, "Range");
|
98
|
+
odd->attr_cnt = 3;
|
99
|
+
// The end. bump up the size of odds if a new class is added.
|
100
|
+
odd++;
|
101
|
+
odd->clas = Qundef;
|
102
|
+
}
|
103
|
+
|
104
|
+
Odd
|
105
|
+
oj_get_odd(VALUE clas) {
|
106
|
+
Odd odd = odds;
|
107
|
+
|
108
|
+
for (; Qundef != odd->clas; odd++) {
|
109
|
+
if (clas == odd->clas) {
|
110
|
+
return odd;
|
111
|
+
}
|
112
|
+
}
|
113
|
+
return 0;
|
114
|
+
}
|
115
|
+
|
116
|
+
Odd
|
117
|
+
oj_get_oddc(const char *classname, size_t len) {
|
118
|
+
Odd odd = odds;
|
119
|
+
|
120
|
+
for (; Qundef != odd->clas; odd++) {
|
121
|
+
if (len == odd->clen && 0 == strncmp(classname, odd->classname, len)) {
|
122
|
+
return odd;
|
123
|
+
}
|
124
|
+
}
|
125
|
+
return 0;
|
126
|
+
}
|
127
|
+
|
128
|
+
OddArgs
|
129
|
+
oj_odd_alloc_args(Odd odd) {
|
130
|
+
OddArgs oa = ALLOC_N(struct _OddArgs, 1);
|
131
|
+
VALUE *a;
|
132
|
+
int i;
|
133
|
+
|
134
|
+
oa->odd = odd;
|
135
|
+
for (i = odd->attr_cnt, a = oa->args; 0 < i; i--, a++) {
|
136
|
+
*a = Qnil;
|
137
|
+
}
|
138
|
+
return oa;
|
139
|
+
}
|
140
|
+
|
141
|
+
void
|
142
|
+
oj_odd_free(OddArgs args) {
|
143
|
+
xfree(args);
|
144
|
+
}
|
145
|
+
|
146
|
+
int
|
147
|
+
oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
|
148
|
+
const char **np;
|
149
|
+
VALUE *vp;
|
150
|
+
int i;
|
151
|
+
|
152
|
+
for (i = args->odd->attr_cnt, np = args->odd->attr_names, vp = args->args; 0 < i; i--, np++, vp++) {
|
153
|
+
if (0 == strncmp(key, *np, klen) && '\0' == *((*np) + klen)) {
|
154
|
+
*vp = value;
|
155
|
+
return 0;
|
156
|
+
}
|
157
|
+
}
|
158
|
+
return -1;
|
159
|
+
}
|
data/ext/oj/odd.h
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
/* odd.h
|
2
|
+
* Copyright (c) 2011, Peter Ohler
|
3
|
+
* All rights reserved.
|
4
|
+
*
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
6
|
+
* modification, are permitted provided that the following conditions are met:
|
7
|
+
*
|
8
|
+
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
+
* list of conditions and the following disclaimer.
|
10
|
+
*
|
11
|
+
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
* this list of conditions and the following disclaimer in the documentation
|
13
|
+
* and/or other materials provided with the distribution.
|
14
|
+
*
|
15
|
+
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
+
* used to endorse or promote products derived from this software without
|
17
|
+
* specific prior written permission.
|
18
|
+
*
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
*/
|
30
|
+
|
31
|
+
#ifndef __OJ_ODD_H__
|
32
|
+
#define __OJ_ODD_H__
|
33
|
+
|
34
|
+
#include "ruby.h"
|
35
|
+
|
36
|
+
#define MAX_ODD_ARGS 10
|
37
|
+
|
38
|
+
typedef struct _Odd {
|
39
|
+
const char *classname;
|
40
|
+
size_t clen;
|
41
|
+
VALUE clas; // Ruby class
|
42
|
+
VALUE create_obj;
|
43
|
+
ID create_op;
|
44
|
+
int attr_cnt;
|
45
|
+
const char *attr_names[MAX_ODD_ARGS]; // 0 terminated attr IDs
|
46
|
+
ID attrs[MAX_ODD_ARGS]; // 0 terminated attr IDs
|
47
|
+
} *Odd;
|
48
|
+
|
49
|
+
typedef struct _OddArgs {
|
50
|
+
Odd odd;
|
51
|
+
VALUE args[MAX_ODD_ARGS];
|
52
|
+
} *OddArgs;
|
53
|
+
|
54
|
+
extern void oj_odd_init(void);
|
55
|
+
extern Odd oj_get_odd(VALUE clas);
|
56
|
+
extern Odd oj_get_oddc(const char *classname, size_t len);
|
57
|
+
extern OddArgs oj_odd_alloc_args(Odd odd);
|
58
|
+
extern void oj_odd_free(OddArgs args);
|
59
|
+
extern int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value);
|
60
|
+
|
61
|
+
#endif /* __OJ_ODD_H__ */
|
data/ext/oj/oj.c
CHANGED
@@ -37,6 +37,9 @@
|
|
37
37
|
#include <unistd.h>
|
38
38
|
|
39
39
|
#include "oj.h"
|
40
|
+
#include "parse.h"
|
41
|
+
#include "hash.h"
|
42
|
+
#include "odd.h"
|
40
43
|
|
41
44
|
typedef struct _YesNoOpt {
|
42
45
|
VALUE sym;
|
@@ -48,12 +51,14 @@ void Init_oj();
|
|
48
51
|
VALUE Oj = Qnil;
|
49
52
|
|
50
53
|
ID oj_add_value_id;
|
54
|
+
ID oj_array_append_id;
|
51
55
|
ID oj_array_end_id;
|
52
56
|
ID oj_array_start_id;
|
53
57
|
ID oj_as_json_id;
|
54
58
|
ID oj_error_id;
|
55
59
|
ID oj_fileno_id;
|
56
60
|
ID oj_hash_end_id;
|
61
|
+
ID oj_hash_set_id;
|
57
62
|
ID oj_hash_start_id;
|
58
63
|
ID oj_instance_variables_id;
|
59
64
|
ID oj_json_create_id;
|
@@ -91,7 +96,6 @@ static VALUE class_cache_sym;
|
|
91
96
|
static VALUE compat_sym;
|
92
97
|
static VALUE create_id_sym;
|
93
98
|
static VALUE indent_sym;
|
94
|
-
static VALUE max_stack_sym;
|
95
99
|
static VALUE mode_sym;
|
96
100
|
static VALUE null_sym;
|
97
101
|
static VALUE object_sym;
|
@@ -112,9 +116,6 @@ static VALUE symbolize_names_sym;
|
|
112
116
|
|
113
117
|
static VALUE mimic = Qnil;
|
114
118
|
|
115
|
-
Cache oj_class_cache = 0;
|
116
|
-
Cache oj_attr_cache = 0;
|
117
|
-
|
118
119
|
#if HAS_ENCODING_SUPPORT
|
119
120
|
rb_encoding *oj_utf8_encoding = 0;
|
120
121
|
#endif
|
@@ -136,25 +137,12 @@ struct _Options oj_default_options = {
|
|
136
137
|
Yes, // bigdec_as_num
|
137
138
|
No, // bigdec_load
|
138
139
|
json_class, // create_id
|
139
|
-
|
140
|
+
10, // create_id_len
|
140
141
|
9, // sec_prec
|
141
142
|
0, // dump_opts
|
142
143
|
};
|
143
144
|
|
144
145
|
static VALUE define_mimic_json(int argc, VALUE *argv, VALUE self);
|
145
|
-
static struct _Odd odds[5]; // bump up if new Odd classes are added
|
146
|
-
|
147
|
-
Odd
|
148
|
-
oj_get_odd(VALUE clas) {
|
149
|
-
Odd odd = odds;
|
150
|
-
|
151
|
-
for (; Qundef != odd->clas; odd++) {
|
152
|
-
if (clas == odd->clas) {
|
153
|
-
return odd;
|
154
|
-
}
|
155
|
-
}
|
156
|
-
return 0;
|
157
|
-
}
|
158
146
|
|
159
147
|
/* call-seq: default_options() => Hash
|
160
148
|
*
|
@@ -169,7 +157,6 @@ oj_get_odd(VALUE clas) {
|
|
169
157
|
* - bigdecimal_as_decimal: [true|false|nil] dump BigDecimal as a decimal number or as a String
|
170
158
|
* - bigdecimal_load: [true|false|nil] load decimals as BigDecimal instead of as a Float
|
171
159
|
* - create_id: [String|nil] create id for json compatible object encoding, default is 'json_create'
|
172
|
-
* - max_stack: [Fixnum|nil] maximum json size to allocate on the stack, default is 65536
|
173
160
|
* - second_precision: [Fixnum|nil] number of digits after the decimal when dumping the seconds portion of time
|
174
161
|
* @return [Hash] all current option settings.
|
175
162
|
*/
|
@@ -179,7 +166,6 @@ get_def_opts(VALUE self) {
|
|
179
166
|
|
180
167
|
rb_hash_aset(opts, indent_sym, INT2FIX(oj_default_options.indent));
|
181
168
|
rb_hash_aset(opts, sec_prec_sym, INT2FIX(oj_default_options.sec_prec));
|
182
|
-
rb_hash_aset(opts, max_stack_sym, INT2FIX(oj_default_options.max_stack));
|
183
169
|
rb_hash_aset(opts, circular_sym, (Yes == oj_default_options.circular) ? Qtrue : ((No == oj_default_options.circular) ? Qfalse : Qnil));
|
184
170
|
rb_hash_aset(opts, class_cache_sym, (Yes == oj_default_options.class_cache) ? Qtrue : ((No == oj_default_options.class_cache) ? Qfalse : Qnil));
|
185
171
|
rb_hash_aset(opts, auto_define_sym, (Yes == oj_default_options.auto_define) ? Qtrue : ((No == oj_default_options.auto_define) ? Qfalse : Qnil));
|
@@ -230,7 +216,6 @@ get_def_opts(VALUE self) {
|
|
230
216
|
* :xmlschema date-time format taken from XML Schema as a String,
|
231
217
|
* :ruby Time.to_s formatted String
|
232
218
|
* @param [String|nil] :create_id create id for json compatible object encoding
|
233
|
-
* @param [Fixnum|nil] :max_stack maximum size to allocate on the stack for a JSON String
|
234
219
|
* @param [Fixnum|nil] :second_precision number of digits after the decimal when dumping the seconds portion of time
|
235
220
|
* @return [nil]
|
236
221
|
*/
|
@@ -268,17 +253,6 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
268
253
|
}
|
269
254
|
oj_default_options.sec_prec = n;
|
270
255
|
}
|
271
|
-
v = rb_hash_aref(opts, max_stack_sym);
|
272
|
-
if (Qnil != v) {
|
273
|
-
int i;
|
274
|
-
|
275
|
-
Check_Type(v, T_FIXNUM);
|
276
|
-
i = FIX2INT(v);
|
277
|
-
if (0 > i) {
|
278
|
-
i = 0;
|
279
|
-
}
|
280
|
-
oj_default_options.max_stack = (size_t)i;
|
281
|
-
}
|
282
256
|
|
283
257
|
v = rb_hash_lookup(opts, mode_sym);
|
284
258
|
if (Qnil == v) {
|
@@ -314,6 +288,7 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
314
288
|
xfree((char*)oj_default_options.create_id);
|
315
289
|
}
|
316
290
|
oj_default_options.create_id = 0;
|
291
|
+
oj_default_options.create_id_len = 0;
|
317
292
|
}
|
318
293
|
v = rb_hash_lookup(opts, create_id_sym);
|
319
294
|
if (Qnil != v) {
|
@@ -321,6 +296,7 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
321
296
|
|
322
297
|
oj_default_options.create_id = ALLOC_N(char, len);
|
323
298
|
strcpy((char*)oj_default_options.create_id, StringValuePtr(v));
|
299
|
+
oj_default_options.create_id_len = len - 1;
|
324
300
|
}
|
325
301
|
}
|
326
302
|
|
@@ -341,8 +317,8 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
341
317
|
return Qnil;
|
342
318
|
}
|
343
319
|
|
344
|
-
|
345
|
-
|
320
|
+
void
|
321
|
+
oj_parse_options(VALUE ropts, Options copts) {
|
346
322
|
struct _YesNoOpt ynos[] = {
|
347
323
|
{ circular_sym, &copts->circular },
|
348
324
|
{ auto_define_sym, &copts->auto_define },
|
@@ -402,6 +378,28 @@ parse_options(VALUE ropts, Options copts) {
|
|
402
378
|
rb_raise(rb_eArgError, ":time_format must be :unix, :xmlschema, or :ruby.");
|
403
379
|
}
|
404
380
|
}
|
381
|
+
if (Qtrue == rb_funcall(ropts, rb_intern("has_key?"), 1, create_id_sym)) {
|
382
|
+
v = rb_hash_lookup(ropts, create_id_sym);
|
383
|
+
if (Qnil == v) {
|
384
|
+
if (json_class != oj_default_options.create_id) {
|
385
|
+
xfree((char*)oj_default_options.create_id);
|
386
|
+
}
|
387
|
+
copts->create_id = 0;
|
388
|
+
copts->create_id_len = 0;
|
389
|
+
} else if (T_STRING == rb_type(v)) {
|
390
|
+
size_t len = RSTRING_LEN(v);
|
391
|
+
const char *str = StringValuePtr(v);
|
392
|
+
|
393
|
+
if (len != copts->create_id_len ||
|
394
|
+
0 != strcmp(copts->create_id, str)) {
|
395
|
+
copts->create_id = ALLOC_N(char, len + 1);
|
396
|
+
strcpy((char*)copts->create_id, str);
|
397
|
+
copts->create_id_len = len;
|
398
|
+
}
|
399
|
+
} else {
|
400
|
+
rb_raise(rb_eArgError, ":create_id must be string.");
|
401
|
+
}
|
402
|
+
}
|
405
403
|
for (o = ynos; 0 != o->attr; o++) {
|
406
404
|
if (Qnil != (v = rb_hash_lookup(ropts, o->sym))) {
|
407
405
|
if (Qtrue == v) {
|
@@ -416,105 +414,118 @@ parse_options(VALUE ropts, Options copts) {
|
|
416
414
|
}
|
417
415
|
}
|
418
416
|
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
VALUE s;
|
437
|
-
|
438
|
-
if (oj_stringio_class == clas) {
|
439
|
-
s = rb_funcall2(input, oj_string_id, 0, 0);
|
440
|
-
len = RSTRING_LEN(s) + 1;
|
441
|
-
if (copts->max_stack < len) {
|
442
|
-
json = ALLOC_N(char, len);
|
443
|
-
} else {
|
444
|
-
json = ALLOCA_N(char, len);
|
445
|
-
}
|
446
|
-
strcpy(json, StringValuePtr(s));
|
447
|
-
#ifndef JRUBY_RUBY
|
448
|
-
#if !IS_WINDOWS
|
449
|
-
// JRuby gets confused with what is the real fileno.
|
450
|
-
} else if (rb_respond_to(input, oj_fileno_id) && Qnil != (s = rb_funcall(input, oj_fileno_id, 0))) {
|
451
|
-
int fd = FIX2INT(s);
|
452
|
-
ssize_t cnt;
|
453
|
-
|
454
|
-
len = lseek(fd, 0, SEEK_END);
|
455
|
-
lseek(fd, 0, SEEK_SET);
|
456
|
-
if (copts->max_stack < len) {
|
457
|
-
json = ALLOC_N(char, len + 1);
|
458
|
-
} else {
|
459
|
-
json = ALLOCA_N(char, len + 1);
|
460
|
-
}
|
461
|
-
if (0 >= (cnt = read(fd, json, len)) || cnt != (ssize_t)len) {
|
462
|
-
rb_raise(rb_eIOError, "failed to read from IO Object.");
|
463
|
-
}
|
464
|
-
json[len] = '\0';
|
465
|
-
#endif
|
466
|
-
#endif
|
467
|
-
} else if (rb_respond_to(input, oj_read_id)) {
|
468
|
-
s = rb_funcall2(input, oj_read_id, 0, 0);
|
469
|
-
len = RSTRING_LEN(s) + 1;
|
470
|
-
if (copts->max_stack < len) {
|
471
|
-
json = ALLOC_N(char, len);
|
472
|
-
} else {
|
473
|
-
json = ALLOCA_N(char, len);
|
474
|
-
}
|
475
|
-
strcpy(json, StringValuePtr(s));
|
476
|
-
} else {
|
477
|
-
rb_raise(rb_eArgError, "load() expected a String or IO Object.");
|
478
|
-
}
|
479
|
-
}
|
480
|
-
obj = oj_parse(json, copts);
|
481
|
-
if (copts->max_stack < len) {
|
482
|
-
xfree(json);
|
483
|
-
}
|
484
|
-
return obj;
|
485
|
-
}
|
417
|
+
/* Document-method: strict_load
|
418
|
+
* call-seq: strict_load(json, options) => Hash, Array, String, Fixnum, Float, true, false, or nil
|
419
|
+
*
|
420
|
+
* Parses a JSON document String into an Hash, Array, String, Fixnum, Float,
|
421
|
+
* true, false, or nil. It parses using a mode that is strict in that it maps
|
422
|
+
* each primitive JSON type to a similar Ruby type. The :create_id is not
|
423
|
+
* honored in this mode. Note that a Ruby Hash is used to represent the JSON
|
424
|
+
* Object type. These two are not the same since teh JSON Object type can have
|
425
|
+
* repeating entries with the same key and Ruby Hash can not.
|
426
|
+
*
|
427
|
+
* Raises an exception if the JSON is malformed or the classes specified are not
|
428
|
+
* valid. If the input is not a valid JSON document (an empty string is not a
|
429
|
+
* valid JSON document) an exception is raised.
|
430
|
+
*
|
431
|
+
* @param [String|IO] json JSON String or an Object that responds to read()
|
432
|
+
* @param [Hash] options load options (same as default_options)
|
433
|
+
*/
|
486
434
|
|
487
|
-
/*
|
435
|
+
/* Document-method: compat_load
|
436
|
+
* call-seq: compat_load(json, options) => Object, Hash, Array, String, Fixnum, Float, true, false, or nil
|
488
437
|
*
|
489
|
-
* Parses a JSON document String into
|
490
|
-
* true, false, or nil.
|
491
|
-
*
|
492
|
-
*
|
493
|
-
*
|
438
|
+
* Parses a JSON document String into an Object, Hash, Array, String, Fixnum,
|
439
|
+
* Float, true, false, or nil. It parses using a mode that is generally
|
440
|
+
* compatible with other Ruby JSON parsers in that it will create objects based
|
441
|
+
* on the :create_id value. It is not compatible in every way to every other
|
442
|
+
* parser though as each parser has it's own variations.
|
494
443
|
*
|
495
|
-
*
|
444
|
+
* Raises an exception if the JSON is malformed or the classes specified are not
|
445
|
+
* valid. If the input is not a valid JSON document (an empty string is not a
|
446
|
+
* valid JSON document) an exception is raised.
|
447
|
+
*
|
448
|
+
* @param [String|IO] json JSON String or an Object that responds to read()
|
449
|
+
* @param [Hash] options load options (same as default_options)
|
450
|
+
*/
|
451
|
+
|
452
|
+
/* Document-method: object_load
|
453
|
+
* call-seq: object_load(json, options) => Object, Hash, Array, String, Fixnum, Float, true, false, or nil
|
454
|
+
*
|
455
|
+
* Parses a JSON document String into an Object, Hash, Array, String, Fixnum,
|
456
|
+
* Float, true, false, or nil. In the :object mode the JSON should have been
|
457
|
+
* generated by Oj.dump(). The parser will reconstitute the original marshalled
|
458
|
+
* or dumped Object. The :auto_define and :circular options have meaning with
|
459
|
+
* this parsing mode.
|
460
|
+
*
|
461
|
+
* Raises an exception if the JSON is malformed or the classes specified are not
|
462
|
+
* valid. If the input is not a valid JSON document (an empty string is not a
|
463
|
+
* valid JSON document) an exception is raised.
|
464
|
+
*
|
465
|
+
* @param [String|IO] json JSON String or an Object that responds to read()
|
466
|
+
* @param [Hash] options load options (same as default_options)
|
467
|
+
*/
|
468
|
+
|
469
|
+
/* call-seq: load(json, options) => Object, Hash, Array, String, Fixnum, Float, true, false, or nil
|
470
|
+
*
|
471
|
+
* Parses a JSON document String into a Object, Hash, Array, String, Fixnum,
|
472
|
+
* Float, true, false, or nil according to the default mode or the mode
|
473
|
+
* specified. Raises an exception if the JSON is malformed or the classes
|
474
|
+
* specified are not valid. If the string input is not a valid JSON document (an
|
475
|
+
* empty string is not a valid JSON document) an exception is raised.
|
476
|
+
*
|
477
|
+
* @param [String|IO] json JSON String or an Object that responds to read()
|
496
478
|
* @param [Hash] options load options (same as default_options)
|
497
479
|
*/
|
498
480
|
static VALUE
|
499
481
|
load(int argc, VALUE *argv, VALUE self) {
|
500
|
-
|
482
|
+
Mode mode = oj_default_options.mode;
|
501
483
|
|
502
484
|
if (1 > argc) {
|
503
485
|
rb_raise(rb_eArgError, "Wrong number of arguments to load().");
|
504
486
|
}
|
505
487
|
if (2 <= argc) {
|
506
|
-
|
488
|
+
VALUE ropts = argv[1];
|
489
|
+
VALUE v;
|
490
|
+
|
491
|
+
if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
|
492
|
+
if (object_sym == v) {
|
493
|
+
mode = ObjectMode;
|
494
|
+
} else if (strict_sym == v) {
|
495
|
+
mode = StrictMode;
|
496
|
+
} else if (compat_sym == v) {
|
497
|
+
mode = CompatMode;
|
498
|
+
} else if (null_sym == v) {
|
499
|
+
mode = NullMode;
|
500
|
+
} else {
|
501
|
+
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.");
|
502
|
+
}
|
503
|
+
}
|
504
|
+
}
|
505
|
+
switch (mode) {
|
506
|
+
case StrictMode:
|
507
|
+
return oj_strict_parse(argc, argv, self);
|
508
|
+
case NullMode:
|
509
|
+
case CompatMode:
|
510
|
+
return oj_compat_parse(argc, argv, self);
|
511
|
+
case ObjectMode:
|
512
|
+
default:
|
513
|
+
break;
|
507
514
|
}
|
508
|
-
return
|
515
|
+
return oj_object_parse(argc, argv, self);
|
509
516
|
}
|
510
517
|
|
511
518
|
/* Document-method: load_file
|
512
|
-
* call-seq: load_file(path, options) => Hash, Array, String, Fixnum, Float, true, false, or nil
|
519
|
+
* call-seq: load_file(path, options) => Object, Hash, Array, String, Fixnum, Float, true, false, or nil
|
513
520
|
*
|
514
|
-
* Parses a JSON document
|
515
|
-
* true, false, or nil
|
516
|
-
*
|
517
|
-
*
|
521
|
+
* Parses a JSON document String into a Object, Hash, Array, String, Fixnum,
|
522
|
+
* Float, true, false, or nil according to the default mode or the mode
|
523
|
+
* specified. Raises an exception if the JSON is malformed or the classes
|
524
|
+
* specified are not valid. If the string input is not a valid JSON document (an
|
525
|
+
* empty string is not a valid JSON document) an exception is raised.
|
526
|
+
*
|
527
|
+
* If the input file is not a valid JSON document (an empty file is not a valid
|
528
|
+
* JSON document) an exception is raised.
|
518
529
|
*
|
519
530
|
* @param [String] path path to a file containing a JSON document
|
520
531
|
* @param [Hash] options load options (same as default_options)
|
@@ -525,9 +536,7 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
525
536
|
char *json;
|
526
537
|
FILE *f;
|
527
538
|
unsigned long len;
|
528
|
-
|
529
|
-
struct _Options options = oj_default_options;
|
530
|
-
size_t max_stack = oj_default_options.max_stack;
|
539
|
+
Mode mode = oj_default_options.mode;
|
531
540
|
|
532
541
|
Check_Type(*argv, T_STRING);
|
533
542
|
path = StringValuePtr(*argv);
|
@@ -536,45 +545,98 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
536
545
|
}
|
537
546
|
fseek(f, 0, SEEK_END);
|
538
547
|
len = ftell(f);
|
539
|
-
|
540
|
-
json = ALLOC_N(char, len + 1);
|
541
|
-
} else {
|
542
|
-
json = ALLOCA_N(char, len + 1);
|
543
|
-
}
|
548
|
+
json = ALLOC_N(char, len + 1);
|
544
549
|
fseek(f, 0, SEEK_SET);
|
545
550
|
if (len != fread(json, 1, len, f)) {
|
551
|
+
xfree(json);
|
546
552
|
fclose(f);
|
547
553
|
rb_raise(rb_const_get_at(Oj, rb_intern("LoadError")), "Failed to read %ld bytes from %s.", len, path);
|
548
554
|
}
|
549
555
|
fclose(f);
|
550
556
|
json[len] = '\0';
|
557
|
+
|
558
|
+
if (1 > argc) {
|
559
|
+
rb_raise(rb_eArgError, "Wrong number of arguments to load().");
|
560
|
+
}
|
551
561
|
if (2 <= argc) {
|
552
|
-
|
562
|
+
VALUE ropts = argv[1];
|
563
|
+
VALUE v;
|
564
|
+
|
565
|
+
if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
|
566
|
+
if (object_sym == v) {
|
567
|
+
mode = ObjectMode;
|
568
|
+
} else if (strict_sym == v) {
|
569
|
+
mode = StrictMode;
|
570
|
+
} else if (compat_sym == v) {
|
571
|
+
mode = CompatMode;
|
572
|
+
} else if (null_sym == v) {
|
573
|
+
mode = NullMode;
|
574
|
+
} else {
|
575
|
+
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.");
|
576
|
+
}
|
577
|
+
}
|
553
578
|
}
|
554
|
-
|
555
|
-
|
556
|
-
|
579
|
+
// The json string is freed in the parser when it is finished with it.
|
580
|
+
switch (mode) {
|
581
|
+
case StrictMode:
|
582
|
+
return oj_strict_parse_cstr(argc, argv, json);
|
583
|
+
case NullMode:
|
584
|
+
case CompatMode:
|
585
|
+
return oj_compat_parse_cstr(argc, argv, json);
|
586
|
+
case ObjectMode:
|
587
|
+
default:
|
588
|
+
break;
|
557
589
|
}
|
558
|
-
return
|
590
|
+
return oj_object_parse_cstr(argc, argv, json);
|
559
591
|
}
|
560
592
|
|
561
|
-
/* call-seq:
|
593
|
+
/* call-seq: safe_load(doc)
|
594
|
+
*
|
595
|
+
* Loads a JSON document in strict mode with :auto_define and :symbol_keys
|
596
|
+
* turned off. This function should be safe to use with JSON received on an
|
597
|
+
* unprotected public interface.
|
562
598
|
*
|
563
|
-
* Loads a JSON document in strict mode with auto_define and symbol_keys turned off. This function should be safe to use
|
564
|
-
* with JSON received on an unprotected public interface.
|
565
599
|
* @param [String|IO] doc JSON String or IO to load
|
566
600
|
* @return [Hash|Array|String|Fixnum|Bignum|BigDecimal|nil|True|False]
|
567
601
|
*/
|
568
602
|
static VALUE
|
569
|
-
|
570
|
-
struct
|
603
|
+
safe_load(VALUE self, VALUE doc) {
|
604
|
+
struct _ParseInfo pi;
|
605
|
+
VALUE args[1];
|
606
|
+
|
607
|
+
pi.options = oj_default_options;
|
608
|
+
pi.options.auto_define = No;
|
609
|
+
pi.options.sym_key = No;
|
610
|
+
pi.options.mode = StrictMode;
|
611
|
+
oj_set_strict_callbacks(&pi);
|
612
|
+
*args = doc;
|
613
|
+
|
614
|
+
return oj_pi_parse(1, args, &pi, 0);
|
615
|
+
}
|
571
616
|
|
572
|
-
|
573
|
-
|
574
|
-
|
617
|
+
/* call-seq: saj_parse(handler, io)
|
618
|
+
*
|
619
|
+
* Parses an IO stream or file containing a JSON document. Raises an exception
|
620
|
+
* if the JSON is malformed. This is a callback parser that calls the methods in
|
621
|
+
* the handler if they exist. A sample is the Oj::Saj class which can be used as
|
622
|
+
* a base class for the handler.
|
623
|
+
*
|
624
|
+
* @param [Oj::Saj] handler responds to Oj::Saj methods
|
625
|
+
* @param [IO|String] io IO Object to read from
|
626
|
+
*/
|
575
627
|
|
576
|
-
|
577
|
-
|
628
|
+
/* call-seq: sc_parse(handler, io)
|
629
|
+
*
|
630
|
+
* Parses an IO stream or file containing a JSON document. Raises an exception
|
631
|
+
* if the JSON is malformed. This is a callback parser (Simple Callback Parser)
|
632
|
+
* that calls the methods in the handler if they exist. A sample is the
|
633
|
+
* Oj::ScHandler class which can be used as a base class for the handler. This
|
634
|
+
* callback parser is slightly more efficient than the Saj callback parser and
|
635
|
+
* requires less argument checking.
|
636
|
+
*
|
637
|
+
* @param [Oj::ScHandler] handler responds to Oj::ScHandler methods
|
638
|
+
* @param [IO|String] io IO Object to read from
|
639
|
+
*/
|
578
640
|
|
579
641
|
/* call-seq: dump(obj, options) => json-string
|
580
642
|
*
|
@@ -590,7 +652,7 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|
590
652
|
VALUE rstr;
|
591
653
|
|
592
654
|
if (2 == argc) {
|
593
|
-
|
655
|
+
oj_parse_options(argv[1], &copts);
|
594
656
|
}
|
595
657
|
out.buf = buf;
|
596
658
|
out.end = buf + sizeof(buf) - 10;
|
@@ -624,7 +686,7 @@ to_file(int argc, VALUE *argv, VALUE self) {
|
|
624
686
|
struct _Options copts = oj_default_options;
|
625
687
|
|
626
688
|
if (3 == argc) {
|
627
|
-
|
689
|
+
oj_parse_options(argv[2], &copts);
|
628
690
|
}
|
629
691
|
Check_Type(*argv, T_STRING);
|
630
692
|
oj_write_obj_to_file(argv[1], StringValuePtr(*argv), &copts);
|
@@ -632,85 +694,6 @@ to_file(int argc, VALUE *argv, VALUE self) {
|
|
632
694
|
return Qnil;
|
633
695
|
}
|
634
696
|
|
635
|
-
/* call-seq: saj_parse(handler, io)
|
636
|
-
*
|
637
|
-
* Parses an IO stream or file containing an JSON document. Raises an exception
|
638
|
-
* if the JSON is malformed.
|
639
|
-
* @param [Oj::Saj] handler SAJ (responds to Oj::Saj methods) like handler
|
640
|
-
* @param [IO|String] io IO Object to read from
|
641
|
-
*/
|
642
|
-
static VALUE
|
643
|
-
saj_parse(int argc, VALUE *argv, VALUE self) {
|
644
|
-
struct _Options copts = oj_default_options;
|
645
|
-
char *json = 0;
|
646
|
-
size_t len = 0;
|
647
|
-
VALUE input = argv[1];
|
648
|
-
|
649
|
-
if (argc < 2) {
|
650
|
-
rb_raise(rb_eArgError, "Wrong number of arguments to saj_parse.\n");
|
651
|
-
}
|
652
|
-
if (rb_type(input) == T_STRING) {
|
653
|
-
// the json string gets modified so make a copy of it
|
654
|
-
len = RSTRING_LEN(input) + 1;
|
655
|
-
if (copts.max_stack < len) {
|
656
|
-
json = ALLOC_N(char, len);
|
657
|
-
} else {
|
658
|
-
json = ALLOCA_N(char, len);
|
659
|
-
}
|
660
|
-
strcpy(json, StringValuePtr(input));
|
661
|
-
} else {
|
662
|
-
VALUE clas = rb_obj_class(input);
|
663
|
-
VALUE s;
|
664
|
-
|
665
|
-
if (oj_stringio_class == clas) {
|
666
|
-
s = rb_funcall2(input, oj_string_id, 0, 0);
|
667
|
-
len = RSTRING_LEN(s) + 1;
|
668
|
-
if (copts.max_stack < len) {
|
669
|
-
json = ALLOC_N(char, len);
|
670
|
-
} else {
|
671
|
-
json = ALLOCA_N(char, len);
|
672
|
-
}
|
673
|
-
strcpy(json, StringValuePtr(s));
|
674
|
-
#ifndef JRUBY_RUBY
|
675
|
-
#if !IS_WINDOWS
|
676
|
-
// JRuby gets confused with what is the real fileno.
|
677
|
-
} else if (rb_respond_to(input, oj_fileno_id) && Qnil != (s = rb_funcall(input, oj_fileno_id, 0))) {
|
678
|
-
int fd = FIX2INT(s);
|
679
|
-
ssize_t cnt;
|
680
|
-
|
681
|
-
len = lseek(fd, 0, SEEK_END);
|
682
|
-
lseek(fd, 0, SEEK_SET);
|
683
|
-
if (copts.max_stack < len) {
|
684
|
-
json = ALLOC_N(char, len + 1);
|
685
|
-
} else {
|
686
|
-
json = ALLOCA_N(char, len + 1);
|
687
|
-
}
|
688
|
-
if (0 >= (cnt = read(fd, json, len)) || cnt != (ssize_t)len) {
|
689
|
-
rb_raise(rb_eIOError, "failed to read from IO Object.");
|
690
|
-
}
|
691
|
-
json[len] = '\0';
|
692
|
-
#endif
|
693
|
-
#endif
|
694
|
-
} else if (rb_respond_to(input, oj_read_id)) {
|
695
|
-
s = rb_funcall2(input, oj_read_id, 0, 0);
|
696
|
-
len = RSTRING_LEN(s) + 1;
|
697
|
-
if (copts.max_stack < len) {
|
698
|
-
json = ALLOC_N(char, len);
|
699
|
-
} else {
|
700
|
-
json = ALLOCA_N(char, len);
|
701
|
-
}
|
702
|
-
strcpy(json, StringValuePtr(s));
|
703
|
-
} else {
|
704
|
-
rb_raise(rb_eArgError, "saj_parse() expected a String or IO Object.");
|
705
|
-
}
|
706
|
-
}
|
707
|
-
oj_saj_parse(*argv, json);
|
708
|
-
if (copts.max_stack < len) {
|
709
|
-
xfree(json);
|
710
|
-
}
|
711
|
-
return Qnil;
|
712
|
-
}
|
713
|
-
|
714
697
|
// Mimic JSON section
|
715
698
|
|
716
699
|
static VALUE
|
@@ -911,12 +894,16 @@ mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
911
894
|
|
912
895
|
static VALUE
|
913
896
|
mimic_parse(int argc, VALUE *argv, VALUE self) {
|
914
|
-
struct
|
897
|
+
struct _ParseInfo pi;
|
898
|
+
VALUE args[1];
|
915
899
|
|
916
|
-
if (
|
917
|
-
rb_raise(rb_eArgError, "Wrong number of arguments to parse
|
900
|
+
if (argc < 1) {
|
901
|
+
rb_raise(rb_eArgError, "Wrong number of arguments to parse.");
|
918
902
|
}
|
919
|
-
|
903
|
+
oj_set_compat_callbacks(&pi);
|
904
|
+
pi.options = oj_default_options;
|
905
|
+
pi.options.auto_define = No;
|
906
|
+
if (2 <= argc) {
|
920
907
|
VALUE ropts = argv[1];
|
921
908
|
VALUE v;
|
922
909
|
|
@@ -924,17 +911,21 @@ mimic_parse(int argc, VALUE *argv, VALUE self) {
|
|
924
911
|
rb_raise(rb_eArgError, "options must be a hash.");
|
925
912
|
}
|
926
913
|
if (Qnil != (v = rb_hash_lookup(ropts, symbolize_names_sym))) {
|
927
|
-
options.sym_key = (Qtrue == v) ? Yes : No;
|
914
|
+
pi.options.sym_key = (Qtrue == v) ? Yes : No;
|
928
915
|
}
|
929
|
-
if (Qnil != (v = rb_hash_lookup(ropts,
|
930
|
-
|
916
|
+
if (Qnil != (v = rb_hash_lookup(ropts, create_additions_sym))) {
|
917
|
+
if (Qfalse == v) {
|
918
|
+
oj_set_strict_callbacks(&pi);
|
919
|
+
}
|
931
920
|
}
|
932
921
|
// :allow_nan is not supported as Oj always allows nan
|
933
|
-
// :max_nesting is
|
922
|
+
// :max_nesting is ignored as Oj has not nesting limit
|
934
923
|
// :object_class is always Hash
|
935
924
|
// :array_class is always Array
|
936
925
|
}
|
937
|
-
|
926
|
+
*args = *argv;
|
927
|
+
|
928
|
+
return oj_pi_parse(1, args, &pi, 0);
|
938
929
|
}
|
939
930
|
|
940
931
|
static VALUE
|
@@ -959,12 +950,14 @@ mimic_create_id(VALUE self, VALUE id) {
|
|
959
950
|
xfree((char*)oj_default_options.create_id);
|
960
951
|
}
|
961
952
|
oj_default_options.create_id = 0;
|
953
|
+
oj_default_options.create_id_len = 0;
|
962
954
|
}
|
963
955
|
if (Qnil != id) {
|
964
956
|
size_t len = RSTRING_LEN(id) + 1;
|
965
957
|
|
966
958
|
oj_default_options.create_id = ALLOC_N(char, len);
|
967
959
|
strcpy((char*)oj_default_options.create_id, StringValuePtr(id));
|
960
|
+
oj_default_options.create_id_len = len - 1;
|
968
961
|
}
|
969
962
|
return id;
|
970
963
|
}
|
@@ -1045,7 +1038,7 @@ define_mimic_json(int argc, VALUE *argv, VALUE self) {
|
|
1045
1038
|
object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_gc_register_address(&object_nl_sym);
|
1046
1039
|
space_before_sym = ID2SYM(rb_intern("space_before")); rb_gc_register_address(&space_before_sym);
|
1047
1040
|
space_sym = ID2SYM(rb_intern("space")); rb_gc_register_address(&space_sym);
|
1048
|
-
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names"));
|
1041
|
+
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names")); rb_gc_register_address(&symbolize_names_sym);
|
1049
1042
|
|
1050
1043
|
oj_default_options.mode = CompatMode;
|
1051
1044
|
oj_default_options.ascii_only = Yes;
|
@@ -1054,9 +1047,6 @@ define_mimic_json(int argc, VALUE *argv, VALUE self) {
|
|
1054
1047
|
}
|
1055
1048
|
|
1056
1049
|
void Init_oj() {
|
1057
|
-
Odd odd;
|
1058
|
-
ID *idp;
|
1059
|
-
|
1060
1050
|
Oj = rb_define_module("Oj");
|
1061
1051
|
|
1062
1052
|
rb_require("time");
|
@@ -1070,19 +1060,26 @@ void Init_oj() {
|
|
1070
1060
|
rb_define_module_function(Oj, "mimic_JSON", define_mimic_json, -1);
|
1071
1061
|
rb_define_module_function(Oj, "load", load, -1);
|
1072
1062
|
rb_define_module_function(Oj, "load_file", load_file, -1);
|
1073
|
-
rb_define_module_function(Oj, "
|
1063
|
+
rb_define_module_function(Oj, "safe_load", safe_load, 1);
|
1064
|
+
rb_define_module_function(Oj, "strict_load", oj_strict_parse, -1);
|
1065
|
+
rb_define_module_function(Oj, "compat_load", oj_compat_parse, -1);
|
1066
|
+
rb_define_module_function(Oj, "object_load", oj_object_parse, -1);
|
1067
|
+
|
1074
1068
|
rb_define_module_function(Oj, "dump", dump, -1);
|
1075
1069
|
rb_define_module_function(Oj, "to_file", to_file, -1);
|
1076
1070
|
|
1077
|
-
rb_define_module_function(Oj, "saj_parse",
|
1071
|
+
rb_define_module_function(Oj, "saj_parse", oj_saj_parse, -1);
|
1072
|
+
rb_define_module_function(Oj, "sc_parse", oj_sc_parse, -1);
|
1078
1073
|
|
1079
1074
|
oj_add_value_id = rb_intern("add_value");
|
1075
|
+
oj_array_append_id = rb_intern("array_append");
|
1080
1076
|
oj_array_end_id = rb_intern("array_end");
|
1081
1077
|
oj_array_start_id = rb_intern("array_start");
|
1082
1078
|
oj_as_json_id = rb_intern("as_json");
|
1083
1079
|
oj_error_id = rb_intern("error");
|
1084
1080
|
oj_fileno_id = rb_intern("fileno");
|
1085
1081
|
oj_hash_end_id = rb_intern("hash_end");
|
1082
|
+
oj_hash_set_id = rb_intern("hash_set");
|
1086
1083
|
oj_hash_start_id = rb_intern("hash_start");
|
1087
1084
|
oj_instance_variables_id = rb_intern("instance_variables");
|
1088
1085
|
oj_json_create_id = rb_intern("json_create");
|
@@ -1118,7 +1115,6 @@ void Init_oj() {
|
|
1118
1115
|
compat_sym = ID2SYM(rb_intern("compat")); rb_gc_register_address(&compat_sym);
|
1119
1116
|
create_id_sym = ID2SYM(rb_intern("create_id")); rb_gc_register_address(&create_id_sym);
|
1120
1117
|
indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&indent_sym);
|
1121
|
-
max_stack_sym = ID2SYM(rb_intern("max_stack")); rb_gc_register_address(&max_stack_sym);
|
1122
1118
|
mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
|
1123
1119
|
null_sym = ID2SYM(rb_intern("null")); rb_gc_register_address(&null_sym);
|
1124
1120
|
object_sym = ID2SYM(rb_intern("object")); rb_gc_register_address(&object_sym);
|
@@ -1137,82 +1133,16 @@ void Init_oj() {
|
|
1137
1133
|
oj_utf8_encoding = rb_enc_find("UTF-8");
|
1138
1134
|
#endif
|
1139
1135
|
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
odd = odds;
|
1144
|
-
// Rational
|
1145
|
-
idp = odd->attrs;
|
1146
|
-
odd->clas = rb_const_get(rb_cObject, rb_intern("Rational"));
|
1147
|
-
odd->create_obj = rb_cObject;
|
1148
|
-
odd->create_op = rb_intern("Rational");
|
1149
|
-
odd->attr_cnt = 2;
|
1150
|
-
*idp++ = rb_intern("numerator");
|
1151
|
-
*idp++ = rb_intern("denominator");
|
1152
|
-
*idp++ = 0;
|
1153
|
-
// Date
|
1154
|
-
odd++;
|
1155
|
-
idp = odd->attrs;
|
1156
|
-
odd->clas = oj_date_class;
|
1157
|
-
odd->create_obj = odd->clas;
|
1158
|
-
odd->create_op = oj_new_id;
|
1159
|
-
odd->attr_cnt = 4;
|
1160
|
-
*idp++ = rb_intern("year");
|
1161
|
-
*idp++ = rb_intern("month");
|
1162
|
-
*idp++ = rb_intern("day");
|
1163
|
-
*idp++ = rb_intern("start");
|
1164
|
-
*idp++ = 0;
|
1165
|
-
// DateTime
|
1166
|
-
odd++;
|
1167
|
-
idp = odd->attrs;
|
1168
|
-
odd->clas = oj_datetime_class;
|
1169
|
-
odd->create_obj = odd->clas;
|
1170
|
-
odd->create_op = oj_new_id;
|
1171
|
-
odd->attr_cnt = 8;
|
1172
|
-
*idp++ = rb_intern("year");
|
1173
|
-
*idp++ = rb_intern("month");
|
1174
|
-
*idp++ = rb_intern("day");
|
1175
|
-
*idp++ = rb_intern("hour");
|
1176
|
-
*idp++ = rb_intern("min");
|
1177
|
-
*idp++ = rb_intern("sec");
|
1178
|
-
*idp++ = rb_intern("offset");
|
1179
|
-
*idp++ = rb_intern("start");
|
1180
|
-
*idp++ = 0;
|
1181
|
-
// Range
|
1182
|
-
odd++;
|
1183
|
-
idp = odd->attrs;
|
1184
|
-
odd->clas = rb_const_get(rb_cObject, rb_intern("Range"));
|
1185
|
-
odd->create_obj = odd->clas;
|
1186
|
-
odd->create_op = oj_new_id;
|
1187
|
-
odd->attr_cnt = 3;
|
1188
|
-
*idp++ = rb_intern("begin");
|
1189
|
-
*idp++ = rb_intern("end");
|
1190
|
-
*idp++ = rb_intern("exclude_end?");
|
1191
|
-
*idp++ = 0;
|
1192
|
-
// The end. bump up the size of odds if a new class is added.
|
1193
|
-
odd++;
|
1194
|
-
odd->clas = Qundef;
|
1136
|
+
oj_hash_init();
|
1137
|
+
oj_odd_init();
|
1195
1138
|
|
1196
1139
|
#if SAFE_CACHE
|
1197
1140
|
pthread_mutex_init(&oj_cache_mutex, 0);
|
1198
1141
|
#endif
|
1199
1142
|
oj_init_doc();
|
1200
|
-
}
|
1201
1143
|
|
1202
|
-
|
1203
|
-
_oj_raise_error(const char *msg, const char *json, const char *current, const char* file, int line) {
|
1204
|
-
int jline = 1;
|
1205
|
-
int col = 1;
|
1144
|
+
//rb_define_module_function(Oj, "hash_test", hash_test, 0);
|
1206
1145
|
|
1207
|
-
for (; json < current && '\n' != *current; current--) {
|
1208
|
-
col++;
|
1209
|
-
}
|
1210
|
-
for (; json < current; current--) {
|
1211
|
-
if ('\n' == *current) {
|
1212
|
-
jline++;
|
1213
|
-
}
|
1214
|
-
}
|
1215
|
-
rb_raise(oj_parse_error_class, "%s at line %d, column %d [%s:%d]", msg, jline, col, file, line);
|
1216
1146
|
}
|
1217
1147
|
|
1218
1148
|
// mimic JSON documentation
|