6
$Date: 2007-08-30 08:12:21 +0900 (木, 30 8月 2007) $
6
$Date: 2007-11-22 10:17:52 +0900 (Thu, 22 Nov 2007) $
7
7
created at: Thu Apr 27 16:30:01 JST 1995
9
9
Copyright (C) 1993-2007 Yukihiro Matsumoto
82
83
static ID s_dump_data, s_load_data, s_alloc;
83
84
static ID s_getc, s_read, s_write, s_binmode;
86
ID rb_id_encoding(void);
91
VALUE (*dumper)(VALUE);
92
VALUE (*loader)(VALUE, VALUE);
95
static st_table *compat_allocator_tbl;
96
static VALUE compat_allocator_tbl_wrapper;
99
mark_marshal_compat_i(st_data_t key, st_data_t value)
101
marshal_compat_t *p = (marshal_compat_t *)value;
102
rb_gc_mark(p->newclass);
103
rb_gc_mark(p->oldclass);
108
mark_marshal_compat_t(void *tbl)
111
st_foreach(tbl, mark_marshal_compat_i, 0);
115
rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE))
117
marshal_compat_t *compat;
118
rb_alloc_func_t allocator = rb_get_alloc_func(newclass);
121
rb_raise(rb_eTypeError, "no allocator");
124
compat = ALLOC(marshal_compat_t);
125
compat->newclass = Qnil;
126
compat->oldclass = Qnil;
127
compat->newclass = newclass;
128
compat->oldclass = oldclass;
129
compat->dumper = dumper;
130
compat->loader = loader;
132
st_insert(compat_allocator_tbl, (st_data_t)allocator, (st_data_t)compat);
88
138
st_table *symbols;
141
st_table *compat_tbl;
93
146
struct dump_call_arg {
295
358
/* xxx: should not use system's sprintf(3) */
296
sprintf(buf, "%.*g", FLOAT_DIG, d);
359
snprintf(buf, sizeof(buf), "%.*g", FLOAT_DIG, d);
297
360
len = strlen(buf);
298
361
w_bytes(buf, len + save_mantissa(d, buf + len), arg);
315
378
sym = rb_id2name(id);
380
rb_raise(rb_eTypeError, "can't dump anonymous ID %ld", id);
316
382
w_byte(TYPE_SYMBOL, arg);
317
383
w_bytes(sym, strlen(sym), arg);
318
384
st_add_direct(arg->symbols, id, arg->symbols->num_entries);
346
412
if (check && FL_TEST(klass, FL_SINGLETON)) {
347
if (RCLASS(klass)->m_tbl->num_entries ||
348
(RCLASS(klass)->iv_tbl && RCLASS(klass)->iv_tbl->num_entries > 1)) {
413
if (RCLASS_M_TBL(klass)->num_entries ||
414
(RCLASS_IV_TBL(klass) && RCLASS_IV_TBL(klass)->num_entries > 1)) {
349
415
rb_raise(rb_eTypeError, "singleton can't be dumped");
351
klass = RCLASS(klass)->super;
417
klass = RCLASS_SUPER(klass);
353
419
while (BUILTIN_TYPE(klass) == T_ICLASS) {
354
420
path = rb_class2name(RBASIC(klass)->klass);
355
421
w_byte(TYPE_EXTENDED, arg);
356
422
w_unique(path, arg);
357
klass = RCLASS(klass)->super;
423
klass = RCLASS_SUPER(klass);
364
430
volatile VALUE p;
367
VALUE klass = CLASS_OF(obj);
435
if (st_lookup(arg->compat_tbl, (st_data_t)obj, &real_obj)) {
436
obj = (VALUE)real_obj;
438
klass = CLASS_OF(obj);
368
439
w_extended(klass, arg, check);
369
440
w_byte(type, arg);
370
441
p = class2path(rb_class_real(klass));
376
w_uclass(VALUE obj, VALUE base_klass, struct dump_arg *arg)
447
w_uclass(VALUE obj, VALUE super, struct dump_arg *arg)
378
449
VALUE klass = CLASS_OF(obj);
380
451
w_extended(klass, arg, Qtrue);
381
452
klass = rb_class_real(klass);
382
if (klass != base_klass) {
453
if (klass != super) {
383
454
w_byte(TYPE_UCLASS, arg);
384
455
w_unique(RSTRING_PTR(class2path(klass)), arg);
389
460
w_obj_each(ID id, VALUE value, struct dump_call_arg *arg)
462
if (id == rb_id_encoding()) return ST_CONTINUE;
391
463
w_symbol(id, arg->arg);
392
464
w_object(value, arg->arg, arg->limit);
393
465
return ST_CONTINUE;
397
w_ivar(st_table *tbl, struct dump_call_arg *arg)
469
w_encoding(VALUE obj, long num, struct dump_call_arg *arg)
471
int encidx = rb_enc_get_index(obj);
472
rb_encoding *enc = 0;
475
if (encidx <= 0 || !(enc = rb_enc_from_index(encidx))) {
476
w_long(num, arg->arg);
479
w_long(num + 1, arg->arg);
480
w_symbol(rb_id_encoding(), arg->arg);
482
if (!arg->arg->encodings)
483
arg->arg->encodings = st_init_strcasetable();
484
else if (st_lookup(arg->arg->encodings, (st_data_t)rb_enc_name(enc), &name))
486
name = (st_data_t)rb_str_new2(rb_enc_name(enc));
487
st_insert(arg->arg->encodings, (st_data_t)rb_enc_name(enc), name);
489
w_object(name, arg->arg, arg->limit);
493
w_ivar(VALUE obj, st_table *tbl, struct dump_call_arg *arg)
495
long num = tbl ? tbl->num_entries : 0;
497
w_encoding(obj, num, arg);
400
w_long(tbl->num_entries, arg->arg);
401
499
st_foreach_safe(tbl, w_obj_each, (st_data_t)arg);
504
w_objivar(VALUE obj, struct dump_call_arg *arg)
509
len = ROBJECT_LEN(obj);
510
ptr = ROBJECT_PTR(obj);
512
for (i = 0; i < len; i++)
513
if (ptr[i] != Qundef)
516
w_encoding(obj, num, arg);
518
rb_ivar_foreach(obj, w_obj_each, (st_data_t)arg);
411
525
struct dump_call_arg c_arg;
412
526
st_table *ivtbl = 0;
529
#define has_ivars(obj, ivtbl) ((ivtbl = rb_generic_ivar_table(obj)) != 0 || \
530
(!SPECIAL_CONST_P(obj) && ENCODING_GET(obj)))
415
532
if (limit == 0) {
416
533
rb_raise(rb_eArgError, "exceed depth limit");
459
576
if (OBJ_TAINTED(obj)) arg->taint = Qtrue;
461
578
st_add_direct(arg->data, obj, arg->data->num_entries);
581
st_data_t compat_data;
582
rb_alloc_func_t allocator = rb_get_alloc_func(RBASIC(obj)->klass);
583
if (st_lookup(compat_allocator_tbl,
584
(st_data_t)allocator,
586
marshal_compat_t *compat = (marshal_compat_t*)compat_data;
587
VALUE real_obj = obj;
588
obj = compat->dumper(real_obj);
589
st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj);
462
593
if (rb_respond_to(obj, s_mdump)) {
465
596
v = rb_funcall(obj, s_mdump, 0, 0);
466
597
w_class(TYPE_USRMARSHAL, obj, arg, Qfalse);
467
598
w_object(v, arg, limit);
468
if (ivtbl) w_ivar(0, &c_arg);
599
if (hasiv) w_ivar(obj, 0, &c_arg);
471
602
if (rb_respond_to(obj, s_dump)) {
604
st_table *ivtbl2 = 0;
474
607
v = rb_funcall(obj, s_dump, 1, INT2NUM(limit));
475
608
if (TYPE(v) != T_STRING) {
476
609
rb_raise(rb_eTypeError, "_dump() must return string");
478
if (!ivtbl && (ivtbl = rb_generic_ivar_table(v))) {
611
if ((hasiv2 = has_ivars(v, ivtbl2)) != 0 && !hasiv) {
479
612
w_byte(TYPE_IVAR, arg);
481
614
w_class(TYPE_USERDEF, obj, arg, Qfalse);
482
615
w_bytes(RSTRING_PTR(v), RSTRING_LEN(v), arg);
484
w_ivar(ivtbl, &c_arg);
617
w_ivar(obj, ivtbl2, &c_arg);
620
w_ivar(obj, ivtbl, &c_arg);
510
646
w_byte(TYPE_FLOAT, arg);
511
w_float(RFLOAT(obj)->value, arg);
647
w_float(RFLOAT_VALUE(obj), arg);
515
651
w_byte(TYPE_BIGNUM, arg);
517
char sign = RBIGNUM(obj)->sign ? '+' : '-';
518
long len = RBIGNUM(obj)->len;
519
BDIGIT *d = RBIGNUM(obj)->digits;
653
char sign = RBIGNUM_SIGN(obj) ? '+' : '-';
654
long len = RBIGNUM_LEN(obj);
655
BDIGIT *d = RBIGNUM_DIGITS(obj);
521
657
w_byte(sign, arg);
522
658
w_long(SHORTLEN(len), arg); /* w_short? */
720
859
arg.symbols = st_init_numtable();
721
860
arg.data = st_init_numtable();
722
861
arg.taint = Qfalse;
862
arg.compat_tbl = st_init_numtable();
863
arg.wrapper = Data_Wrap_Struct(rb_cData, mark_dump_arg, 0, &arg);
724
866
c_arg.arg = &arg;
725
867
c_arg.limit = limit;
825
969
if (len == 0) return rb_str_new(0, 0);
826
970
if (TYPE(arg->src) == T_STRING) {
827
if (RSTRING_LEN(arg->src) > arg->offset) {
971
if (RSTRING_LEN(arg->src) - arg->offset >= len) {
828
972
str = rb_str_new(RSTRING_PTR(arg->src)+arg->offset, len);
829
973
arg->offset += len;
900
1044
r_entry(VALUE v, struct load_arg *arg)
902
rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), v);
903
if (arg->taint) OBJ_TAINT(v);
1046
st_data_t real_obj = (VALUE)Qundef;
1047
if (st_lookup(arg->compat_tbl, v, &real_obj)) {
1048
rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), (VALUE)real_obj);
1051
rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), v);
1055
if ((VALUE)real_obj != Qundef)
1056
OBJ_TAINT((VALUE)real_obj);
1062
r_leave(VALUE v, struct load_arg *arg)
1065
if (st_lookup(arg->compat_tbl, v, &data)) {
1066
VALUE real_obj = (VALUE)data;
1067
rb_alloc_func_t allocator = rb_get_alloc_func(CLASS_OF(real_obj));
1069
if (st_lookup(compat_allocator_tbl, (st_data_t)allocator, &data)) {
1070
marshal_compat_t *compat = (marshal_compat_t*)data;
1071
compat->loader(real_obj, v);
1073
st_delete(arg->compat_tbl, &key, 0);
904
1076
if (arg->proc) {
905
1077
v = rb_funcall(arg->proc, rb_intern("call"), 1, v);
918
1090
ID id = r_symbol(arg);
919
1091
VALUE val = r_object(arg);
920
rb_ivar_set(obj, id, val);
1092
if (id == rb_id_encoding()) {
1093
int idx = rb_enc_find_index(StringValueCStr(val));
1094
if (idx > 0) rb_enc_associate_index(obj, idx);
1097
rb_ivar_set(obj, id, val);
1126
obj_alloc_by_path(const char *path, struct load_arg *arg)
1130
rb_alloc_func_t allocator;
1132
klass = path2class(path);
1134
allocator = rb_get_alloc_func(klass);
1135
if (st_lookup(compat_allocator_tbl, (st_data_t)allocator, &data)) {
1136
marshal_compat_t *compat = (marshal_compat_t*)data;
1137
VALUE real_obj = rb_obj_alloc(klass);
1138
VALUE obj = rb_obj_alloc(compat->oldclass);
1139
st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj);
1143
return rb_obj_alloc(klass);
948
1147
r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
1061
1261
NEWOBJ(big, struct RBignum);
1062
1262
OBJSETUP(big, rb_cBignum, T_BIGNUM);
1063
big->sign = (r_byte(arg) == '+');
1263
RBIGNUM_SET_SIGN(big, (r_byte(arg) == '+'));
1064
1264
len = r_long(arg);
1065
1265
data = r_bytes0(len * 2, arg);
1066
1266
#if SIZEOF_BDIGITS == SIZEOF_SHORT
1267
rb_big_resize((VALUE)big, len);
1069
big->len = (len + 1) * 2 / sizeof(BDIGIT);
1269
rb_big_resize((VALUE)big, (len + 1) * 2 / sizeof(BDIGIT));
1071
big->digits = digits = ALLOC_N(BDIGIT, big->len);
1271
digits = RBIGNUM_DIGITS(big);
1072
1272
MEMCPY(digits, RSTRING_PTR(data), char, len * 2);
1073
1273
#if SIZEOF_BDIGITS > SIZEOF_SHORT
1074
1274
MEMZERO((char *)digits + len * 2, char,
1075
big->len * sizeof(BDIGIT) - len * 2);
1275
RBIGNUM_LEN(big) * sizeof(BDIGIT) - len * 2);
1277
len = RBIGNUM_LEN(big);
1078
1278
while (len > 0) {
1079
1279
unsigned char *p = (unsigned char *)digits;
1080
1280
BDIGIT num = 0;
1136
1340
if (type == TYPE_HASH_DEF) {
1137
1341
RHASH(v)->ifnone = r_object(arg);
1343
v = r_leave(v, arg);
1142
1347
case TYPE_STRUCT:
1144
VALUE klass, mem, values;
1145
1351
volatile long i; /* gcc 2.7.2.3 -O2 bug?? */
1149
1355
klass = path2class(r_unique(arg));
1358
v = rb_obj_alloc(klass);
1359
if (TYPE(v) != T_STRUCT) {
1360
rb_raise(rb_eTypeError, "class %s not a struct", rb_class2name(klass));
1150
1362
mem = rb_struct_s_members(klass);
1152
rb_raise(rb_eTypeError, "uninitialized struct");
1363
if (RARRAY_LEN(mem) != len) {
1364
rb_raise(rb_eTypeError, "struct %s not compatible (struct size differs)",
1365
rb_class2name(klass));
1368
v = r_entry(v, arg);
1156
1369
values = rb_ary_new2(len);
1157
1370
for (i=0; i<len; i++) {
1158
rb_ary_push(values, Qnil);
1160
v = rb_struct_alloc(klass, values);
1161
v = r_entry(v, arg);
1162
for (i=0; i<len; i++) {
1163
1371
slot = r_symbol(arg);
1165
1373
if (RARRAY_PTR(mem)[i] != ID2SYM(slot)) {
1168
1376
rb_id2name(slot),
1169
1377
rb_id2name(SYM2ID(RARRAY_PTR(mem)[i])));
1171
rb_struct_aset(v, LONG2FIX(i), r_object(arg));
1379
rb_ary_push(values, r_object(arg));
1381
rb_struct_initialize(v, values);
1382
v = r_leave(v, arg);
1211
1422
v = r_entry(v, arg);
1212
1423
data = r_object(arg);
1213
1424
rb_funcall(v, s_mload, 1, data);
1425
v = r_leave(v, arg);
1217
1429
case TYPE_OBJECT:
1219
VALUE klass = path2class(r_unique(arg));
1221
v = rb_obj_alloc(klass);
1431
v = obj_alloc_by_path(r_unique(arg), arg);
1222
1432
if (TYPE(v) != T_OBJECT) {
1223
1433
rb_raise(rb_eArgError, "dump format error");
1225
1435
v = r_entry(v, arg);
1226
1436
r_ivar(v, arg);
1437
v = r_leave(v, arg);
1312
1527
load_ensure(struct load_arg *arg)
1314
1529
st_free_table(arg->symbols);
1530
st_free_table(arg->compat_tbl);
1531
DATA_PTR(arg->compat_tbl_wrapper) = 0;
1532
arg->compat_tbl_wrapper = 0;
1430
1650
rb_define_const(rb_mMarshal, "MAJOR_VERSION", INT2FIX(MARSHAL_MAJOR));
1431
1651
rb_define_const(rb_mMarshal, "MINOR_VERSION", INT2FIX(MARSHAL_MINOR));
1653
compat_allocator_tbl = st_init_numtable();
1654
rb_gc_register_address(&compat_allocator_tbl_wrapper);
1655
compat_allocator_tbl_wrapper =
1656
Data_Wrap_Struct(rb_cData, mark_marshal_compat_t, 0, compat_allocator_tbl);