oj 3.13.7 → 3.13.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/README.md +9 -0
- data/ext/oj/custom.c +4 -4
- data/ext/oj/dump.c +63 -88
- data/ext/oj/dump.h +14 -1
- data/ext/oj/dump_compat.c +1 -1
- data/ext/oj/dump_object.c +46 -39
- data/ext/oj/dump_strict.c +2 -2
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/fast.c +13 -3
- data/ext/oj/intern.c +7 -1
- data/ext/oj/mimic_json.c +48 -59
- data/ext/oj/object.c +27 -46
- data/ext/oj/oj.c +109 -153
- data/ext/oj/oj.h +1 -0
- data/ext/oj/parse.c +9 -1
- data/ext/oj/rails.c +5 -5
- data/ext/oj/usual.c +4 -2
- data/ext/oj/wab.c +1 -1
- data/lib/oj/version.rb +1 -1
- data/pages/JsonGem.md +15 -0
- data/pages/Modes.md +6 -3
- data/pages/Rails.md +12 -0
- data/test/bug.rb +16 -0
- data/test/foo.rb +71 -7
- data/test/test_fast.rb +37 -7
- data/test/test_saj.rb +1 -1
- data/test/test_various.rb +27 -2
- data/test/tests.rb +0 -1
- metadata +5 -2
data/ext/oj/intern.c
CHANGED
@@ -186,6 +186,7 @@ static VALUE resolve_classpath(ParseInfo pi, const char *name, size_t len, int a
|
|
186
186
|
char * end = class_name + sizeof(class_name) - 1;
|
187
187
|
char * s;
|
188
188
|
const char *n = name;
|
189
|
+
size_t nlen = len;
|
189
190
|
|
190
191
|
clas = rb_cObject;
|
191
192
|
for (s = class_name; 0 < len; n++, len--) {
|
@@ -208,7 +209,12 @@ static VALUE resolve_classpath(ParseInfo pi, const char *name, size_t len, int a
|
|
208
209
|
}
|
209
210
|
*s = '\0';
|
210
211
|
if (Qundef == (clas = resolve_classname(clas, class_name, auto_define))) {
|
211
|
-
|
212
|
+
if (sizeof(class_name) <= nlen) {
|
213
|
+
nlen = sizeof(class_name) - 1;
|
214
|
+
}
|
215
|
+
strncpy(class_name, name, nlen);
|
216
|
+
class_name[nlen] = '\0';
|
217
|
+
oj_set_error_at(pi, error_class, __FILE__, __LINE__, "class '%s' is not defined", class_name);
|
212
218
|
if (Qnil != error_class) {
|
213
219
|
pi->err_class = error_class;
|
214
220
|
}
|
data/ext/oj/mimic_json.c
CHANGED
@@ -6,8 +6,6 @@
|
|
6
6
|
#include "oj.h"
|
7
7
|
#include "parse.h"
|
8
8
|
|
9
|
-
static VALUE symbolize_names_sym = Qundef;
|
10
|
-
|
11
9
|
extern const char oj_json_class[];
|
12
10
|
|
13
11
|
VALUE oj_array_nl_sym;
|
@@ -274,7 +272,7 @@ static int mimic_walk(VALUE key, VALUE obj, VALUE proc) {
|
|
274
272
|
size_t i;
|
275
273
|
|
276
274
|
for (i = 0; i < cnt; i++) {
|
277
|
-
mimic_walk(Qnil,
|
275
|
+
mimic_walk(Qnil, RARRAY_AREF(obj, i), proc);
|
278
276
|
}
|
279
277
|
break;
|
280
278
|
}
|
@@ -501,6 +499,52 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
501
499
|
return mimic_generate_core(2, rargs, &copts);
|
502
500
|
}
|
503
501
|
|
502
|
+
static int parse_options_cb(VALUE k, VALUE v, VALUE info) {
|
503
|
+
struct _parseInfo *pi = (struct _parseInfo *)info;
|
504
|
+
|
505
|
+
if (oj_symbolize_names_sym == k) {
|
506
|
+
pi->options.sym_key = (Qtrue == v) ? Yes : No;
|
507
|
+
} else if (oj_quirks_mode_sym == k) {
|
508
|
+
pi->options.quirks_mode = (Qtrue == v) ? Yes : No;
|
509
|
+
} else if (oj_create_additions_sym == k) {
|
510
|
+
pi->options.create_ok = (Qtrue == v) ? Yes : No;
|
511
|
+
} else if (oj_allow_nan_sym == k) {
|
512
|
+
pi->options.allow_nan = (Qtrue == v) ? Yes : No;
|
513
|
+
} else if (oj_hash_class_sym == k) {
|
514
|
+
if (Qnil == v) {
|
515
|
+
pi->options.hash_class = Qnil;
|
516
|
+
} else {
|
517
|
+
rb_check_type(v, T_CLASS);
|
518
|
+
pi->options.hash_class = v;
|
519
|
+
}
|
520
|
+
} else if (oj_object_class_sym == k) {
|
521
|
+
if (Qnil == v) {
|
522
|
+
pi->options.hash_class = Qnil;
|
523
|
+
} else {
|
524
|
+
rb_check_type(v, T_CLASS);
|
525
|
+
pi->options.hash_class = v;
|
526
|
+
}
|
527
|
+
} else if (oj_array_class_sym == k) {
|
528
|
+
if (Qnil == v) {
|
529
|
+
pi->options.array_class = Qnil;
|
530
|
+
} else {
|
531
|
+
rb_check_type(v, T_CLASS);
|
532
|
+
pi->options.array_class = v;
|
533
|
+
}
|
534
|
+
} else if (oj_decimal_class_sym == k) {
|
535
|
+
pi->options.compat_bigdec = (oj_bigdecimal_class == v);
|
536
|
+
} else if (oj_max_nesting_sym == k) {
|
537
|
+
if (Qtrue == v) {
|
538
|
+
pi->max_depth = 100;
|
539
|
+
} else if (Qfalse == v || Qnil == v) {
|
540
|
+
pi->max_depth = 0;
|
541
|
+
} else if (T_FIXNUM == rb_type(v)) {
|
542
|
+
pi->max_depth = NUM2INT(v);
|
543
|
+
}
|
544
|
+
}
|
545
|
+
return ST_CONTINUE;
|
546
|
+
}
|
547
|
+
|
504
548
|
static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
505
549
|
struct _parseInfo pi;
|
506
550
|
VALUE ropts;
|
@@ -526,63 +570,11 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
526
570
|
pi.max_depth = 100;
|
527
571
|
|
528
572
|
if (Qnil != ropts) {
|
529
|
-
VALUE v;
|
530
|
-
|
531
573
|
if (T_HASH != rb_type(ropts)) {
|
532
574
|
rb_raise(rb_eArgError, "options must be a hash.");
|
533
575
|
}
|
534
|
-
if (Qundef == symbolize_names_sym) {
|
535
|
-
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names"));
|
536
|
-
rb_gc_register_address(&symbolize_names_sym);
|
537
|
-
}
|
538
|
-
if (Qnil != (v = rb_hash_lookup(ropts, symbolize_names_sym))) {
|
539
|
-
pi.options.sym_key = (Qtrue == v) ? Yes : No;
|
540
|
-
}
|
541
|
-
if (Qnil != (v = rb_hash_lookup(ropts, oj_quirks_mode_sym))) {
|
542
|
-
pi.options.quirks_mode = (Qtrue == v) ? Yes : No;
|
543
|
-
}
|
544
|
-
if (Qnil != (v = rb_hash_lookup(ropts, oj_create_additions_sym))) {
|
545
|
-
pi.options.create_ok = (Qtrue == v) ? Yes : No;
|
546
|
-
}
|
547
|
-
if (Qnil != (v = rb_hash_lookup(ropts, oj_allow_nan_sym))) {
|
548
|
-
pi.options.allow_nan = (Qtrue == v) ? Yes : No;
|
549
|
-
}
|
550
576
|
|
551
|
-
|
552
|
-
if (Qnil == (v = rb_hash_lookup(ropts, oj_hash_class_sym))) {
|
553
|
-
pi.options.hash_class = Qnil;
|
554
|
-
} else {
|
555
|
-
rb_check_type(v, T_CLASS);
|
556
|
-
pi.options.hash_class = v;
|
557
|
-
}
|
558
|
-
}
|
559
|
-
if (oj_hash_has_key(ropts, oj_object_class_sym)) {
|
560
|
-
if (Qnil == (v = rb_hash_lookup(ropts, oj_object_class_sym))) {
|
561
|
-
pi.options.hash_class = Qnil;
|
562
|
-
} else {
|
563
|
-
rb_check_type(v, T_CLASS);
|
564
|
-
pi.options.hash_class = v;
|
565
|
-
}
|
566
|
-
}
|
567
|
-
if (oj_hash_has_key(ropts, oj_array_class_sym)) {
|
568
|
-
if (Qnil == (v = rb_hash_lookup(ropts, oj_array_class_sym))) {
|
569
|
-
pi.options.array_class = Qnil;
|
570
|
-
} else {
|
571
|
-
rb_check_type(v, T_CLASS);
|
572
|
-
pi.options.array_class = v;
|
573
|
-
}
|
574
|
-
}
|
575
|
-
if (oj_hash_has_key(ropts, oj_decimal_class_sym)) {
|
576
|
-
pi.options.compat_bigdec = (oj_bigdecimal_class == rb_hash_lookup(ropts, oj_decimal_class_sym));
|
577
|
-
}
|
578
|
-
v = rb_hash_lookup(ropts, oj_max_nesting_sym);
|
579
|
-
if (Qtrue == v) {
|
580
|
-
pi.max_depth = 100;
|
581
|
-
} else if (Qfalse == v || Qnil == v) {
|
582
|
-
pi.max_depth = 0;
|
583
|
-
} else if (T_FIXNUM == rb_type(v)) {
|
584
|
-
pi.max_depth = NUM2INT(v);
|
585
|
-
}
|
577
|
+
rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
|
586
578
|
oj_parse_opt_match_string(&pi.options.str_rx, ropts);
|
587
579
|
if (Yes == pi.options.create_ok && Yes == pi.options.sym_key) {
|
588
580
|
rb_raise(rb_eArgError, ":symbolize_names and :create_additions can not both be true.");
|
@@ -852,9 +844,6 @@ void oj_mimic_json_methods(VALUE json) {
|
|
852
844
|
// Pull in the JSON::State mimic file.
|
853
845
|
state_class = rb_const_get_at(generator, rb_intern("State"));
|
854
846
|
rb_gc_register_mark_object(state_class);
|
855
|
-
|
856
|
-
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names"));
|
857
|
-
rb_gc_register_address(&symbolize_names_sym);
|
858
847
|
}
|
859
848
|
|
860
849
|
/* Document-module: JSON
|
data/ext/oj/object.c
CHANGED
@@ -35,7 +35,7 @@ static VALUE calc_hash_key(ParseInfo pi, Val kval, char k1) {
|
|
35
35
|
return ID2SYM(rb_intern3(kval->key + 1, kval->klen - 1, oj_utf8_encoding));
|
36
36
|
}
|
37
37
|
if (Yes == pi->options.sym_key) {
|
38
|
-
|
38
|
+
return ID2SYM(rb_intern3(kval->key, kval->klen, oj_utf8_encoding));
|
39
39
|
}
|
40
40
|
#if HAVE_RB_ENC_INTERNED_STR
|
41
41
|
rkey = rb_enc_interned_str(kval->key, kval->klen, oj_utf8_encoding);
|
@@ -60,21 +60,16 @@ static VALUE str_to_value(ParseInfo pi, const char *str, size_t len, const char
|
|
60
60
|
}
|
61
61
|
rstr = oj_circ_array_get(pi->circ_array, i);
|
62
62
|
} else {
|
63
|
-
|
63
|
+
rstr = rb_utf8_str_new(str, len);
|
64
64
|
}
|
65
65
|
return rstr;
|
66
66
|
}
|
67
67
|
|
68
|
-
#if (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8)
|
69
|
-
static VALUE oj_parse_xml_time(const char *str, int len) {
|
70
|
-
return rb_funcall(rb_cTime, oj_parse_id, 1, rb_str_new(str, len));
|
71
|
-
}
|
72
|
-
#else
|
73
68
|
// The much faster approach (4x faster)
|
74
69
|
static int parse_num(const char *str, const char *end, int cnt) {
|
75
|
-
int
|
70
|
+
int n = 0;
|
76
71
|
char c;
|
77
|
-
int
|
72
|
+
int i;
|
78
73
|
|
79
74
|
for (i = cnt; 0 < i; i--, str++) {
|
80
75
|
c = *str;
|
@@ -88,9 +83,9 @@ static int parse_num(const char *str, const char *end, int cnt) {
|
|
88
83
|
|
89
84
|
VALUE
|
90
85
|
oj_parse_xml_time(const char *str, int len) {
|
91
|
-
VALUE
|
86
|
+
VALUE args[8];
|
92
87
|
const char *end = str + len;
|
93
|
-
int
|
88
|
+
int n;
|
94
89
|
|
95
90
|
// year
|
96
91
|
if (0 > (n = parse_num(str, end, 4))) {
|
@@ -201,7 +196,6 @@ oj_parse_xml_time(const char *str, int len) {
|
|
201
196
|
}
|
202
197
|
return rb_funcall2(rb_cTime, oj_new_id, 7, args);
|
203
198
|
}
|
204
|
-
#endif
|
205
199
|
|
206
200
|
static int hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t len) {
|
207
201
|
const char *key = kval->key;
|
@@ -226,13 +220,10 @@ static int hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t
|
|
226
220
|
}
|
227
221
|
parent->val = odd->clas;
|
228
222
|
parent->odd_args = oj_odd_alloc_args(odd);
|
229
|
-
} break;
|
230
|
-
case 'm':
|
231
|
-
parent->val = ID2SYM(rb_intern3(str + 1, len - 1, oj_utf8_encoding));
|
232
|
-
break;
|
233
|
-
case 's':
|
234
|
-
parent->val = rb_utf8_str_new(str, len);
|
235
223
|
break;
|
224
|
+
}
|
225
|
+
case 'm': parent->val = ID2SYM(rb_intern3(str + 1, len - 1, oj_utf8_encoding)); break;
|
226
|
+
case 's': parent->val = rb_utf8_str_new(str, len); break;
|
236
227
|
case 'c': // class
|
237
228
|
{
|
238
229
|
VALUE clas = oj_name2class(pi, str, len, Yes == pi->options.auto_define, rb_eArgError);
|
@@ -242,7 +233,8 @@ static int hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t
|
|
242
233
|
} else {
|
243
234
|
parent->val = clas;
|
244
235
|
}
|
245
|
-
|
236
|
+
break;
|
237
|
+
}
|
246
238
|
case 't': // time
|
247
239
|
parent->val = oj_parse_xml_time(str, (int)len);
|
248
240
|
break;
|
@@ -282,22 +274,21 @@ static int hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
|
|
282
274
|
VALUE args[8];
|
283
275
|
|
284
276
|
sec_as_time(t, &ti);
|
285
|
-
args[0]
|
286
|
-
args[1]
|
287
|
-
args[2]
|
288
|
-
args[3]
|
289
|
-
args[4]
|
290
|
-
args[5]
|
291
|
-
args[6]
|
277
|
+
args[0] = LONG2NUM((long)(ti.year));
|
278
|
+
args[1] = LONG2NUM(ti.mon);
|
279
|
+
args[2] = LONG2NUM(ti.day);
|
280
|
+
args[3] = LONG2NUM(ti.hour);
|
281
|
+
args[4] = LONG2NUM(ti.min);
|
282
|
+
args[5] = rb_float_new((double)ti.sec + ((double)nsec + 0.5) / 1000000000.0);
|
283
|
+
args[6] = LONG2NUM(ni->exp);
|
292
284
|
parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
|
293
285
|
} else {
|
294
286
|
parent->val = rb_time_nano_new(ni->i, (long)nsec);
|
295
287
|
}
|
296
288
|
}
|
297
289
|
break;
|
298
|
-
case 'i':
|
299
|
-
if (!ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp &&
|
300
|
-
0 != pi->circ_array) { // fixnum
|
290
|
+
case 'i': // circular index
|
291
|
+
if (!ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp && 0 != pi->circ_array) { // fixnum
|
301
292
|
if (Qnil == parent->val) {
|
302
293
|
parent->val = rb_hash_new();
|
303
294
|
}
|
@@ -334,7 +325,7 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
|
|
334
325
|
int i, cnt = (int)RARRAY_LEN(e1);
|
335
326
|
|
336
327
|
for (i = 0; i < cnt; i++) {
|
337
|
-
rstr =
|
328
|
+
rstr = RARRAY_AREF(e1, i);
|
338
329
|
args[i] = rb_funcall(rstr, oj_to_sym_id, 0);
|
339
330
|
}
|
340
331
|
sc = rb_funcall2(rb_cStruct, oj_new_id, cnt, args);
|
@@ -402,9 +393,7 @@ WHICH_TYPE:
|
|
402
393
|
}
|
403
394
|
break;
|
404
395
|
case T_HASH:
|
405
|
-
rb_hash_aset(parent->val,
|
406
|
-
calc_hash_key(pi, kval, parent->k1),
|
407
|
-
str_to_value(pi, str, len, orig));
|
396
|
+
rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), str_to_value(pi, str, len, orig));
|
408
397
|
break;
|
409
398
|
case T_STRING:
|
410
399
|
rval = str_to_value(pi, str, len, orig);
|
@@ -481,8 +470,8 @@ WHICH_TYPE:
|
|
481
470
|
rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), rval);
|
482
471
|
break;
|
483
472
|
case T_OBJECT:
|
484
|
-
if (2 == klen && '^' == *key && 'i' == key[1] && !ni->infinity && !ni->neg &&
|
485
|
-
|
473
|
+
if (2 == klen && '^' == *key && 'i' == key[1] && !ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp &&
|
474
|
+
0 != pi->circ_array) { // fixnum
|
486
475
|
oj_circ_array_set(pi->circ_array, parent->val, ni->i);
|
487
476
|
} else {
|
488
477
|
rval = oj_num_as_value(ni);
|
@@ -559,11 +548,7 @@ WHICH_TYPE:
|
|
559
548
|
volatile VALUE *a = RARRAY_PTR(value);
|
560
549
|
|
561
550
|
if (2 != len) {
|
562
|
-
oj_set_error_at(pi,
|
563
|
-
oj_parse_error_class,
|
564
|
-
__FILE__,
|
565
|
-
__LINE__,
|
566
|
-
"invalid hash pair");
|
551
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
|
567
552
|
return;
|
568
553
|
}
|
569
554
|
rb_hash_aset(parent->val, *a, a[1]);
|
@@ -637,10 +622,7 @@ static void end_hash(ParseInfo pi) {
|
|
637
622
|
} else if (NULL != parent->odd_args) {
|
638
623
|
OddArgs oa = parent->odd_args;
|
639
624
|
|
640
|
-
parent->val = rb_funcall2(oa->odd->create_obj,
|
641
|
-
oa->odd->create_op,
|
642
|
-
oa->odd->attr_cnt,
|
643
|
-
oa->args);
|
625
|
+
parent->val = rb_funcall2(oa->odd->create_obj, oa->odd->create_op, oa->odd->attr_cnt, oa->args);
|
644
626
|
oj_odd_free(oa);
|
645
627
|
parent->odd_args = NULL;
|
646
628
|
}
|
@@ -653,8 +635,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
|
|
653
635
|
volatile VALUE rval = Qnil;
|
654
636
|
|
655
637
|
// orig lets us know whether the string was ^r1 or \u005er1
|
656
|
-
if (3 <= len && 0 != pi->circ_array && '^' == orig[0] &&
|
657
|
-
0 == rb_array_len(stack_peek(&pi->stack)->val)) {
|
638
|
+
if (3 <= len && 0 != pi->circ_array && '^' == orig[0] && 0 == rb_array_len(stack_peek(&pi->stack)->val)) {
|
658
639
|
if ('i' == str[1]) {
|
659
640
|
long i = read_long(str + 2, len - 2);
|
660
641
|
|