oj 3.13.9 → 3.13.12
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 +14 -0
- data/README.md +9 -0
- data/ext/oj/circarray.c +1 -1
- data/ext/oj/code.c +15 -22
- data/ext/oj/custom.c +32 -59
- data/ext/oj/dump.c +129 -175
- data/ext/oj/dump.h +25 -8
- data/ext/oj/dump_compat.c +44 -81
- data/ext/oj/dump_leaf.c +14 -58
- data/ext/oj/dump_object.c +68 -129
- data/ext/oj/dump_strict.c +14 -26
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/fast.c +15 -9
- data/ext/oj/intern.c +9 -2
- data/ext/oj/intern.h +1 -1
- data/ext/oj/mimic_json.c +73 -73
- data/ext/oj/object.c +1 -1
- data/ext/oj/odd.c +83 -63
- data/ext/oj/odd.h +13 -13
- data/ext/oj/oj.c +29 -17
- data/ext/oj/oj.h +20 -2
- data/ext/oj/parse.c +3 -2
- data/ext/oj/parser.c +10 -15
- data/ext/oj/rails.c +43 -62
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +2 -0
- data/ext/oj/saj.c +11 -23
- data/ext/oj/stream_writer.c +3 -1
- data/ext/oj/string_writer.c +12 -5
- data/ext/oj/wab.c +9 -9
- 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/bar.rb +1 -8
- data/test/foo.rb +70 -13
- data/test/perf_dump.rb +50 -0
- data/test/test_fast.rb +19 -0
- data/test/test_object.rb +12 -7
- data/test/test_saj.rb +1 -1
- data/test/test_various.rb +27 -2
- data/test/tests.rb +0 -1
- metadata +6 -3
data/ext/oj/intern.h
CHANGED
data/ext/oj/mimic_json.c
CHANGED
@@ -198,7 +198,6 @@ static int mimic_limit_arg(VALUE a) {
|
|
198
198
|
* Returns [_String_] a JSON string.
|
199
199
|
*/
|
200
200
|
static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
|
201
|
-
char buf[4096];
|
202
201
|
struct _out out;
|
203
202
|
struct _options copts = oj_default_options;
|
204
203
|
VALUE rstr;
|
@@ -206,9 +205,9 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
206
205
|
|
207
206
|
copts.str_rx.head = NULL;
|
208
207
|
copts.str_rx.tail = NULL;
|
209
|
-
|
210
|
-
out
|
211
|
-
|
208
|
+
|
209
|
+
oj_out_init(&out);
|
210
|
+
|
212
211
|
out.caller = CALLER_DUMP;
|
213
212
|
copts.escape_mode = JXEsc;
|
214
213
|
copts.mode = CompatMode;
|
@@ -257,9 +256,9 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
257
256
|
rb_funcall2(io, oj_write_id, 1, args);
|
258
257
|
rstr = io;
|
259
258
|
}
|
260
|
-
|
261
|
-
|
262
|
-
|
259
|
+
|
260
|
+
oj_out_free(&out);
|
261
|
+
|
263
262
|
return rstr;
|
264
263
|
}
|
265
264
|
|
@@ -272,7 +271,7 @@ static int mimic_walk(VALUE key, VALUE obj, VALUE proc) {
|
|
272
271
|
size_t i;
|
273
272
|
|
274
273
|
for (i = 0; i < cnt; i++) {
|
275
|
-
mimic_walk(Qnil,
|
274
|
+
mimic_walk(Qnil, RARRAY_AREF(obj, i), proc);
|
276
275
|
}
|
277
276
|
break;
|
278
277
|
}
|
@@ -358,15 +357,16 @@ static VALUE mimic_dump_load(int argc, VALUE *argv, VALUE self) {
|
|
358
357
|
}
|
359
358
|
|
360
359
|
static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
361
|
-
char buf[4096];
|
362
360
|
struct _out out;
|
363
361
|
VALUE rstr;
|
364
362
|
|
365
|
-
|
363
|
+
if (0 == argc) {
|
364
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0))");
|
365
|
+
}
|
366
|
+
memset(out.stack_buffer, 0, sizeof(out.stack_buffer));
|
367
|
+
|
368
|
+
oj_out_init(&out);
|
366
369
|
|
367
|
-
out.buf = buf;
|
368
|
-
out.end = buf + sizeof(buf) - 10;
|
369
|
-
out.allocated = false;
|
370
370
|
out.omit_nil = copts->dump_opts.omit_nil;
|
371
371
|
out.caller = CALLER_GENERATE;
|
372
372
|
// For obj.to_json or generate nan is not allowed but if called from dump
|
@@ -398,9 +398,9 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
398
398
|
}
|
399
399
|
rstr = rb_str_new2(out.buf);
|
400
400
|
rstr = oj_encode(rstr);
|
401
|
-
|
402
|
-
|
403
|
-
|
401
|
+
|
402
|
+
oj_out_free(&out);
|
403
|
+
|
404
404
|
return rstr;
|
405
405
|
}
|
406
406
|
|
@@ -457,9 +457,12 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
457
457
|
// a Hash. I haven't dug deep enough to find out why but using a State
|
458
458
|
// instance and not a Hash gives the desired behavior.
|
459
459
|
*rargs = *argv;
|
460
|
+
if (0 == argc) {
|
461
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0))");
|
462
|
+
}
|
460
463
|
if (1 == argc) {
|
461
464
|
h = rb_hash_new();
|
462
|
-
} else
|
465
|
+
} else {
|
463
466
|
h = argv[1];
|
464
467
|
}
|
465
468
|
if (!oj_hash_has_key(h, oj_indent_sym)) {
|
@@ -499,6 +502,52 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
499
502
|
return mimic_generate_core(2, rargs, &copts);
|
500
503
|
}
|
501
504
|
|
505
|
+
static int parse_options_cb(VALUE k, VALUE v, VALUE info) {
|
506
|
+
struct _parseInfo *pi = (struct _parseInfo *)info;
|
507
|
+
|
508
|
+
if (oj_symbolize_names_sym == k) {
|
509
|
+
pi->options.sym_key = (Qtrue == v) ? Yes : No;
|
510
|
+
} else if (oj_quirks_mode_sym == k) {
|
511
|
+
pi->options.quirks_mode = (Qtrue == v) ? Yes : No;
|
512
|
+
} else if (oj_create_additions_sym == k) {
|
513
|
+
pi->options.create_ok = (Qtrue == v) ? Yes : No;
|
514
|
+
} else if (oj_allow_nan_sym == k) {
|
515
|
+
pi->options.allow_nan = (Qtrue == v) ? Yes : No;
|
516
|
+
} else if (oj_hash_class_sym == k) {
|
517
|
+
if (Qnil == v) {
|
518
|
+
pi->options.hash_class = Qnil;
|
519
|
+
} else {
|
520
|
+
rb_check_type(v, T_CLASS);
|
521
|
+
pi->options.hash_class = v;
|
522
|
+
}
|
523
|
+
} else if (oj_object_class_sym == k) {
|
524
|
+
if (Qnil == v) {
|
525
|
+
pi->options.hash_class = Qnil;
|
526
|
+
} else {
|
527
|
+
rb_check_type(v, T_CLASS);
|
528
|
+
pi->options.hash_class = v;
|
529
|
+
}
|
530
|
+
} else if (oj_array_class_sym == k) {
|
531
|
+
if (Qnil == v) {
|
532
|
+
pi->options.array_class = Qnil;
|
533
|
+
} else {
|
534
|
+
rb_check_type(v, T_CLASS);
|
535
|
+
pi->options.array_class = v;
|
536
|
+
}
|
537
|
+
} else if (oj_decimal_class_sym == k) {
|
538
|
+
pi->options.compat_bigdec = (oj_bigdecimal_class == v);
|
539
|
+
} else if (oj_max_nesting_sym == k) {
|
540
|
+
if (Qtrue == v) {
|
541
|
+
pi->max_depth = 100;
|
542
|
+
} else if (Qfalse == v || Qnil == v) {
|
543
|
+
pi->max_depth = 0;
|
544
|
+
} else if (T_FIXNUM == rb_type(v)) {
|
545
|
+
pi->max_depth = NUM2INT(v);
|
546
|
+
}
|
547
|
+
}
|
548
|
+
return ST_CONTINUE;
|
549
|
+
}
|
550
|
+
|
502
551
|
static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
503
552
|
struct _parseInfo pi;
|
504
553
|
VALUE ropts;
|
@@ -524,59 +573,11 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
524
573
|
pi.max_depth = 100;
|
525
574
|
|
526
575
|
if (Qnil != ropts) {
|
527
|
-
VALUE v;
|
528
|
-
|
529
576
|
if (T_HASH != rb_type(ropts)) {
|
530
577
|
rb_raise(rb_eArgError, "options must be a hash.");
|
531
578
|
}
|
532
|
-
if (Qnil != (v = rb_hash_lookup(ropts, oj_symbolize_names_sym))) {
|
533
|
-
pi.options.sym_key = (Qtrue == v) ? Yes : No;
|
534
|
-
}
|
535
|
-
if (Qnil != (v = rb_hash_lookup(ropts, oj_quirks_mode_sym))) {
|
536
|
-
pi.options.quirks_mode = (Qtrue == v) ? Yes : No;
|
537
|
-
}
|
538
|
-
if (Qnil != (v = rb_hash_lookup(ropts, oj_create_additions_sym))) {
|
539
|
-
pi.options.create_ok = (Qtrue == v) ? Yes : No;
|
540
|
-
}
|
541
|
-
if (Qnil != (v = rb_hash_lookup(ropts, oj_allow_nan_sym))) {
|
542
|
-
pi.options.allow_nan = (Qtrue == v) ? Yes : No;
|
543
|
-
}
|
544
579
|
|
545
|
-
|
546
|
-
if (Qnil == (v = rb_hash_lookup(ropts, oj_hash_class_sym))) {
|
547
|
-
pi.options.hash_class = Qnil;
|
548
|
-
} else {
|
549
|
-
rb_check_type(v, T_CLASS);
|
550
|
-
pi.options.hash_class = v;
|
551
|
-
}
|
552
|
-
}
|
553
|
-
if (oj_hash_has_key(ropts, oj_object_class_sym)) {
|
554
|
-
if (Qnil == (v = rb_hash_lookup(ropts, oj_object_class_sym))) {
|
555
|
-
pi.options.hash_class = Qnil;
|
556
|
-
} else {
|
557
|
-
rb_check_type(v, T_CLASS);
|
558
|
-
pi.options.hash_class = v;
|
559
|
-
}
|
560
|
-
}
|
561
|
-
if (oj_hash_has_key(ropts, oj_array_class_sym)) {
|
562
|
-
if (Qnil == (v = rb_hash_lookup(ropts, oj_array_class_sym))) {
|
563
|
-
pi.options.array_class = Qnil;
|
564
|
-
} else {
|
565
|
-
rb_check_type(v, T_CLASS);
|
566
|
-
pi.options.array_class = v;
|
567
|
-
}
|
568
|
-
}
|
569
|
-
if (oj_hash_has_key(ropts, oj_decimal_class_sym)) {
|
570
|
-
pi.options.compat_bigdec = (oj_bigdecimal_class == rb_hash_lookup(ropts, oj_decimal_class_sym));
|
571
|
-
}
|
572
|
-
v = rb_hash_lookup(ropts, oj_max_nesting_sym);
|
573
|
-
if (Qtrue == v) {
|
574
|
-
pi.max_depth = 100;
|
575
|
-
} else if (Qfalse == v || Qnil == v) {
|
576
|
-
pi.max_depth = 0;
|
577
|
-
} else if (T_FIXNUM == rb_type(v)) {
|
578
|
-
pi.max_depth = NUM2INT(v);
|
579
|
-
}
|
580
|
+
rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
|
580
581
|
oj_parse_opt_match_string(&pi.options.str_rx, ropts);
|
581
582
|
if (Yes == pi.options.create_ok && Yes == pi.options.sym_key) {
|
582
583
|
rb_raise(rb_eArgError, ":symbolize_names and :create_additions can not both be true.");
|
@@ -742,16 +743,15 @@ static struct _options mimic_object_to_json_options = {0, // indent
|
|
742
743
|
}};
|
743
744
|
|
744
745
|
static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
|
745
|
-
char buf[4096];
|
746
746
|
struct _out out;
|
747
747
|
VALUE rstr;
|
748
748
|
struct _options copts = oj_default_options;
|
749
749
|
|
750
750
|
copts.str_rx.head = NULL;
|
751
751
|
copts.str_rx.tail = NULL;
|
752
|
-
|
753
|
-
out
|
754
|
-
|
752
|
+
|
753
|
+
oj_out_init(&out);
|
754
|
+
|
755
755
|
out.omit_nil = copts.dump_opts.omit_nil;
|
756
756
|
copts.mode = CompatMode;
|
757
757
|
copts.to_json = No;
|
@@ -767,9 +767,9 @@ static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
|
|
767
767
|
}
|
768
768
|
rstr = rb_str_new2(out.buf);
|
769
769
|
rstr = oj_encode(rstr);
|
770
|
-
|
771
|
-
|
772
|
-
|
770
|
+
|
771
|
+
oj_out_free(&out);
|
772
|
+
|
773
773
|
return rstr;
|
774
774
|
}
|
775
775
|
|
data/ext/oj/object.c
CHANGED
@@ -325,7 +325,7 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
|
|
325
325
|
int i, cnt = (int)RARRAY_LEN(e1);
|
326
326
|
|
327
327
|
for (i = 0; i < cnt; i++) {
|
328
|
-
rstr =
|
328
|
+
rstr = RARRAY_AREF(e1, i);
|
329
329
|
args[i] = rb_funcall(rstr, oj_to_sym_id, 0);
|
330
330
|
}
|
331
331
|
sc = rb_funcall2(rb_cStruct, oj_new_id, cnt, args);
|
data/ext/oj/odd.c
CHANGED
@@ -5,28 +5,27 @@
|
|
5
5
|
|
6
6
|
#include <string.h>
|
7
7
|
|
8
|
-
static
|
9
|
-
static
|
10
|
-
static
|
11
|
-
static ID
|
12
|
-
static ID
|
13
|
-
static ID
|
14
|
-
static ID
|
15
|
-
static ID denominator_id;
|
16
|
-
static ID rational_id;
|
17
|
-
static VALUE rational_class;
|
8
|
+
static Odd odds = NULL;
|
9
|
+
static ID sec_id;
|
10
|
+
static ID sec_fraction_id;
|
11
|
+
static ID to_f_id;
|
12
|
+
static ID numerator_id;
|
13
|
+
static ID denominator_id;
|
14
|
+
static ID rational_id;
|
18
15
|
|
19
16
|
static void set_class(Odd odd, const char *classname) {
|
20
17
|
const char **np;
|
21
|
-
ID
|
18
|
+
ID *idp;
|
22
19
|
|
23
|
-
odd->classname
|
24
|
-
odd->clen
|
25
|
-
odd->clas
|
20
|
+
odd->classname = classname;
|
21
|
+
odd->clen = strlen(classname);
|
22
|
+
odd->clas = rb_const_get(rb_cObject, rb_intern(classname));
|
23
|
+
rb_gc_register_mark_object(odd->clas);
|
26
24
|
odd->create_obj = odd->clas;
|
27
|
-
odd->
|
28
|
-
odd->
|
29
|
-
odd->
|
25
|
+
rb_gc_register_mark_object(odd->create_obj);
|
26
|
+
odd->create_op = rb_intern("new");
|
27
|
+
odd->is_module = (T_MODULE == rb_type(odd->clas));
|
28
|
+
odd->raw = 0;
|
30
29
|
for (np = odd->attr_names, idp = odd->attrs; 0 != *np; np++, idp++) {
|
31
30
|
*idp = rb_intern(*np);
|
32
31
|
}
|
@@ -37,15 +36,48 @@ static VALUE get_datetime_secs(VALUE obj) {
|
|
37
36
|
volatile VALUE rsecs = rb_funcall(obj, sec_id, 0);
|
38
37
|
volatile VALUE rfrac = rb_funcall(obj, sec_fraction_id, 0);
|
39
38
|
long sec = NUM2LONG(rsecs);
|
40
|
-
long long num =
|
41
|
-
long long den =
|
39
|
+
long long num = NUM2LL(rb_funcall(rfrac, numerator_id, 0));
|
40
|
+
long long den = NUM2LL(rb_funcall(rfrac, denominator_id, 0));
|
42
41
|
|
43
42
|
num += sec * den;
|
44
43
|
|
45
44
|
return rb_funcall(rb_cObject, rational_id, 2, rb_ll2inum(num), rb_ll2inum(den));
|
46
45
|
}
|
47
46
|
|
48
|
-
void
|
47
|
+
static void print_odd(Odd odd) {
|
48
|
+
const char **np;
|
49
|
+
int i;
|
50
|
+
|
51
|
+
printf(" %s {\n", odd->classname);
|
52
|
+
printf(" attr_cnt: %d %p\n", odd->attr_cnt, (void *)odd->attr_names);
|
53
|
+
printf(" attr_names: %p\n", (void *)*odd->attr_names);
|
54
|
+
printf(" attr_names: %c\n", **odd->attr_names);
|
55
|
+
for (i = odd->attr_cnt, np = odd->attr_names; 0 < i; i--, np++) {
|
56
|
+
printf(" %d %s\n", i, *np);
|
57
|
+
}
|
58
|
+
printf(" }\n");
|
59
|
+
}
|
60
|
+
|
61
|
+
void print_all_odds(const char *label) {
|
62
|
+
Odd odd;
|
63
|
+
printf("@ %s {\n", label);
|
64
|
+
for (odd = odds; NULL != odd; odd = odd->next) {
|
65
|
+
print_odd(odd);
|
66
|
+
}
|
67
|
+
printf("}\n");
|
68
|
+
}
|
69
|
+
|
70
|
+
static Odd odd_create(void) {
|
71
|
+
Odd odd = ALLOC(struct _odd);
|
72
|
+
|
73
|
+
memset(odd, 0, sizeof(struct _odd));
|
74
|
+
odd->next = odds;
|
75
|
+
odds = odd;
|
76
|
+
|
77
|
+
return odd;
|
78
|
+
}
|
79
|
+
|
80
|
+
void oj_odd_init(void) {
|
49
81
|
Odd odd;
|
50
82
|
const char **np;
|
51
83
|
|
@@ -55,11 +87,9 @@ void oj_odd_init() {
|
|
55
87
|
numerator_id = rb_intern("numerator");
|
56
88
|
denominator_id = rb_intern("denominator");
|
57
89
|
rational_id = rb_intern("Rational");
|
58
|
-
rational_class = rb_const_get(rb_cObject, rational_id);
|
59
90
|
|
60
|
-
memset(_odds, 0, sizeof(_odds));
|
61
|
-
odd = odds;
|
62
91
|
// Rational
|
92
|
+
odd = odd_create();
|
63
93
|
np = odd->attr_names;
|
64
94
|
*np++ = "numerator";
|
65
95
|
*np++ = "denominator";
|
@@ -68,8 +98,9 @@ void oj_odd_init() {
|
|
68
98
|
odd->create_obj = rb_cObject;
|
69
99
|
odd->create_op = rational_id;
|
70
100
|
odd->attr_cnt = 2;
|
101
|
+
|
71
102
|
// Date
|
72
|
-
odd
|
103
|
+
odd = odd_create();
|
73
104
|
np = odd->attr_names;
|
74
105
|
*np++ = "year";
|
75
106
|
*np++ = "month";
|
@@ -78,8 +109,9 @@ void oj_odd_init() {
|
|
78
109
|
*np++ = 0;
|
79
110
|
set_class(odd, "Date");
|
80
111
|
odd->attr_cnt = 4;
|
112
|
+
|
81
113
|
// DateTime
|
82
|
-
odd
|
114
|
+
odd = odd_create();
|
83
115
|
np = odd->attr_names;
|
84
116
|
*np++ = "year";
|
85
117
|
*np++ = "month";
|
@@ -93,8 +125,9 @@ void oj_odd_init() {
|
|
93
125
|
set_class(odd, "DateTime");
|
94
126
|
odd->attr_cnt = 8;
|
95
127
|
odd->attrFuncs[5] = get_datetime_secs;
|
128
|
+
|
96
129
|
// Range
|
97
|
-
odd
|
130
|
+
odd = odd_create();
|
98
131
|
np = odd->attr_names;
|
99
132
|
*np++ = "begin";
|
100
133
|
*np++ = "end";
|
@@ -102,15 +135,13 @@ void oj_odd_init() {
|
|
102
135
|
*np++ = 0;
|
103
136
|
set_class(odd, "Range");
|
104
137
|
odd->attr_cnt = 3;
|
105
|
-
|
106
|
-
odd_cnt = odd - odds + 1;
|
107
138
|
}
|
108
139
|
|
109
140
|
Odd oj_get_odd(VALUE clas) {
|
110
141
|
Odd odd;
|
111
142
|
const char *classname = NULL;
|
112
143
|
|
113
|
-
for (odd = odds
|
144
|
+
for (odd = odds; NULL != odd; odd = odd->next) {
|
114
145
|
if (clas == odd->clas) {
|
115
146
|
return odd;
|
116
147
|
}
|
@@ -129,21 +160,20 @@ Odd oj_get_odd(VALUE clas) {
|
|
129
160
|
Odd oj_get_oddc(const char *classname, size_t len) {
|
130
161
|
Odd odd;
|
131
162
|
|
132
|
-
for (odd = odds
|
163
|
+
for (odd = odds; NULL != odd; odd = odd->next) {
|
133
164
|
if (len == odd->clen && 0 == strncmp(classname, odd->classname, len)) {
|
134
165
|
return odd;
|
135
166
|
}
|
136
|
-
if (odd->is_module && 0 == strncmp(odd->classname, classname, odd->clen) &&
|
137
|
-
':' == classname[odd->clen]) {
|
167
|
+
if (odd->is_module && 0 == strncmp(odd->classname, classname, odd->clen) && ':' == classname[odd->clen]) {
|
138
168
|
return odd;
|
139
169
|
}
|
140
170
|
}
|
141
|
-
return
|
171
|
+
return NULL;
|
142
172
|
}
|
143
173
|
|
144
174
|
OddArgs oj_odd_alloc_args(Odd odd) {
|
145
175
|
OddArgs oa = ALLOC_N(struct _oddArgs, 1);
|
146
|
-
VALUE
|
176
|
+
VALUE *a;
|
147
177
|
int i;
|
148
178
|
|
149
179
|
oa->odd = odd;
|
@@ -159,11 +189,10 @@ void oj_odd_free(OddArgs args) {
|
|
159
189
|
|
160
190
|
int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
|
161
191
|
const char **np;
|
162
|
-
VALUE
|
192
|
+
VALUE *vp;
|
163
193
|
int i;
|
164
194
|
|
165
|
-
for (i = args->odd->attr_cnt, np = args->odd->attr_names, vp = args->args; 0 < i;
|
166
|
-
i--, np++, vp++) {
|
195
|
+
for (i = args->odd->attr_cnt, np = args->odd->attr_names, vp = args->args; 0 < i; i--, np++, vp++) {
|
167
196
|
if (0 == strncmp(key, *np, klen) && '\0' == *((*np) + klen)) {
|
168
197
|
*vp = value;
|
169
198
|
return 0;
|
@@ -172,37 +201,26 @@ int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
|
|
172
201
|
return -1;
|
173
202
|
}
|
174
203
|
|
175
|
-
void oj_reg_odd(VALUE
|
176
|
-
VALUE create_object,
|
177
|
-
VALUE create_method,
|
178
|
-
int mcnt,
|
179
|
-
VALUE *members,
|
180
|
-
bool raw) {
|
204
|
+
void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw) {
|
181
205
|
Odd odd;
|
182
206
|
const char **np;
|
183
|
-
ID
|
207
|
+
ID *ap;
|
184
208
|
AttrGetFunc *fp;
|
185
209
|
|
186
|
-
|
187
|
-
odds = ALLOC_N(struct _odd, odd_cnt + 1);
|
188
|
-
|
189
|
-
memcpy(odds, _odds, sizeof(struct _odd) * odd_cnt);
|
190
|
-
} else {
|
191
|
-
REALLOC_N(odds, struct _odd, odd_cnt + 1);
|
192
|
-
}
|
193
|
-
odd = odds + odd_cnt;
|
210
|
+
odd = odd_create();
|
194
211
|
odd->clas = clas;
|
212
|
+
rb_gc_register_mark_object(odd->clas);
|
195
213
|
if (NULL == (odd->classname = strdup(rb_class2name(clas)))) {
|
196
|
-
rb_raise(rb_eNoMemError, "for
|
214
|
+
rb_raise(rb_eNoMemError, "for class name.");
|
197
215
|
}
|
198
216
|
odd->clen = strlen(odd->classname);
|
199
217
|
odd->create_obj = create_object;
|
200
|
-
odd->
|
201
|
-
odd->
|
202
|
-
odd->
|
203
|
-
odd->
|
204
|
-
|
205
|
-
|
218
|
+
rb_gc_register_mark_object(odd->create_obj);
|
219
|
+
odd->create_op = SYM2ID(create_method);
|
220
|
+
odd->attr_cnt = mcnt;
|
221
|
+
odd->is_module = (T_MODULE == rb_type(clas));
|
222
|
+
odd->raw = raw;
|
223
|
+
for (ap = odd->attrs, np = odd->attr_names, fp = odd->attrFuncs; 0 < mcnt; mcnt--, ap++, np++, members++, fp++) {
|
206
224
|
*fp = 0;
|
207
225
|
switch (rb_type(*members)) {
|
208
226
|
case T_STRING:
|
@@ -210,14 +228,16 @@ void oj_reg_odd(VALUE clas,
|
|
210
228
|
rb_raise(rb_eNoMemError, "for attribute name.");
|
211
229
|
}
|
212
230
|
break;
|
213
|
-
case T_SYMBOL:
|
214
|
-
|
215
|
-
|
231
|
+
case T_SYMBOL:
|
232
|
+
// The symbol can move and invalidate the name so make a copy.
|
233
|
+
if (NULL == (*np = strdup(rb_id2name(SYM2ID(*members))))) {
|
234
|
+
rb_raise(rb_eNoMemError, "for attribute name.");
|
235
|
+
}
|
216
236
|
break;
|
237
|
+
default: rb_raise(rb_eArgError, "registered member identifiers must be Strings or Symbols."); break;
|
217
238
|
}
|
218
239
|
*ap = rb_intern(*np);
|
219
240
|
}
|
220
241
|
*np = 0;
|
221
242
|
*ap = 0;
|
222
|
-
odd_cnt++;
|
223
243
|
}
|
data/ext/oj/odd.h
CHANGED
@@ -13,17 +13,18 @@
|
|
13
13
|
typedef VALUE (*AttrGetFunc)(VALUE obj);
|
14
14
|
|
15
15
|
typedef struct _odd {
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
VALUE
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
bool
|
24
|
-
|
25
|
-
|
26
|
-
|
16
|
+
struct _odd *next;
|
17
|
+
const char * classname;
|
18
|
+
size_t clen;
|
19
|
+
VALUE clas; // Ruby class or module
|
20
|
+
VALUE create_obj;
|
21
|
+
ID create_op;
|
22
|
+
int attr_cnt;
|
23
|
+
bool is_module;
|
24
|
+
bool raw;
|
25
|
+
const char * attr_names[MAX_ODD_ARGS]; // NULL terminated attr names
|
26
|
+
ID attrs[MAX_ODD_ARGS]; // 0 terminated attr IDs
|
27
|
+
AttrGetFunc attrFuncs[MAX_ODD_ARGS];
|
27
28
|
} * Odd;
|
28
29
|
|
29
30
|
typedef struct _oddArgs {
|
@@ -37,7 +38,6 @@ extern Odd oj_get_oddc(const char *classname, size_t len);
|
|
37
38
|
extern OddArgs oj_odd_alloc_args(Odd odd);
|
38
39
|
extern void oj_odd_free(OddArgs args);
|
39
40
|
extern int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value);
|
40
|
-
extern void
|
41
|
-
oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw);
|
41
|
+
extern void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw);
|
42
42
|
|
43
43
|
#endif /* OJ_ODD_H */
|
data/ext/oj/oj.c
CHANGED
@@ -153,6 +153,7 @@ static VALUE xmlschema_sym;
|
|
153
153
|
static VALUE xss_safe_sym;
|
154
154
|
|
155
155
|
rb_encoding *oj_utf8_encoding = 0;
|
156
|
+
int oj_utf8_encoding_index = 0;
|
156
157
|
|
157
158
|
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
158
159
|
pthread_mutex_t oj_cache_mutex;
|
@@ -916,7 +917,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
916
917
|
|
917
918
|
copts->ignore = ALLOC_N(VALUE, cnt + 1);
|
918
919
|
for (i = 0; i < cnt; i++) {
|
919
|
-
copts->ignore[i] =
|
920
|
+
copts->ignore[i] = RARRAY_AREF(v, i);
|
920
921
|
}
|
921
922
|
copts->ignore[i] = Qnil;
|
922
923
|
}
|
@@ -1243,9 +1244,8 @@ static VALUE dump_body(VALUE a) {
|
|
1243
1244
|
static VALUE dump_ensure(VALUE a) {
|
1244
1245
|
volatile struct dump_arg *arg = (void *)a;
|
1245
1246
|
|
1246
|
-
|
1247
|
-
|
1248
|
-
}
|
1247
|
+
oj_out_free(arg->out);
|
1248
|
+
|
1249
1249
|
return Qnil;
|
1250
1250
|
}
|
1251
1251
|
|
@@ -1257,7 +1257,6 @@ static VALUE dump_ensure(VALUE a) {
|
|
1257
1257
|
* - *options* [_Hash_] same as default_options
|
1258
1258
|
*/
|
1259
1259
|
static VALUE dump(int argc, VALUE *argv, VALUE self) {
|
1260
|
-
char buf[4096];
|
1261
1260
|
struct dump_arg arg;
|
1262
1261
|
struct _out out;
|
1263
1262
|
struct _options copts = oj_default_options;
|
@@ -1279,9 +1278,8 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
|
|
1279
1278
|
arg.argc = argc;
|
1280
1279
|
arg.argv = argv;
|
1281
1280
|
|
1282
|
-
arg.out
|
1283
|
-
|
1284
|
-
arg.out->allocated = false;
|
1281
|
+
oj_out_init(arg.out);
|
1282
|
+
|
1285
1283
|
arg.out->omit_nil = copts.dump_opts.omit_nil;
|
1286
1284
|
arg.out->caller = CALLER_DUMP;
|
1287
1285
|
|
@@ -1313,7 +1311,6 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
|
|
1313
1311
|
* Returns [_String_] the encoded JSON.
|
1314
1312
|
*/
|
1315
1313
|
static VALUE to_json(int argc, VALUE *argv, VALUE self) {
|
1316
|
-
char buf[4096];
|
1317
1314
|
struct _out out;
|
1318
1315
|
struct _options copts = oj_default_options;
|
1319
1316
|
VALUE rstr;
|
@@ -1328,9 +1325,9 @@ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
|
|
1328
1325
|
}
|
1329
1326
|
copts.mode = CompatMode;
|
1330
1327
|
copts.to_json = Yes;
|
1331
|
-
|
1332
|
-
out
|
1333
|
-
|
1328
|
+
|
1329
|
+
oj_out_init(&out);
|
1330
|
+
|
1334
1331
|
out.omit_nil = copts.dump_opts.omit_nil;
|
1335
1332
|
// For obj.to_json or generate nan is not allowed but if called from dump
|
1336
1333
|
// it is.
|
@@ -1341,9 +1338,9 @@ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
|
|
1341
1338
|
}
|
1342
1339
|
rstr = rb_str_new2(out.buf);
|
1343
1340
|
rstr = oj_encode(rstr);
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1341
|
+
|
1342
|
+
oj_out_free(&out);
|
1343
|
+
|
1347
1344
|
return rstr;
|
1348
1345
|
}
|
1349
1346
|
|
@@ -1703,6 +1700,15 @@ static VALUE protect_require(VALUE x) {
|
|
1703
1700
|
return Qnil;
|
1704
1701
|
}
|
1705
1702
|
|
1703
|
+
extern void print_all_odds(const char *label);
|
1704
|
+
|
1705
|
+
static VALUE
|
1706
|
+
debug_odd(VALUE self, VALUE label) {
|
1707
|
+
print_all_odds(RSTRING_PTR(label));
|
1708
|
+
return Qnil;
|
1709
|
+
}
|
1710
|
+
|
1711
|
+
|
1706
1712
|
/* Document-module: Oj
|
1707
1713
|
*
|
1708
1714
|
* Optimized JSON (Oj), as the name implies was written to provide speed
|
@@ -1731,15 +1737,19 @@ static VALUE protect_require(VALUE x) {
|
|
1731
1737
|
*
|
1732
1738
|
* - *:wab* specifically for WAB data exchange.
|
1733
1739
|
*/
|
1734
|
-
void Init_oj() {
|
1740
|
+
void Init_oj(void) {
|
1735
1741
|
int err = 0;
|
1736
1742
|
|
1737
1743
|
#if HAVE_RB_EXT_RACTOR_SAFE
|
1738
1744
|
rb_ext_ractor_safe(true);
|
1739
1745
|
#endif
|
1740
1746
|
Oj = rb_define_module("Oj");
|
1747
|
+
rb_gc_register_address(&Oj);
|
1741
1748
|
|
1742
1749
|
oj_cstack_class = rb_define_class_under(Oj, "CStack", rb_cObject);
|
1750
|
+
rb_gc_register_address(&oj_cstack_class);
|
1751
|
+
|
1752
|
+
rb_undef_alloc_func(oj_cstack_class);
|
1743
1753
|
|
1744
1754
|
oj_string_writer_init();
|
1745
1755
|
oj_stream_writer_init();
|
@@ -1748,9 +1758,11 @@ void Init_oj() {
|
|
1748
1758
|
// On Rubinius the require fails but can be done from a ruby file.
|
1749
1759
|
rb_protect(protect_require, Qnil, &err);
|
1750
1760
|
rb_require("stringio");
|
1751
|
-
|
1761
|
+
oj_utf8_encoding_index = rb_enc_find_index("UTF-8");
|
1762
|
+
oj_utf8_encoding = rb_enc_from_index(oj_utf8_encoding_index);
|
1752
1763
|
|
1753
1764
|
// rb_define_module_function(Oj, "hash_test", hash_test, 0);
|
1765
|
+
rb_define_module_function(Oj, "debug_odd", debug_odd, 1);
|
1754
1766
|
|
1755
1767
|
rb_define_module_function(Oj, "default_options", get_def_opts, 0);
|
1756
1768
|
rb_define_module_function(Oj, "default_options=", set_def_opts, 1);
|