oj 2.1.7 → 2.2.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 +6 -4
- data/ext/oj/dump.c +97 -70
- data/ext/oj/extconf.rb +1 -2
- data/ext/oj/object.c +11 -11
- data/ext/oj/oj.c +64 -7
- data/ext/oj/oj.h +8 -1
- data/ext/oj/parse.c +11 -18
- data/ext/oj/saj.c +7 -13
- data/ext/oj/scp.c +4 -4
- data/ext/oj/strict.c +4 -4
- data/ext/oj/val_stack.c +30 -0
- data/ext/oj/val_stack.h +23 -28
- data/lib/oj/version.rb +1 -1
- data/test/test_gc.rb +51 -0
- data/test/test_saj.rb +1 -1
- data/test/tests.rb +49 -19
- metadata +3 -2
data/ext/oj/object.c
CHANGED
@@ -72,7 +72,7 @@ hash_key(ParseInfo pi, const char *key, size_t klen, char k1) {
|
|
72
72
|
|
73
73
|
static VALUE
|
74
74
|
str_to_value(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
75
|
-
VALUE rstr = Qnil;
|
75
|
+
volatile VALUE rstr = Qnil;
|
76
76
|
|
77
77
|
if (':' == *orig && 0 < len) {
|
78
78
|
rstr = rb_str_new(str + 1, len - 1);
|
@@ -183,11 +183,11 @@ static int
|
|
183
183
|
hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, VALUE value) {
|
184
184
|
if (2 == klen && 'u' == key[1] && T_ARRAY == rb_type(value)) {
|
185
185
|
#if HAS_RSTRUCT
|
186
|
-
long
|
187
|
-
VALUE
|
188
|
-
VALUE
|
189
|
-
VALUE s;
|
190
|
-
VALUE
|
186
|
+
long len = RARRAY_LEN(value);
|
187
|
+
VALUE *a = RARRAY_PTR(value);
|
188
|
+
VALUE sc;
|
189
|
+
volatile VALUE s;
|
190
|
+
VALUE *sv;
|
191
191
|
|
192
192
|
if (0 == len) {
|
193
193
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
|
@@ -231,11 +231,11 @@ hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, VALUE value) {
|
|
231
231
|
|
232
232
|
static void
|
233
233
|
copy_ivars(VALUE target, VALUE src) {
|
234
|
-
VALUE vars = rb_funcall(src, oj_instance_variables_id, 0);
|
235
|
-
VALUE
|
236
|
-
ID
|
237
|
-
int
|
238
|
-
const char
|
234
|
+
volatile VALUE vars = rb_funcall(src, oj_instance_variables_id, 0);
|
235
|
+
VALUE *np = RARRAY_PTR(vars);
|
236
|
+
ID vid;
|
237
|
+
int i, cnt = (int)RARRAY_LEN(vars);
|
238
|
+
const char *attr;
|
239
239
|
|
240
240
|
for (i = cnt; 0 < i; i--, np++) {
|
241
241
|
vid = rb_to_id(*np);
|
data/ext/oj/oj.c
CHANGED
@@ -80,6 +80,7 @@ ID oj_write_id;
|
|
80
80
|
|
81
81
|
VALUE oj_bag_class;
|
82
82
|
VALUE oj_bigdecimal_class;
|
83
|
+
VALUE oj_cstack_class;
|
83
84
|
VALUE oj_date_class;
|
84
85
|
VALUE oj_datetime_class;
|
85
86
|
VALUE oj_parse_error_class;
|
@@ -89,6 +90,7 @@ VALUE oj_time_class;
|
|
89
90
|
|
90
91
|
VALUE oj_slash_string;
|
91
92
|
|
93
|
+
static VALUE ascii_sym;
|
92
94
|
static VALUE ascii_only_sym;
|
93
95
|
static VALUE auto_define_sym;
|
94
96
|
static VALUE bigdecimal_as_decimal_sym;
|
@@ -97,10 +99,13 @@ static VALUE circular_sym;
|
|
97
99
|
static VALUE class_cache_sym;
|
98
100
|
static VALUE compat_sym;
|
99
101
|
static VALUE create_id_sym;
|
102
|
+
static VALUE escape_mode_sym;
|
100
103
|
static VALUE indent_sym;
|
104
|
+
static VALUE json_sym;
|
101
105
|
static VALUE mode_sym;
|
102
106
|
static VALUE null_sym;
|
103
107
|
static VALUE object_sym;
|
108
|
+
static VALUE xss_safe_sym;
|
104
109
|
static VALUE ruby_sym;
|
105
110
|
static VALUE sec_prec_sym;
|
106
111
|
static VALUE strict_sym;
|
@@ -134,7 +139,7 @@ struct _Options oj_default_options = {
|
|
134
139
|
No, // circular
|
135
140
|
No, // auto_define
|
136
141
|
No, // sym_key
|
137
|
-
|
142
|
+
JSONEsc, // escape_mode
|
138
143
|
ObjectMode, // mode
|
139
144
|
Yes, // class_cache
|
140
145
|
UnixTime, // time_format
|
@@ -155,6 +160,7 @@ static VALUE define_mimic_json(int argc, VALUE *argv, VALUE self);
|
|
155
160
|
* - circular: [true|false|nil] support circular references while dumping
|
156
161
|
* - auto_define: [true|false|nil] automatically define classes if they do not exist
|
157
162
|
* - symbol_keys: [true|false|nil] use symbols instead of strings for hash keys
|
163
|
+
* - escape_mode: [:json|:xss_safe|:ascii|nil] use symbols instead of strings for hash keys
|
158
164
|
* - class_cache: [true|false|nil] cache classes for faster parsing (if dynamically modifying classes or reloading classes then don't use this)
|
159
165
|
* - mode: [:object|:strict|:compat|:null] load and dump modes to use for JSON
|
160
166
|
* - time_format: [:unix|:xmlschema|:ruby] time format when dumping in :compat mode
|
@@ -173,7 +179,6 @@ get_def_opts(VALUE self) {
|
|
173
179
|
rb_hash_aset(opts, circular_sym, (Yes == oj_default_options.circular) ? Qtrue : ((No == oj_default_options.circular) ? Qfalse : Qnil));
|
174
180
|
rb_hash_aset(opts, class_cache_sym, (Yes == oj_default_options.class_cache) ? Qtrue : ((No == oj_default_options.class_cache) ? Qfalse : Qnil));
|
175
181
|
rb_hash_aset(opts, auto_define_sym, (Yes == oj_default_options.auto_define) ? Qtrue : ((No == oj_default_options.auto_define) ? Qfalse : Qnil));
|
176
|
-
rb_hash_aset(opts, ascii_only_sym, (Yes == oj_default_options.ascii_only) ? Qtrue : ((No == oj_default_options.ascii_only) ? Qfalse : Qnil));
|
177
182
|
rb_hash_aset(opts, symbol_keys_sym, (Yes == oj_default_options.sym_key) ? Qtrue : ((No == oj_default_options.sym_key) ? Qfalse : Qnil));
|
178
183
|
rb_hash_aset(opts, bigdecimal_as_decimal_sym, (Yes == oj_default_options.bigdec_as_num) ? Qtrue : ((No == oj_default_options.bigdec_as_num) ? Qfalse : Qnil));
|
179
184
|
rb_hash_aset(opts, bigdecimal_load_sym, (Yes == oj_default_options.bigdec_load) ? Qtrue : ((No == oj_default_options.bigdec_load) ? Qfalse : Qnil));
|
@@ -184,6 +189,12 @@ get_def_opts(VALUE self) {
|
|
184
189
|
case ObjectMode:
|
185
190
|
default: rb_hash_aset(opts, mode_sym, object_sym); break;
|
186
191
|
}
|
192
|
+
switch (oj_default_options.escape_mode) {
|
193
|
+
case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
|
194
|
+
case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
|
195
|
+
case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
|
196
|
+
default: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
|
197
|
+
}
|
187
198
|
switch (oj_default_options.time_format) {
|
188
199
|
case XmlTime: rb_hash_aset(opts, time_format_sym, xmlschema_sym); break;
|
189
200
|
case RubyTime: rb_hash_aset(opts, time_format_sym, ruby_sym); break;
|
@@ -204,7 +215,9 @@ get_def_opts(VALUE self) {
|
|
204
215
|
* @param [true|false|nil] :auto_define automatically define classes if they do not exist
|
205
216
|
* @param [true|false|nil] :symbol_keys convert hash keys to symbols
|
206
217
|
* @param [true|false|nil] :class_cache cache classes for faster parsing
|
207
|
-
* @param [
|
218
|
+
* @param [:json|:xss_safe|:ascii|nil] :escape mode encodes all high-bit characters as
|
219
|
+
* escaped sequences if :ascii, :json is standand UTF-8 JSON encoding,
|
220
|
+
* and :xss_safe escapes &, <, and >, and some others.
|
208
221
|
* @param [true|false|nil] :bigdecimal_as_decimal dump BigDecimal as a decimal number or as a String
|
209
222
|
* @param [true|false|nil] :bigdecimal_load load decimals as a BigDecimal instead of as a Float
|
210
223
|
* @param [:object|:strict|:compat|:null] load and dump mode to use for JSON
|
@@ -230,7 +243,6 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
230
243
|
{ auto_define_sym, &oj_default_options.auto_define },
|
231
244
|
{ symbol_keys_sym, &oj_default_options.sym_key },
|
232
245
|
{ class_cache_sym, &oj_default_options.class_cache },
|
233
|
-
{ ascii_only_sym, &oj_default_options.ascii_only },
|
234
246
|
{ bigdecimal_as_decimal_sym, &oj_default_options.bigdec_as_num },
|
235
247
|
{ bigdecimal_load_sym, &oj_default_options.bigdec_load },
|
236
248
|
{ Qnil, 0 }
|
@@ -286,6 +298,19 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
286
298
|
rb_raise(rb_eArgError, ":time_format must be :unix, :xmlschema, or :ruby.");
|
287
299
|
}
|
288
300
|
|
301
|
+
v = rb_hash_lookup(opts, escape_mode_sym);
|
302
|
+
if (Qnil == v) {
|
303
|
+
// ignore
|
304
|
+
} else if (json_sym == v) {
|
305
|
+
oj_default_options.escape_mode = JSONEsc;
|
306
|
+
} else if (xss_safe_sym == v) {
|
307
|
+
oj_default_options.escape_mode = XSSEsc;
|
308
|
+
} else if (ascii_sym == v) {
|
309
|
+
oj_default_options.escape_mode = ASCIIEsc;
|
310
|
+
} else {
|
311
|
+
rb_raise(rb_eArgError, ":encoding must be :json, :rails, or :ascii.");
|
312
|
+
}
|
313
|
+
|
289
314
|
if (Qtrue == rb_funcall(opts, rb_intern("has_key?"), 1, create_id_sym)) {
|
290
315
|
if (0 != oj_default_options.create_id) {
|
291
316
|
if (json_class != oj_default_options.create_id) {
|
@@ -318,6 +343,13 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
318
343
|
}
|
319
344
|
}
|
320
345
|
}
|
346
|
+
// This is here only for backwards compatibility with the original Oj.
|
347
|
+
v = rb_hash_lookup(opts, ascii_only_sym);
|
348
|
+
if (Qtrue == v) {
|
349
|
+
oj_default_options.escape_mode = ASCIIEsc;
|
350
|
+
} else if (Qfalse == v) {
|
351
|
+
oj_default_options.escape_mode = JSONEsc;
|
352
|
+
}
|
321
353
|
return Qnil;
|
322
354
|
}
|
323
355
|
|
@@ -328,7 +360,6 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
328
360
|
{ auto_define_sym, &copts->auto_define },
|
329
361
|
{ symbol_keys_sym, &copts->sym_key },
|
330
362
|
{ class_cache_sym, &copts->class_cache },
|
331
|
-
{ ascii_only_sym, &copts->ascii_only },
|
332
363
|
{ bigdecimal_as_decimal_sym, &copts->bigdec_as_num },
|
333
364
|
{ bigdecimal_load_sym, &copts->bigdec_load },
|
334
365
|
{ Qnil, 0 }
|
@@ -382,6 +413,19 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
382
413
|
rb_raise(rb_eArgError, ":time_format must be :unix, :xmlschema, or :ruby.");
|
383
414
|
}
|
384
415
|
}
|
416
|
+
|
417
|
+
if (Qnil != (v = rb_hash_lookup(ropts, escape_mode_sym))) {
|
418
|
+
if (json_sym == v) {
|
419
|
+
copts->escape_mode = JSONEsc;
|
420
|
+
} else if (xss_safe_sym == v) {
|
421
|
+
copts->escape_mode = XSSEsc;
|
422
|
+
} else if (ascii_sym == v) {
|
423
|
+
copts->escape_mode = ASCIIEsc;
|
424
|
+
} else {
|
425
|
+
rb_raise(rb_eArgError, ":encoding must be :json, :rails, or :ascii.");
|
426
|
+
}
|
427
|
+
}
|
428
|
+
|
385
429
|
if (Qtrue == rb_funcall(ropts, rb_intern("has_key?"), 1, create_id_sym)) {
|
386
430
|
v = rb_hash_lookup(ropts, create_id_sym);
|
387
431
|
if (Qnil == v) {
|
@@ -415,6 +459,13 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
415
459
|
}
|
416
460
|
}
|
417
461
|
}
|
462
|
+
// This is here only for backwards compatibility with the original Oj.
|
463
|
+
v = rb_hash_lookup(ropts, ascii_only_sym);
|
464
|
+
if (Qtrue == v) {
|
465
|
+
copts->escape_mode = ASCIIEsc;
|
466
|
+
} else if (Qfalse == v) {
|
467
|
+
copts->escape_mode = JSONEsc;
|
468
|
+
}
|
418
469
|
}
|
419
470
|
}
|
420
471
|
|
@@ -1009,7 +1060,7 @@ mimic_create_id(VALUE self, VALUE id) {
|
|
1009
1060
|
* will be replaced with Oj methods.
|
1010
1061
|
*
|
1011
1062
|
* Note that this also sets the default options of :mode to :compat and
|
1012
|
-
* :
|
1063
|
+
* :encoding to :ascii.
|
1013
1064
|
*/
|
1014
1065
|
static VALUE
|
1015
1066
|
define_mimic_json(int argc, VALUE *argv, VALUE self) {
|
@@ -1079,7 +1130,7 @@ define_mimic_json(int argc, VALUE *argv, VALUE self) {
|
|
1079
1130
|
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names")); rb_gc_register_address(&symbolize_names_sym);
|
1080
1131
|
|
1081
1132
|
oj_default_options.mode = CompatMode;
|
1082
|
-
oj_default_options.
|
1133
|
+
oj_default_options.escape_mode = ASCIIEsc;
|
1083
1134
|
|
1084
1135
|
return mimic;
|
1085
1136
|
}
|
@@ -1114,6 +1165,8 @@ iconv_rescue(VALUE x) {
|
|
1114
1165
|
void Init_oj() {
|
1115
1166
|
Oj = rb_define_module("Oj");
|
1116
1167
|
|
1168
|
+
oj_cstack_class = rb_define_class_under(Oj, "CStack", rb_cObject);
|
1169
|
+
|
1117
1170
|
rb_require("time");
|
1118
1171
|
rb_require("date");
|
1119
1172
|
rb_require("bigdecimal");
|
@@ -1185,6 +1238,7 @@ void Init_oj() {
|
|
1185
1238
|
oj_struct_class = rb_const_get(rb_cObject, rb_intern("Struct"));
|
1186
1239
|
oj_time_class = rb_const_get(rb_cObject, rb_intern("Time"));
|
1187
1240
|
|
1241
|
+
ascii_sym = ID2SYM(rb_intern("ascii")); rb_gc_register_address(&ascii_sym);
|
1188
1242
|
ascii_only_sym = ID2SYM(rb_intern("ascii_only")); rb_gc_register_address(&ascii_only_sym);
|
1189
1243
|
auto_define_sym = ID2SYM(rb_intern("auto_define")); rb_gc_register_address(&auto_define_sym);
|
1190
1244
|
bigdecimal_as_decimal_sym = ID2SYM(rb_intern("bigdecimal_as_decimal"));rb_gc_register_address(&bigdecimal_as_decimal_sym);
|
@@ -1193,10 +1247,13 @@ void Init_oj() {
|
|
1193
1247
|
class_cache_sym = ID2SYM(rb_intern("class_cache")); rb_gc_register_address(&class_cache_sym);
|
1194
1248
|
compat_sym = ID2SYM(rb_intern("compat")); rb_gc_register_address(&compat_sym);
|
1195
1249
|
create_id_sym = ID2SYM(rb_intern("create_id")); rb_gc_register_address(&create_id_sym);
|
1250
|
+
escape_mode_sym = ID2SYM(rb_intern("escape_mode")); rb_gc_register_address(&escape_mode_sym);
|
1196
1251
|
indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&indent_sym);
|
1252
|
+
json_sym = ID2SYM(rb_intern("json")); rb_gc_register_address(&json_sym);
|
1197
1253
|
mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
|
1198
1254
|
null_sym = ID2SYM(rb_intern("null")); rb_gc_register_address(&null_sym);
|
1199
1255
|
object_sym = ID2SYM(rb_intern("object")); rb_gc_register_address(&object_sym);
|
1256
|
+
xss_safe_sym = ID2SYM(rb_intern("xss_safe")); rb_gc_register_address(&xss_safe_sym);
|
1200
1257
|
ruby_sym = ID2SYM(rb_intern("ruby")); rb_gc_register_address(&ruby_sym);
|
1201
1258
|
sec_prec_sym = ID2SYM(rb_intern("second_precision"));rb_gc_register_address(&sec_prec_sym);
|
1202
1259
|
strict_sym = ID2SYM(rb_intern("strict")); rb_gc_register_address(&strict_sym);
|
data/ext/oj/oj.h
CHANGED
@@ -85,6 +85,12 @@ typedef enum {
|
|
85
85
|
RubyTime = 'r'
|
86
86
|
} TimeFormat;
|
87
87
|
|
88
|
+
typedef enum {
|
89
|
+
JSONEsc = 'j',
|
90
|
+
XSSEsc = 'x',
|
91
|
+
ASCIIEsc = 'a'
|
92
|
+
} Encoding;
|
93
|
+
|
88
94
|
typedef struct _DumpOpts {
|
89
95
|
const char *indent;
|
90
96
|
const char *before_sep;
|
@@ -103,7 +109,7 @@ typedef struct _Options {
|
|
103
109
|
char circular; // YesNo
|
104
110
|
char auto_define; // YesNo
|
105
111
|
char sym_key; // YesNo
|
106
|
-
char
|
112
|
+
char escape_mode; // Escape_Mode
|
107
113
|
char mode; // Mode
|
108
114
|
char class_cache; // YesNo
|
109
115
|
char time_format; // TimeFormat
|
@@ -181,6 +187,7 @@ extern VALUE oj_utf8_encoding;
|
|
181
187
|
|
182
188
|
extern VALUE oj_bag_class;
|
183
189
|
extern VALUE oj_bigdecimal_class;
|
190
|
+
extern VALUE oj_cstack_class;
|
184
191
|
extern VALUE oj_date_class;
|
185
192
|
extern VALUE oj_datetime_class;
|
186
193
|
extern VALUE oj_doc_class;
|
data/ext/oj/parse.c
CHANGED
@@ -499,9 +499,8 @@ read_num(ParseInfo pi) {
|
|
499
499
|
|
500
500
|
static void
|
501
501
|
array_start(ParseInfo pi) {
|
502
|
-
VALUE v =
|
502
|
+
VALUE v = pi->start_array(pi);
|
503
503
|
|
504
|
-
v = pi->start_array(pi);
|
505
504
|
stack_push(&pi->stack, v, NEXT_ARRAY_NEW);
|
506
505
|
}
|
507
506
|
|
@@ -521,9 +520,8 @@ array_end(ParseInfo pi) {
|
|
521
520
|
|
522
521
|
static void
|
523
522
|
hash_start(ParseInfo pi) {
|
524
|
-
VALUE v =
|
523
|
+
VALUE v = pi->start_hash(pi);
|
525
524
|
|
526
|
-
v = pi->start_hash(pi);
|
527
525
|
stack_push(&pi->stack, v, NEXT_HASH_NEW);
|
528
526
|
}
|
529
527
|
|
@@ -571,9 +569,11 @@ colon(ParseInfo pi) {
|
|
571
569
|
|
572
570
|
void
|
573
571
|
oj_parse2(ParseInfo pi) {
|
572
|
+
volatile VALUE rstack = Qnil;
|
573
|
+
|
574
574
|
pi->cur = pi->json;
|
575
575
|
err_init(&pi->err);
|
576
|
-
|
576
|
+
rstack = oj_stack_init(&pi->stack);
|
577
577
|
while (1) {
|
578
578
|
next_non_white(pi);
|
579
579
|
switch (*pi->cur++) {
|
@@ -656,7 +656,7 @@ oj_num_as_value(NumInfo ni) {
|
|
656
656
|
rnum = rb_float_new(OJ_INFINITY);
|
657
657
|
}
|
658
658
|
} else if (ni->nan) {
|
659
|
-
rnum = rb_float_new(
|
659
|
+
rnum = rb_float_new(0.0/0.0);
|
660
660
|
} else if (1 == ni->div && 0 == ni->exp) { // fixnum
|
661
661
|
if (ni->big) {
|
662
662
|
if (256 > ni->len) {
|
@@ -719,11 +719,11 @@ protect_parse(VALUE pip) {
|
|
719
719
|
|
720
720
|
VALUE
|
721
721
|
oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json) {
|
722
|
-
char
|
723
|
-
VALUE
|
724
|
-
VALUE result = Qnil;
|
725
|
-
int
|
726
|
-
int
|
722
|
+
char *buf = 0;
|
723
|
+
VALUE input;
|
724
|
+
volatile VALUE result = Qnil;
|
725
|
+
int line = 0;
|
726
|
+
int free_json = 0;
|
727
727
|
|
728
728
|
if (argc < 1) {
|
729
729
|
rb_raise(rb_eArgError, "Wrong number of arguments to parse.");
|
@@ -784,15 +784,8 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json) {
|
|
784
784
|
// GC can run at any time. When it runs any Object created by C will be
|
785
785
|
// freed. This usually only happens with large files but it does happen and
|
786
786
|
// it happens more frequently on Ruby 1.8.7.
|
787
|
-
#if HAS_GC_GUARD
|
788
|
-
rb_gc_disable();
|
789
|
-
#endif
|
790
787
|
rb_protect(protect_parse, (VALUE)pi, &line);
|
791
788
|
result = stack_head_val(&pi->stack);
|
792
|
-
#if HAS_GC_GUARD
|
793
|
-
RB_GC_GUARD(result);
|
794
|
-
rb_gc_enable();
|
795
|
-
#endif
|
796
789
|
// proceed with cleanup
|
797
790
|
if (0 != pi->circ_array) {
|
798
791
|
oj_circ_array_free(pi->circ_array);
|
data/ext/oj/saj.c
CHANGED
@@ -44,12 +44,6 @@
|
|
44
44
|
#include "oj.h"
|
45
45
|
#include "encode.h"
|
46
46
|
|
47
|
-
typedef struct _CX {
|
48
|
-
VALUE *cur;
|
49
|
-
VALUE *end;
|
50
|
-
VALUE stack[1024];
|
51
|
-
} *CX;
|
52
|
-
|
53
47
|
typedef struct _ParseInfo {
|
54
48
|
char *str; /* buffer being read from */
|
55
49
|
char *s; /* current position in buffer */
|
@@ -145,7 +139,7 @@ next_white(ParseInfo pi) {
|
|
145
139
|
|
146
140
|
inline static void
|
147
141
|
call_add_value(VALUE handler, VALUE value, const char *key) {
|
148
|
-
VALUE k;
|
142
|
+
volatile VALUE k;
|
149
143
|
|
150
144
|
if (0 == key) {
|
151
145
|
k = Qnil;
|
@@ -158,7 +152,7 @@ call_add_value(VALUE handler, VALUE value, const char *key) {
|
|
158
152
|
|
159
153
|
inline static void
|
160
154
|
call_no_value(VALUE handler, ID method, const char *key) {
|
161
|
-
VALUE k;
|
155
|
+
volatile VALUE k;
|
162
156
|
|
163
157
|
if (0 == key) {
|
164
158
|
k = Qnil;
|
@@ -668,7 +662,7 @@ respond_to(VALUE obj, ID method) {
|
|
668
662
|
|
669
663
|
static void
|
670
664
|
sajkey_parse(VALUE handler, char *json) {
|
671
|
-
VALUE
|
665
|
+
volatile VALUE obj = Qnil;
|
672
666
|
struct _ParseInfo pi;
|
673
667
|
|
674
668
|
if (0 == json) {
|
@@ -737,14 +731,14 @@ oj_saj_parse(int argc, VALUE *argv, VALUE self) {
|
|
737
731
|
json = ALLOC_N(char, len);
|
738
732
|
strcpy(json, StringValuePtr(input));
|
739
733
|
} else {
|
740
|
-
VALUE
|
741
|
-
VALUE s;
|
734
|
+
VALUE clas = rb_obj_class(input);
|
735
|
+
volatile VALUE s;
|
742
736
|
|
743
737
|
if (oj_stringio_class == clas) {
|
744
738
|
s = rb_funcall2(input, oj_string_id, 0, 0);
|
745
739
|
len = RSTRING_LEN(s) + 1;
|
746
740
|
json = ALLOC_N(char, len);
|
747
|
-
strcpy(json,
|
741
|
+
strcpy(json, rb_string_value_cstr((VALUE*)&s));
|
748
742
|
#ifndef JRUBY_RUBY
|
749
743
|
#if !IS_WINDOWS
|
750
744
|
// JRuby gets confused with what is the real fileno.
|
@@ -765,7 +759,7 @@ oj_saj_parse(int argc, VALUE *argv, VALUE self) {
|
|
765
759
|
s = rb_funcall2(input, oj_read_id, 0, 0);
|
766
760
|
len = RSTRING_LEN(s) + 1;
|
767
761
|
json = ALLOC_N(char, len);
|
768
|
-
strcpy(json,
|
762
|
+
strcpy(json, rb_string_value_cstr((VALUE*)&s));
|
769
763
|
} else {
|
770
764
|
rb_raise(rb_eArgError, "saj_parse() expected a String or IO Object.");
|
771
765
|
}
|
data/ext/oj/scp.c
CHANGED
@@ -107,7 +107,7 @@ add_value(ParseInfo pi, VALUE val) {
|
|
107
107
|
|
108
108
|
static void
|
109
109
|
add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
110
|
-
VALUE rstr = rb_str_new(str, len);
|
110
|
+
volatile VALUE rstr = rb_str_new(str, len);
|
111
111
|
|
112
112
|
rstr = oj_encode(rstr);
|
113
113
|
rb_funcall((VALUE)pi->cbc, oj_add_value_id, 1, rstr);
|
@@ -140,7 +140,7 @@ end_array(ParseInfo pi) {
|
|
140
140
|
|
141
141
|
static VALUE
|
142
142
|
hash_key(ParseInfo pi, const char *key, size_t klen) {
|
143
|
-
VALUE rkey = rb_str_new(key, klen);
|
143
|
+
volatile VALUE rkey = rb_str_new(key, klen);
|
144
144
|
|
145
145
|
rkey = oj_encode(rkey);
|
146
146
|
if (Yes == pi->options.sym_key) {
|
@@ -151,7 +151,7 @@ hash_key(ParseInfo pi, const char *key, size_t klen) {
|
|
151
151
|
|
152
152
|
static void
|
153
153
|
hash_set_cstr(ParseInfo pi, const char *key, size_t klen, const char *str, size_t len, const char *orig) {
|
154
|
-
VALUE rstr = rb_str_new(str, len);
|
154
|
+
volatile VALUE rstr = rb_str_new(str, len);
|
155
155
|
|
156
156
|
rstr = oj_encode(rstr);
|
157
157
|
rb_funcall((VALUE)pi->cbc, oj_hash_set_id, 3, stack_peek(&pi->stack)->val, hash_key(pi, key, klen), rstr);
|
@@ -169,7 +169,7 @@ hash_set_value(ParseInfo pi, const char *key, size_t klen, VALUE value) {
|
|
169
169
|
|
170
170
|
static void
|
171
171
|
array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
172
|
-
VALUE rstr = rb_str_new(str, len);
|
172
|
+
volatile VALUE rstr = rb_str_new(str, len);
|
173
173
|
|
174
174
|
rstr = oj_encode(rstr);
|
175
175
|
rb_funcall((VALUE)pi->cbc, oj_array_append_id, 2, stack_peek(&pi->stack)->val, rstr);
|