mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
marshal.c: refine special instance variables
* marshal.c (w_obj_each, obj_count_ivars): count instance variables accurately. * marshal.c (encoding_name, w_encoding): separate getting encoding values and writing them. * marshal.c (w_symbol, w_ivar, w_objivar, w_object): refine special instance variables. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44838 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
17a47a3358
commit
5ba39a12d9
1 changed files with 77 additions and 49 deletions
126
marshal.c
126
marshal.c
|
@ -219,7 +219,8 @@ class2path(VALUE klass)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void w_long(long, struct dump_arg*);
|
static void w_long(long, struct dump_arg*);
|
||||||
static void w_encoding(VALUE obj, long num, struct dump_call_arg *arg);
|
static void w_encoding(VALUE encname, struct dump_call_arg *arg);
|
||||||
|
static VALUE encoding_name(VALUE obj, struct dump_arg *arg);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w_nbyte(const char *s, long n, struct dump_arg *arg)
|
w_nbyte(const char *s, long n, struct dump_arg *arg)
|
||||||
|
@ -410,7 +411,7 @@ w_symbol(ID id, struct dump_arg *arg)
|
||||||
{
|
{
|
||||||
VALUE sym;
|
VALUE sym;
|
||||||
st_data_t num;
|
st_data_t num;
|
||||||
int encidx = -1;
|
VALUE encname;
|
||||||
|
|
||||||
if (st_lookup(arg->symbols, id, &num)) {
|
if (st_lookup(arg->symbols, id, &num)) {
|
||||||
w_byte(TYPE_SYMLINK, arg);
|
w_byte(TYPE_SYMLINK, arg);
|
||||||
|
@ -421,10 +422,10 @@ w_symbol(ID id, struct dump_arg *arg)
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
rb_raise(rb_eTypeError, "can't dump anonymous ID %"PRIdVALUE, id);
|
rb_raise(rb_eTypeError, "can't dump anonymous ID %"PRIdVALUE, id);
|
||||||
}
|
}
|
||||||
encidx = rb_enc_get_index(sym);
|
encname = encoding_name(sym, arg);
|
||||||
if (encidx == rb_usascii_encindex() ||
|
if (NIL_P(encname) ||
|
||||||
rb_enc_str_coderange(sym) == ENC_CODERANGE_7BIT) {
|
rb_enc_str_coderange(sym) == ENC_CODERANGE_7BIT) {
|
||||||
encidx = -1;
|
encname = Qnil;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
w_byte(TYPE_IVAR, arg);
|
w_byte(TYPE_IVAR, arg);
|
||||||
|
@ -432,11 +433,12 @@ w_symbol(ID id, struct dump_arg *arg)
|
||||||
w_byte(TYPE_SYMBOL, arg);
|
w_byte(TYPE_SYMBOL, arg);
|
||||||
w_bytes(RSTRING_PTR(sym), RSTRING_LEN(sym), arg);
|
w_bytes(RSTRING_PTR(sym), RSTRING_LEN(sym), arg);
|
||||||
st_add_direct(arg->symbols, id, arg->symbols->num_entries);
|
st_add_direct(arg->symbols, id, arg->symbols->num_entries);
|
||||||
if (encidx != -1) {
|
if (!NIL_P(encname)) {
|
||||||
struct dump_call_arg c_arg;
|
struct dump_call_arg c_arg;
|
||||||
c_arg.limit = 1;
|
c_arg.limit = 1;
|
||||||
c_arg.arg = arg;
|
c_arg.arg = arg;
|
||||||
w_encoding(sym, 0, &c_arg);
|
w_long(1L, arg);
|
||||||
|
w_encoding(encname, &c_arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -511,6 +513,8 @@ w_uclass(VALUE obj, VALUE super, struct dump_arg *arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define to_be_skipped_id(id) (id == rb_id_encoding() || id == rb_intern("E"))
|
||||||
|
|
||||||
static int
|
static int
|
||||||
w_obj_each(st_data_t key, st_data_t val, st_data_t a)
|
w_obj_each(st_data_t key, st_data_t val, st_data_t a)
|
||||||
{
|
{
|
||||||
|
@ -518,56 +522,80 @@ w_obj_each(st_data_t key, st_data_t val, st_data_t a)
|
||||||
VALUE value = (VALUE)val;
|
VALUE value = (VALUE)val;
|
||||||
struct dump_call_arg *arg = (struct dump_call_arg *)a;
|
struct dump_call_arg *arg = (struct dump_call_arg *)a;
|
||||||
|
|
||||||
if (id == rb_id_encoding()) return ST_CONTINUE;
|
if (to_be_skipped_id(id)) return ST_CONTINUE;
|
||||||
if (id == rb_intern("E")) return ST_CONTINUE;
|
|
||||||
w_symbol(id, arg->arg);
|
w_symbol(id, arg->arg);
|
||||||
w_object(value, arg->arg, arg->limit);
|
w_object(value, arg->arg, arg->limit);
|
||||||
return ST_CONTINUE;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
w_encoding(VALUE obj, long num, struct dump_call_arg *arg)
|
obj_count_ivars(st_data_t key, st_data_t val, st_data_t a)
|
||||||
|
{
|
||||||
|
ID id = (ID)key;
|
||||||
|
if (!to_be_skipped_id(id)) ++*(st_index_t *)a;
|
||||||
|
return ST_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
encoding_name(VALUE obj, struct dump_arg *arg)
|
||||||
{
|
{
|
||||||
int encidx = rb_enc_get_index(obj);
|
int encidx = rb_enc_get_index(obj);
|
||||||
rb_encoding *enc = 0;
|
rb_encoding *enc = 0;
|
||||||
st_data_t name;
|
st_data_t name;
|
||||||
|
|
||||||
if (encidx <= 0 || !(enc = rb_enc_from_index(encidx))) {
|
if (encidx <= 0 || !(enc = rb_enc_from_index(encidx))) {
|
||||||
w_long(num, arg->arg);
|
return Qnil;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
w_long(num + 1, arg->arg);
|
|
||||||
|
|
||||||
/* special treatment for US-ASCII and UTF-8 */
|
/* special treatment for US-ASCII and UTF-8 */
|
||||||
if (encidx == rb_usascii_encindex()) {
|
if (encidx == rb_usascii_encindex()) {
|
||||||
w_symbol(rb_intern("E"), arg->arg);
|
return Qfalse;
|
||||||
w_object(Qfalse, arg->arg, arg->limit + 1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else if (encidx == rb_utf8_encindex()) {
|
else if (encidx == rb_utf8_encindex()) {
|
||||||
w_symbol(rb_intern("E"), arg->arg);
|
return Qtrue;
|
||||||
w_object(Qtrue, arg->arg, arg->limit + 1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
w_symbol(rb_id_encoding(), arg->arg);
|
if (arg->encodings ?
|
||||||
do {
|
!st_lookup(arg->encodings, (st_data_t)rb_enc_name(enc), &name) :
|
||||||
if (!arg->arg->encodings)
|
(arg->encodings = st_init_strcasetable(), 1)) {
|
||||||
arg->arg->encodings = st_init_strcasetable();
|
name = (st_data_t)rb_str_new_cstr(rb_enc_name(enc));
|
||||||
else if (st_lookup(arg->arg->encodings, (st_data_t)rb_enc_name(enc), &name))
|
st_insert(arg->encodings, (st_data_t)rb_enc_name(enc), name);
|
||||||
break;
|
}
|
||||||
name = (st_data_t)rb_str_new2(rb_enc_name(enc));
|
return (VALUE)name;
|
||||||
st_insert(arg->arg->encodings, (st_data_t)rb_enc_name(enc), name);
|
|
||||||
} while (0);
|
|
||||||
w_object(name, arg->arg, arg->limit + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w_ivar(VALUE obj, st_table *tbl, struct dump_call_arg *arg)
|
w_encoding(VALUE encname, struct dump_call_arg *arg)
|
||||||
{
|
{
|
||||||
long num = tbl ? tbl->num_entries : 0;
|
switch (encname) {
|
||||||
|
case Qfalse:
|
||||||
|
case Qtrue:
|
||||||
|
w_symbol(rb_intern("E"), arg->arg);
|
||||||
|
w_object(encname, arg->arg, arg->limit + 1);
|
||||||
|
case Qnil:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
w_symbol(rb_id_encoding(), arg->arg);
|
||||||
|
w_object(encname, arg->arg, arg->limit + 1);
|
||||||
|
}
|
||||||
|
|
||||||
w_encoding(obj, num, arg);
|
static st_index_t
|
||||||
|
has_ivars(VALUE obj, VALUE encname, st_table **ivtbl)
|
||||||
|
{
|
||||||
|
st_index_t num = !NIL_P(encname);
|
||||||
|
|
||||||
|
*ivtbl = rb_generic_ivar_table(obj);
|
||||||
|
if (*ivtbl) {
|
||||||
|
st_foreach_safe(*ivtbl, obj_count_ivars, (st_data_t)&num);
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
w_ivar(st_index_t num, st_table *tbl, VALUE encname, struct dump_call_arg *arg)
|
||||||
|
{
|
||||||
|
w_long(num, arg->arg);
|
||||||
|
w_encoding(encname, arg);
|
||||||
if (tbl) {
|
if (tbl) {
|
||||||
st_foreach_safe(tbl, w_obj_each, (st_data_t)arg);
|
st_foreach_safe(tbl, w_obj_each, (st_data_t)arg);
|
||||||
}
|
}
|
||||||
|
@ -586,7 +614,7 @@ w_objivar(VALUE obj, struct dump_call_arg *arg)
|
||||||
if (ptr[i] != Qundef)
|
if (ptr[i] != Qundef)
|
||||||
num += 1;
|
num += 1;
|
||||||
|
|
||||||
w_encoding(obj, num, arg);
|
w_long(num, arg->arg);
|
||||||
if (num != 0) {
|
if (num != 0) {
|
||||||
rb_ivar_foreach(obj, w_obj_each, (st_data_t)arg);
|
rb_ivar_foreach(obj, w_obj_each, (st_data_t)arg);
|
||||||
}
|
}
|
||||||
|
@ -598,9 +626,8 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
|
||||||
struct dump_call_arg c_arg;
|
struct dump_call_arg c_arg;
|
||||||
st_table *ivtbl = 0;
|
st_table *ivtbl = 0;
|
||||||
st_data_t num;
|
st_data_t num;
|
||||||
int hasiv = 0;
|
st_index_t hasiv = 0;
|
||||||
#define has_ivars(obj, ivtbl) ((((ivtbl) = rb_generic_ivar_table(obj)) != 0) || \
|
VALUE encname = Qnil;
|
||||||
(!SPECIAL_CONST_P(obj) && !ENCODING_IS_ASCII8BIT(obj)))
|
|
||||||
|
|
||||||
if (limit == 0) {
|
if (limit == 0) {
|
||||||
rb_raise(rb_eArgError, "exceed depth limit");
|
rb_raise(rb_eArgError, "exceed depth limit");
|
||||||
|
@ -663,7 +690,8 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
|
||||||
}
|
}
|
||||||
if (rb_obj_respond_to(obj, s_dump, TRUE)) {
|
if (rb_obj_respond_to(obj, s_dump, TRUE)) {
|
||||||
st_table *ivtbl2 = 0;
|
st_table *ivtbl2 = 0;
|
||||||
int hasiv2;
|
st_index_t hasiv2;
|
||||||
|
VALUE encname2;
|
||||||
|
|
||||||
v = INT2NUM(limit);
|
v = INT2NUM(limit);
|
||||||
v = rb_funcall2(obj, s_dump, 1, &v);
|
v = rb_funcall2(obj, s_dump, 1, &v);
|
||||||
|
@ -671,18 +699,18 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
|
||||||
if (!RB_TYPE_P(v, T_STRING)) {
|
if (!RB_TYPE_P(v, T_STRING)) {
|
||||||
rb_raise(rb_eTypeError, "_dump() must return string");
|
rb_raise(rb_eTypeError, "_dump() must return string");
|
||||||
}
|
}
|
||||||
hasiv = has_ivars(obj, ivtbl);
|
hasiv = has_ivars(obj, (encname = encoding_name(obj, arg)), &ivtbl);
|
||||||
if (hasiv) w_byte(TYPE_IVAR, arg);
|
hasiv2 = has_ivars(v, (encname2 = encoding_name(v, arg)), &ivtbl2);
|
||||||
if ((hasiv2 = has_ivars(v, ivtbl2)) != 0 && !hasiv) {
|
if (hasiv2) {
|
||||||
w_byte(TYPE_IVAR, arg);
|
hasiv = hasiv2;
|
||||||
|
ivtbl = ivtbl2;
|
||||||
|
encname = encname2;
|
||||||
}
|
}
|
||||||
|
if (hasiv) w_byte(TYPE_IVAR, arg);
|
||||||
w_class(TYPE_USERDEF, obj, arg, FALSE);
|
w_class(TYPE_USERDEF, obj, arg, FALSE);
|
||||||
w_bytes(RSTRING_PTR(v), RSTRING_LEN(v), arg);
|
w_bytes(RSTRING_PTR(v), RSTRING_LEN(v), arg);
|
||||||
if (hasiv2) {
|
if (hasiv) {
|
||||||
w_ivar(v, ivtbl2, &c_arg);
|
w_ivar(hasiv, ivtbl, encname, &c_arg);
|
||||||
}
|
|
||||||
else if (hasiv) {
|
|
||||||
w_ivar(obj, ivtbl, &c_arg);
|
|
||||||
}
|
}
|
||||||
st_add_direct(arg->data, obj, arg->data->num_entries);
|
st_add_direct(arg->data, obj, arg->data->num_entries);
|
||||||
return;
|
return;
|
||||||
|
@ -690,7 +718,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
|
||||||
|
|
||||||
st_add_direct(arg->data, obj, arg->data->num_entries);
|
st_add_direct(arg->data, obj, arg->data->num_entries);
|
||||||
|
|
||||||
hasiv = has_ivars(obj, ivtbl);
|
hasiv = has_ivars(obj, (encname = encoding_name(obj, arg)), &ivtbl);
|
||||||
{
|
{
|
||||||
st_data_t compat_data;
|
st_data_t compat_data;
|
||||||
rb_alloc_func_t allocator = rb_get_alloc_func(RBASIC(obj)->klass);
|
rb_alloc_func_t allocator = rb_get_alloc_func(RBASIC(obj)->klass);
|
||||||
|
@ -855,7 +883,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
|
||||||
RB_GC_GUARD(obj);
|
RB_GC_GUARD(obj);
|
||||||
}
|
}
|
||||||
if (hasiv) {
|
if (hasiv) {
|
||||||
w_ivar(obj, ivtbl, &c_arg);
|
w_ivar(hasiv, ivtbl, encname, &c_arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue