oj 3.13.11 → 3.15.0
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 +74 -0
- data/README.md +4 -2
- data/ext/oj/buf.h +11 -6
- data/ext/oj/cache.c +25 -24
- data/ext/oj/cache8.c +10 -9
- data/ext/oj/circarray.c +8 -6
- data/ext/oj/circarray.h +2 -2
- data/ext/oj/code.c +17 -24
- data/ext/oj/code.h +2 -2
- data/ext/oj/compat.c +17 -44
- data/ext/oj/custom.c +70 -141
- data/ext/oj/debug.c +3 -9
- data/ext/oj/dump.c +128 -118
- data/ext/oj/dump.h +12 -8
- data/ext/oj/dump_compat.c +564 -641
- data/ext/oj/dump_leaf.c +17 -63
- data/ext/oj/dump_object.c +70 -199
- data/ext/oj/dump_strict.c +22 -46
- data/ext/oj/encoder.c +1 -1
- data/ext/oj/err.c +2 -13
- data/ext/oj/err.h +9 -12
- data/ext/oj/extconf.rb +14 -5
- data/ext/oj/fast.c +75 -103
- data/ext/oj/intern.c +52 -50
- data/ext/oj/intern.h +4 -8
- data/ext/oj/mem.c +318 -0
- data/ext/oj/mem.h +53 -0
- data/ext/oj/mimic_json.c +75 -47
- data/ext/oj/object.c +49 -66
- data/ext/oj/odd.c +89 -67
- data/ext/oj/odd.h +15 -15
- data/ext/oj/oj.c +140 -99
- data/ext/oj/oj.h +80 -51
- data/ext/oj/parse.c +162 -184
- data/ext/oj/parse.h +7 -10
- data/ext/oj/parser.c +89 -34
- data/ext/oj/parser.h +18 -7
- data/ext/oj/rails.c +82 -146
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +11 -12
- data/ext/oj/reader.h +4 -2
- data/ext/oj/resolve.c +3 -4
- data/ext/oj/rxclass.c +6 -5
- data/ext/oj/rxclass.h +1 -1
- data/ext/oj/saj.c +20 -31
- data/ext/oj/saj2.c +329 -93
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/scp.c +3 -14
- data/ext/oj/sparse.c +26 -70
- data/ext/oj/stream_writer.c +12 -22
- data/ext/oj/strict.c +20 -52
- data/ext/oj/string_writer.c +21 -21
- data/ext/oj/trace.h +31 -4
- data/ext/oj/usual.c +105 -150
- data/ext/oj/usual.h +68 -0
- data/ext/oj/util.h +1 -1
- data/ext/oj/val_stack.c +1 -1
- data/ext/oj/val_stack.h +8 -7
- data/ext/oj/validate.c +21 -26
- data/ext/oj/wab.c +31 -68
- data/lib/oj/active_support_helper.rb +0 -1
- data/lib/oj/bag.rb +7 -1
- data/lib/oj/easy_hash.rb +4 -5
- data/lib/oj/error.rb +0 -1
- data/lib/oj/json.rb +4 -2
- data/lib/oj/mimic.rb +4 -2
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/state.rb +9 -6
- data/lib/oj/version.rb +1 -2
- data/lib/oj.rb +2 -0
- data/pages/Compatibility.md +1 -1
- data/pages/InstallOptions.md +20 -0
- data/pages/Options.md +10 -0
- data/test/_test_active.rb +8 -9
- data/test/_test_active_mimic.rb +7 -8
- data/test/_test_mimic_rails.rb +17 -20
- data/test/activerecord/result_test.rb +5 -6
- data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
- data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
- data/test/{activesupport5 → activesupport7}/encoding_test.rb +20 -34
- data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
- data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
- data/test/files.rb +15 -15
- data/test/foo.rb +9 -71
- data/test/helper.rb +11 -8
- data/test/isolated/shared.rb +3 -2
- data/test/json_gem/json_addition_test.rb +2 -2
- data/test/json_gem/json_common_interface_test.rb +4 -4
- data/test/json_gem/json_encoding_test.rb +0 -0
- data/test/json_gem/json_ext_parser_test.rb +1 -0
- data/test/json_gem/json_fixtures_test.rb +3 -2
- data/test/json_gem/json_generator_test.rb +48 -36
- data/test/json_gem/json_generic_object_test.rb +11 -11
- data/test/json_gem/json_parser_test.rb +54 -47
- data/test/json_gem/json_string_matching_test.rb +9 -9
- data/test/json_gem/test_helper.rb +7 -3
- data/test/mem.rb +13 -12
- data/test/perf.rb +21 -26
- data/test/perf_compat.rb +31 -33
- data/test/perf_dump.rb +50 -0
- data/test/perf_fast.rb +80 -82
- data/test/perf_file.rb +27 -29
- data/test/perf_object.rb +65 -69
- data/test/perf_once.rb +12 -11
- data/test/perf_parser.rb +42 -48
- data/test/perf_saj.rb +46 -54
- data/test/perf_scp.rb +57 -69
- data/test/perf_simple.rb +41 -39
- data/test/perf_strict.rb +68 -70
- data/test/perf_wab.rb +67 -69
- data/test/prec.rb +3 -3
- data/test/sample/change.rb +0 -1
- data/test/sample/dir.rb +0 -1
- data/test/sample/doc.rb +0 -1
- data/test/sample/file.rb +0 -1
- data/test/sample/group.rb +0 -1
- data/test/sample/hasprops.rb +0 -1
- data/test/sample/layer.rb +0 -1
- data/test/sample/rect.rb +0 -1
- data/test/sample/shape.rb +0 -1
- data/test/sample/text.rb +0 -1
- data/test/sample.rb +16 -16
- data/test/sample_json.rb +8 -8
- data/test/test_compat.rb +76 -42
- data/test/test_custom.rb +72 -51
- data/test/test_debian.rb +7 -10
- data/test/test_fast.rb +86 -90
- data/test/test_file.rb +41 -30
- data/test/test_gc.rb +16 -5
- data/test/test_generate.rb +5 -5
- data/test/test_hash.rb +4 -4
- data/test/test_integer_range.rb +9 -9
- data/test/test_null.rb +20 -20
- data/test/test_object.rb +85 -96
- data/test/test_parser.rb +6 -22
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +115 -23
- data/test/test_parser_usual.rb +6 -6
- data/test/test_rails.rb +2 -2
- data/test/test_saj.rb +10 -8
- data/test/test_scp.rb +37 -39
- data/test/test_strict.rb +30 -32
- data/test/test_various.rb +147 -99
- data/test/test_wab.rb +48 -44
- data/test/test_writer.rb +47 -47
- data/test/tests.rb +13 -4
- data/test/tests_mimic.rb +12 -3
- data/test/tests_mimic_addition.rb +12 -3
- metadata +33 -144
- data/test/activesupport4/decoding_test.rb +0 -108
- data/test/activesupport4/encoding_test.rb +0 -531
- data/test/activesupport4/test_helper.rb +0 -41
- data/test/activesupport5/test_helper.rb +0 -72
- data/test/bar.rb +0 -16
- data/test/baz.rb +0 -16
- data/test/bug.rb +0 -16
- data/test/zoo.rb +0 -13
data/ext/oj/object.c
CHANGED
@@ -67,9 +67,9 @@ static VALUE str_to_value(ParseInfo pi, const char *str, size_t len, const char
|
|
67
67
|
|
68
68
|
// The much faster approach (4x faster)
|
69
69
|
static int parse_num(const char *str, const char *end, int cnt) {
|
70
|
-
int
|
70
|
+
int n = 0;
|
71
71
|
char c;
|
72
|
-
int
|
72
|
+
int i;
|
73
73
|
|
74
74
|
for (i = cnt; 0 < i; i--, str++) {
|
75
75
|
c = *str;
|
@@ -83,9 +83,9 @@ static int parse_num(const char *str, const char *end, int cnt) {
|
|
83
83
|
|
84
84
|
VALUE
|
85
85
|
oj_parse_xml_time(const char *str, int len) {
|
86
|
-
VALUE
|
86
|
+
VALUE args[8];
|
87
87
|
const char *end = str + len;
|
88
|
-
int
|
88
|
+
int n;
|
89
89
|
|
90
90
|
// year
|
91
91
|
if (0 > (n = parse_num(str, end, 4))) {
|
@@ -269,19 +269,10 @@ static int hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
|
|
269
269
|
// match the expected value.
|
270
270
|
parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
|
271
271
|
} else if (ni->has_exp) {
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
sec_as_time(t, &ti);
|
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);
|
284
|
-
parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
|
272
|
+
struct timespec ts;
|
273
|
+
ts.tv_sec = ni->i;
|
274
|
+
ts.tv_nsec = nsec;
|
275
|
+
parent->val = rb_time_timespec_new(&ts, (int)ni->exp);
|
285
276
|
} else {
|
286
277
|
parent->val = rb_time_nano_new(ni->i, (long)nsec);
|
287
278
|
}
|
@@ -317,7 +308,7 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
|
|
317
308
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
|
318
309
|
return 1;
|
319
310
|
}
|
320
|
-
e1 = *
|
311
|
+
e1 = *RARRAY_CONST_PTR(value);
|
321
312
|
// check for anonymous Struct
|
322
313
|
if (T_ARRAY == rb_type(e1)) {
|
323
314
|
VALUE args[1024];
|
@@ -331,40 +322,44 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
|
|
331
322
|
sc = rb_funcall2(rb_cStruct, oj_new_id, cnt, args);
|
332
323
|
} else {
|
333
324
|
// If struct is not defined then we let this fail and raise an exception.
|
334
|
-
sc = oj_name2struct(pi, *
|
325
|
+
sc = oj_name2struct(pi, *RARRAY_CONST_PTR(value), rb_eArgError);
|
335
326
|
}
|
336
|
-
|
337
|
-
|
338
|
-
|
327
|
+
if (sc == rb_cRange) {
|
328
|
+
parent->val = rb_class_new_instance(len - 1, RARRAY_CONST_PTR(value) + 1, rb_cRange);
|
329
|
+
} else {
|
330
|
+
// Create a properly initialized struct instance without calling the initialize method.
|
331
|
+
parent->val = rb_obj_alloc(sc);
|
332
|
+
// If the JSON array has more entries than the struct class allows, we record an error.
|
339
333
|
#ifdef RSTRUCT_LEN
|
340
334
|
#if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
341
|
-
|
335
|
+
slen = (int)NUM2LONG(RSTRUCT_LEN(parent->val));
|
342
336
|
#else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
343
|
-
|
337
|
+
slen = (int)RSTRUCT_LEN(parent->val);
|
344
338
|
#endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
345
339
|
#else
|
346
|
-
|
340
|
+
slen = FIX2INT(rb_funcall2(parent->val, oj_length_id, 0, 0));
|
347
341
|
#endif
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
342
|
+
// MRI >= 1.9
|
343
|
+
if (len - 1 > slen) {
|
344
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
|
345
|
+
} else {
|
346
|
+
int i;
|
353
347
|
|
354
|
-
|
355
|
-
|
348
|
+
for (i = 0; i < len - 1; i++) {
|
349
|
+
rb_struct_aset(parent->val, INT2FIX(i), RARRAY_CONST_PTR(value)[i + 1]);
|
350
|
+
}
|
356
351
|
}
|
357
352
|
}
|
358
353
|
return 1;
|
359
354
|
} else if (3 <= klen && '#' == key[1]) {
|
360
|
-
volatile VALUE *a;
|
355
|
+
volatile const VALUE *a;
|
361
356
|
|
362
357
|
if (2 != len) {
|
363
358
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
|
364
359
|
return 1;
|
365
360
|
}
|
366
361
|
parent->val = rb_hash_new();
|
367
|
-
a =
|
362
|
+
a = RARRAY_CONST_PTR(value);
|
368
363
|
rb_hash_aset(parent->val, *a, a[1]);
|
369
364
|
|
370
365
|
return 1;
|
@@ -374,11 +369,17 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
|
|
374
369
|
}
|
375
370
|
|
376
371
|
void oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
|
377
|
-
|
372
|
+
if (kval->klen == 5 && strncmp("~mesg", kval->key, 5) == 0 && rb_obj_is_kind_of(parent->val, rb_eException)) {
|
373
|
+
parent->val = rb_funcall(parent->val, rb_intern("exception"), 1, value);
|
374
|
+
} else if (kval->klen == 3 && strncmp("~bt", kval->key, 3) == 0 && rb_obj_is_kind_of(parent->val, rb_eException)) {
|
375
|
+
rb_funcall(parent->val, rb_intern("set_backtrace"), 1, value);
|
376
|
+
} else {
|
377
|
+
rb_ivar_set(parent->val, oj_attr_intern(kval->key, kval->klen), value);
|
378
|
+
}
|
378
379
|
}
|
379
380
|
|
380
381
|
static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
|
381
|
-
const char
|
382
|
+
const char *key = kval->key;
|
382
383
|
int klen = kval->klen;
|
383
384
|
Val parent = stack_peek(&pi->stack);
|
384
385
|
volatile VALUE rval = Qnil;
|
@@ -445,13 +446,11 @@ WHICH_TYPE:
|
|
445
446
|
rb_class2name(rb_obj_class(parent->val)));
|
446
447
|
return;
|
447
448
|
}
|
448
|
-
|
449
|
-
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
|
450
|
-
}
|
449
|
+
TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rval);
|
451
450
|
}
|
452
451
|
|
453
452
|
static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
454
|
-
const char
|
453
|
+
const char *key = kval->key;
|
455
454
|
int klen = kval->klen;
|
456
455
|
Val parent = stack_peek(&pi->stack);
|
457
456
|
volatile VALUE rval = Qnil;
|
@@ -516,9 +515,7 @@ WHICH_TYPE:
|
|
516
515
|
rb_class2name(rb_obj_class(parent->val)));
|
517
516
|
return;
|
518
517
|
}
|
519
|
-
|
520
|
-
oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, rval);
|
521
|
-
}
|
518
|
+
TRACE_PARSE_CALL(pi->options.trace, "add_number", pi, rval);
|
522
519
|
}
|
523
520
|
|
524
521
|
static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
@@ -544,8 +541,8 @@ WHICH_TYPE:
|
|
544
541
|
}
|
545
542
|
} else {
|
546
543
|
if (3 <= klen && '^' == *key && '#' == key[1] && T_ARRAY == rb_type(value)) {
|
547
|
-
long
|
548
|
-
volatile VALUE *a =
|
544
|
+
long len = RARRAY_LEN(value);
|
545
|
+
volatile const VALUE *a = RARRAY_CONST_PTR(value);
|
549
546
|
|
550
547
|
if (2 != len) {
|
551
548
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
|
@@ -602,15 +599,11 @@ WHICH_TYPE:
|
|
602
599
|
rb_class2name(rb_obj_class(parent->val)));
|
603
600
|
return;
|
604
601
|
}
|
605
|
-
|
606
|
-
oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, value);
|
607
|
-
}
|
602
|
+
TRACE_PARSE_CALL(pi->options.trace, "add_value", pi, value);
|
608
603
|
}
|
609
604
|
|
610
605
|
static VALUE start_hash(ParseInfo pi) {
|
611
|
-
|
612
|
-
oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
|
613
|
-
}
|
606
|
+
TRACE_PARSE_IN(pi->options.trace, "start_hash", pi);
|
614
607
|
return Qnil;
|
615
608
|
}
|
616
609
|
|
@@ -626,9 +619,7 @@ static void end_hash(ParseInfo pi) {
|
|
626
619
|
oj_odd_free(oa);
|
627
620
|
parent->odd_args = NULL;
|
628
621
|
}
|
629
|
-
|
630
|
-
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
631
|
-
}
|
622
|
+
TRACE_PARSE_HASH_END(pi->options.trace, pi);
|
632
623
|
}
|
633
624
|
|
634
625
|
static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
@@ -654,32 +645,24 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
|
|
654
645
|
}
|
655
646
|
rval = str_to_value(pi, str, len, orig);
|
656
647
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
657
|
-
|
658
|
-
oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rval);
|
659
|
-
}
|
648
|
+
TRACE_PARSE_CALL(pi->options.trace, "append_string", pi, rval);
|
660
649
|
}
|
661
650
|
|
662
651
|
static void array_append_num(ParseInfo pi, NumInfo ni) {
|
663
652
|
volatile VALUE rval = oj_num_as_value(ni);
|
664
653
|
|
665
654
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
666
|
-
|
667
|
-
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
668
|
-
}
|
655
|
+
TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, rval);
|
669
656
|
}
|
670
657
|
|
671
658
|
static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
672
659
|
pi->stack.head->val = str_to_value(pi, str, len, orig);
|
673
|
-
|
674
|
-
oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
|
675
|
-
}
|
660
|
+
TRACE_PARSE_CALL(pi->options.trace, "add_string", pi, pi->stack.head->val);
|
676
661
|
}
|
677
662
|
|
678
663
|
static void add_num(ParseInfo pi, NumInfo ni) {
|
679
664
|
pi->stack.head->val = oj_num_as_value(ni);
|
680
|
-
|
681
|
-
oj_trace_parse_call("add_num", pi, __FILE__, __LINE__, pi->stack.head->val);
|
682
|
-
}
|
665
|
+
TRACE_PARSE_CALL(pi->options.trace, "add_num", pi, pi->stack.head->val);
|
683
666
|
}
|
684
667
|
|
685
668
|
void oj_set_object_callbacks(ParseInfo pi) {
|
data/ext/oj/odd.c
CHANGED
@@ -5,28 +5,29 @@
|
|
5
5
|
|
6
6
|
#include <string.h>
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
static
|
11
|
-
static ID
|
12
|
-
static ID
|
13
|
-
static ID
|
14
|
-
static ID
|
15
|
-
static ID
|
16
|
-
static ID
|
17
|
-
static VALUE rational_class;
|
8
|
+
#include "mem.h"
|
9
|
+
|
10
|
+
static Odd odds = NULL;
|
11
|
+
static ID sec_id;
|
12
|
+
static ID sec_fraction_id;
|
13
|
+
static ID to_f_id;
|
14
|
+
static ID numerator_id;
|
15
|
+
static ID denominator_id;
|
16
|
+
static ID rational_id;
|
18
17
|
|
19
18
|
static void set_class(Odd odd, const char *classname) {
|
20
19
|
const char **np;
|
21
|
-
ID
|
20
|
+
ID *idp;
|
22
21
|
|
23
|
-
odd->classname
|
24
|
-
odd->clen
|
25
|
-
odd->clas
|
22
|
+
odd->classname = classname;
|
23
|
+
odd->clen = strlen(classname);
|
24
|
+
odd->clas = rb_const_get(rb_cObject, rb_intern(classname));
|
25
|
+
rb_gc_register_mark_object(odd->clas);
|
26
26
|
odd->create_obj = odd->clas;
|
27
|
-
odd->
|
28
|
-
odd->
|
29
|
-
odd->
|
27
|
+
rb_gc_register_mark_object(odd->create_obj);
|
28
|
+
odd->create_op = rb_intern("new");
|
29
|
+
odd->is_module = (T_MODULE == rb_type(odd->clas));
|
30
|
+
odd->raw = 0;
|
30
31
|
for (np = odd->attr_names, idp = odd->attrs; 0 != *np; np++, idp++) {
|
31
32
|
*idp = rb_intern(*np);
|
32
33
|
}
|
@@ -37,15 +38,48 @@ static VALUE get_datetime_secs(VALUE obj) {
|
|
37
38
|
volatile VALUE rsecs = rb_funcall(obj, sec_id, 0);
|
38
39
|
volatile VALUE rfrac = rb_funcall(obj, sec_fraction_id, 0);
|
39
40
|
long sec = NUM2LONG(rsecs);
|
40
|
-
long long num =
|
41
|
-
long long den =
|
41
|
+
long long num = NUM2LL(rb_funcall(rfrac, numerator_id, 0));
|
42
|
+
long long den = NUM2LL(rb_funcall(rfrac, denominator_id, 0));
|
42
43
|
|
43
44
|
num += sec * den;
|
44
45
|
|
45
46
|
return rb_funcall(rb_cObject, rational_id, 2, rb_ll2inum(num), rb_ll2inum(den));
|
46
47
|
}
|
47
48
|
|
48
|
-
void
|
49
|
+
static void print_odd(Odd odd) {
|
50
|
+
const char **np;
|
51
|
+
int i;
|
52
|
+
|
53
|
+
printf(" %s {\n", odd->classname);
|
54
|
+
printf(" attr_cnt: %d %p\n", odd->attr_cnt, (void *)odd->attr_names);
|
55
|
+
printf(" attr_names: %p\n", (void *)*odd->attr_names);
|
56
|
+
printf(" attr_names: %c\n", **odd->attr_names);
|
57
|
+
for (i = odd->attr_cnt, np = odd->attr_names; 0 < i; i--, np++) {
|
58
|
+
printf(" %d %s\n", i, *np);
|
59
|
+
}
|
60
|
+
printf(" }\n");
|
61
|
+
}
|
62
|
+
|
63
|
+
void print_all_odds(const char *label) {
|
64
|
+
Odd odd;
|
65
|
+
printf("@ %s {\n", label);
|
66
|
+
for (odd = odds; NULL != odd; odd = odd->next) {
|
67
|
+
print_odd(odd);
|
68
|
+
}
|
69
|
+
printf("}\n");
|
70
|
+
}
|
71
|
+
|
72
|
+
static Odd odd_create(void) {
|
73
|
+
Odd odd = OJ_R_ALLOC(struct _odd);
|
74
|
+
|
75
|
+
memset(odd, 0, sizeof(struct _odd));
|
76
|
+
odd->next = odds;
|
77
|
+
odds = odd;
|
78
|
+
|
79
|
+
return odd;
|
80
|
+
}
|
81
|
+
|
82
|
+
void oj_odd_init(void) {
|
49
83
|
Odd odd;
|
50
84
|
const char **np;
|
51
85
|
|
@@ -55,11 +89,9 @@ void oj_odd_init() {
|
|
55
89
|
numerator_id = rb_intern("numerator");
|
56
90
|
denominator_id = rb_intern("denominator");
|
57
91
|
rational_id = rb_intern("Rational");
|
58
|
-
rational_class = rb_const_get(rb_cObject, rational_id);
|
59
92
|
|
60
|
-
memset(_odds, 0, sizeof(_odds));
|
61
|
-
odd = odds;
|
62
93
|
// Rational
|
94
|
+
odd = odd_create();
|
63
95
|
np = odd->attr_names;
|
64
96
|
*np++ = "numerator";
|
65
97
|
*np++ = "denominator";
|
@@ -68,8 +100,9 @@ void oj_odd_init() {
|
|
68
100
|
odd->create_obj = rb_cObject;
|
69
101
|
odd->create_op = rational_id;
|
70
102
|
odd->attr_cnt = 2;
|
103
|
+
|
71
104
|
// Date
|
72
|
-
odd
|
105
|
+
odd = odd_create();
|
73
106
|
np = odd->attr_names;
|
74
107
|
*np++ = "year";
|
75
108
|
*np++ = "month";
|
@@ -78,8 +111,9 @@ void oj_odd_init() {
|
|
78
111
|
*np++ = 0;
|
79
112
|
set_class(odd, "Date");
|
80
113
|
odd->attr_cnt = 4;
|
114
|
+
|
81
115
|
// DateTime
|
82
|
-
odd
|
116
|
+
odd = odd_create();
|
83
117
|
np = odd->attr_names;
|
84
118
|
*np++ = "year";
|
85
119
|
*np++ = "month";
|
@@ -93,8 +127,9 @@ void oj_odd_init() {
|
|
93
127
|
set_class(odd, "DateTime");
|
94
128
|
odd->attr_cnt = 8;
|
95
129
|
odd->attrFuncs[5] = get_datetime_secs;
|
130
|
+
|
96
131
|
// Range
|
97
|
-
odd
|
132
|
+
odd = odd_create();
|
98
133
|
np = odd->attr_names;
|
99
134
|
*np++ = "begin";
|
100
135
|
*np++ = "end";
|
@@ -102,15 +137,13 @@ void oj_odd_init() {
|
|
102
137
|
*np++ = 0;
|
103
138
|
set_class(odd, "Range");
|
104
139
|
odd->attr_cnt = 3;
|
105
|
-
|
106
|
-
odd_cnt = odd - odds + 1;
|
107
140
|
}
|
108
141
|
|
109
142
|
Odd oj_get_odd(VALUE clas) {
|
110
143
|
Odd odd;
|
111
144
|
const char *classname = NULL;
|
112
145
|
|
113
|
-
for (odd = odds
|
146
|
+
for (odd = odds; NULL != odd; odd = odd->next) {
|
114
147
|
if (clas == odd->clas) {
|
115
148
|
return odd;
|
116
149
|
}
|
@@ -129,21 +162,20 @@ Odd oj_get_odd(VALUE clas) {
|
|
129
162
|
Odd oj_get_oddc(const char *classname, size_t len) {
|
130
163
|
Odd odd;
|
131
164
|
|
132
|
-
for (odd = odds
|
165
|
+
for (odd = odds; NULL != odd; odd = odd->next) {
|
133
166
|
if (len == odd->clen && 0 == strncmp(classname, odd->classname, len)) {
|
134
167
|
return odd;
|
135
168
|
}
|
136
|
-
if (odd->is_module && 0 == strncmp(odd->classname, classname, odd->clen) &&
|
137
|
-
':' == classname[odd->clen]) {
|
169
|
+
if (odd->is_module && 0 == strncmp(odd->classname, classname, odd->clen) && ':' == classname[odd->clen]) {
|
138
170
|
return odd;
|
139
171
|
}
|
140
172
|
}
|
141
|
-
return
|
173
|
+
return NULL;
|
142
174
|
}
|
143
175
|
|
144
176
|
OddArgs oj_odd_alloc_args(Odd odd) {
|
145
|
-
OddArgs oa =
|
146
|
-
VALUE
|
177
|
+
OddArgs oa = OJ_R_ALLOC_N(struct _oddArgs, 1);
|
178
|
+
VALUE *a;
|
147
179
|
int i;
|
148
180
|
|
149
181
|
oa->odd = odd;
|
@@ -154,16 +186,15 @@ OddArgs oj_odd_alloc_args(Odd odd) {
|
|
154
186
|
}
|
155
187
|
|
156
188
|
void oj_odd_free(OddArgs args) {
|
157
|
-
|
189
|
+
OJ_R_FREE(args);
|
158
190
|
}
|
159
191
|
|
160
192
|
int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
|
161
193
|
const char **np;
|
162
|
-
VALUE
|
194
|
+
VALUE *vp;
|
163
195
|
int i;
|
164
196
|
|
165
|
-
for (i = args->odd->attr_cnt, np = args->odd->attr_names, vp = args->args; 0 < i;
|
166
|
-
i--, np++, vp++) {
|
197
|
+
for (i = args->odd->attr_cnt, np = args->odd->attr_names, vp = args->args; 0 < i; i--, np++, vp++) {
|
167
198
|
if (0 == strncmp(key, *np, klen) && '\0' == *((*np) + klen)) {
|
168
199
|
*vp = value;
|
169
200
|
return 0;
|
@@ -172,52 +203,43 @@ int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
|
|
172
203
|
return -1;
|
173
204
|
}
|
174
205
|
|
175
|
-
void oj_reg_odd(VALUE
|
176
|
-
VALUE create_object,
|
177
|
-
VALUE create_method,
|
178
|
-
int mcnt,
|
179
|
-
VALUE *members,
|
180
|
-
bool raw) {
|
206
|
+
void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw) {
|
181
207
|
Odd odd;
|
182
208
|
const char **np;
|
183
|
-
ID
|
209
|
+
ID *ap;
|
184
210
|
AttrGetFunc *fp;
|
185
211
|
|
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;
|
212
|
+
odd = odd_create();
|
194
213
|
odd->clas = clas;
|
195
|
-
|
196
|
-
|
214
|
+
rb_gc_register_mark_object(odd->clas);
|
215
|
+
if (NULL == (odd->classname = OJ_STRDUP(rb_class2name(clas)))) {
|
216
|
+
rb_raise(rb_eNoMemError, "for class name.");
|
197
217
|
}
|
198
218
|
odd->clen = strlen(odd->classname);
|
199
219
|
odd->create_obj = create_object;
|
200
|
-
odd->
|
201
|
-
odd->
|
202
|
-
odd->
|
203
|
-
odd->
|
204
|
-
|
205
|
-
|
220
|
+
rb_gc_register_mark_object(odd->create_obj);
|
221
|
+
odd->create_op = SYM2ID(create_method);
|
222
|
+
odd->attr_cnt = mcnt;
|
223
|
+
odd->is_module = (T_MODULE == rb_type(clas));
|
224
|
+
odd->raw = raw;
|
225
|
+
for (ap = odd->attrs, np = odd->attr_names, fp = odd->attrFuncs; 0 < mcnt; mcnt--, ap++, np++, members++, fp++) {
|
206
226
|
*fp = 0;
|
207
227
|
switch (rb_type(*members)) {
|
208
228
|
case T_STRING:
|
209
|
-
if (NULL == (*np =
|
229
|
+
if (NULL == (*np = OJ_STRDUP(RSTRING_PTR(*members)))) {
|
210
230
|
rb_raise(rb_eNoMemError, "for attribute name.");
|
211
231
|
}
|
212
232
|
break;
|
213
|
-
case T_SYMBOL:
|
214
|
-
|
215
|
-
|
233
|
+
case T_SYMBOL:
|
234
|
+
// The symbol can move and invalidate the name so make a copy.
|
235
|
+
if (NULL == (*np = OJ_STRDUP(rb_id2name(SYM2ID(*members))))) {
|
236
|
+
rb_raise(rb_eNoMemError, "for attribute name.");
|
237
|
+
}
|
216
238
|
break;
|
239
|
+
default: rb_raise(rb_eArgError, "registered member identifiers must be Strings or Symbols."); break;
|
217
240
|
}
|
218
241
|
*ap = rb_intern(*np);
|
219
242
|
}
|
220
243
|
*np = 0;
|
221
244
|
*ap = 0;
|
222
|
-
odd_cnt++;
|
223
245
|
}
|
data/ext/oj/odd.h
CHANGED
@@ -13,23 +13,24 @@
|
|
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
|
-
|
27
|
-
|
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];
|
28
|
+
} *Odd;
|
28
29
|
|
29
30
|
typedef struct _oddArgs {
|
30
31
|
Odd odd;
|
31
32
|
VALUE args[MAX_ODD_ARGS];
|
32
|
-
} *
|
33
|
+
} *OddArgs;
|
33
34
|
|
34
35
|
extern void oj_odd_init(void);
|
35
36
|
extern Odd oj_get_odd(VALUE clas);
|
@@ -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 */
|