struct.c: fix index in message

* struct.c (rb_struct_aref, rb_struct_aset): show the given index,
  not offset index, in the error messages when the offset is out
  of the range.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52584 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2015-11-16 05:46:50 +00:00
Родитель f4fbc7d2a6
Коммит 9044b126e5
2 изменённых файлов: 57 добавлений и 73 удалений

122
struct.c
Просмотреть файл

@ -816,16 +816,57 @@ rb_struct_init_copy(VALUE copy, VALUE s)
return copy;
}
static VALUE
rb_struct_aref_sym(VALUE s, VALUE name)
static int
rb_struct_pos(VALUE s, VALUE *name)
{
int pos = struct_member_pos(s, name);
if (pos != -1) {
return RSTRUCT_GET(s, pos);
}
rb_name_err_raise("no member '%1$s' in struct", s, name);
long i;
VALUE idx = *name;
UNREACHABLE;
if (RB_TYPE_P(idx, T_SYMBOL)) {
return struct_member_pos(s, idx);
}
else if (RB_TYPE_P(idx, T_STRING)) {
idx = rb_check_symbol(name);
if (NIL_P(idx)) return -1;
return struct_member_pos(s, idx);
}
else {
long len;
i = NUM2LONG(idx);
len = RSTRUCT_LEN(s);
if (i < 0) {
if (i + len < 0) {
*name = LONG2FIX(i);
return -1;
}
i += len;
}
else if (len <= i) {
*name = LONG2FIX(i);
return -1;
}
return (int)i;
}
}
NORETURN(static void invalid_struct_pos(VALUE s, VALUE idx));
static void
invalid_struct_pos(VALUE s, VALUE idx)
{
if (FIXNUM_P(idx)) {
long i = FIX2INT(idx), len = RSTRUCT_LEN(s);
if (i < 0) {
rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
i, len);
}
else {
rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
i, len);
}
}
else {
rb_name_err_raise("no member '%1$s' in struct", s, idx);
}
}
/*
@ -848,46 +889,11 @@ rb_struct_aref_sym(VALUE s, VALUE name)
VALUE
rb_struct_aref(VALUE s, VALUE idx)
{
long i;
if (RB_TYPE_P(idx, T_SYMBOL)) {
return rb_struct_aref_sym(s, idx);
}
else if (RB_TYPE_P(idx, T_STRING)) {
ID id = rb_check_id(&idx);
if (!id) {
rb_name_err_raise("no member '%1$s' in struct",
s, idx);
}
return rb_struct_aref_sym(s, ID2SYM(id));
}
i = NUM2LONG(idx);
if (i < 0) i = RSTRUCT_LEN(s) + i;
if (i < 0)
rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
i, RSTRUCT_LEN(s));
if (RSTRUCT_LEN(s) <= i)
rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
i, RSTRUCT_LEN(s));
int i = rb_struct_pos(s, &idx);
if (i < 0) invalid_struct_pos(s, idx);
return RSTRUCT_GET(s, i);
}
static VALUE
rb_struct_aset_sym(VALUE s, VALUE name, VALUE val)
{
int pos = struct_member_pos(s, name);
if (pos != -1) {
rb_struct_modify(s);
RSTRUCT_SET(s, pos, val);
return val;
}
rb_name_err_raise("no member '%1$s' in struct", s, name);
UNREACHABLE;
}
/*
* call-seq:
* struct[name] = obj -> obj
@ -910,30 +916,8 @@ rb_struct_aset_sym(VALUE s, VALUE name, VALUE val)
VALUE
rb_struct_aset(VALUE s, VALUE idx, VALUE val)
{
long i;
if (RB_TYPE_P(idx, T_SYMBOL)) {
return rb_struct_aset_sym(s, idx, val);
}
if (RB_TYPE_P(idx, T_STRING)) {
ID id = rb_check_id(&idx);
if (!id) {
rb_name_err_raise("no member '%1$s' in struct",
s, idx);
}
return rb_struct_aset_sym(s, ID2SYM(id), val);
}
i = NUM2LONG(idx);
if (i < 0) i = RSTRUCT_LEN(s) + i;
if (i < 0) {
rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
i, RSTRUCT_LEN(s));
}
if (RSTRUCT_LEN(s) <= i) {
rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
i, RSTRUCT_LEN(s));
}
int i = rb_struct_pos(s, &idx);
if (i < 0) invalid_struct_pos(s, idx);
rb_struct_modify(s);
RSTRUCT_SET(s, i, val);
return val;

Просмотреть файл

@ -155,8 +155,8 @@ module TestStruct
klass = @Struct.new(:a)
o = klass.new(1)
assert_equal(1, o[0])
assert_raise(IndexError) { o[-2] }
assert_raise(IndexError) { o[1] }
assert_raise_with_message(IndexError, /offset -2\b/) {o[-2]}
assert_raise_with_message(IndexError, /offset 1\b/) {o[1]}
assert_raise_with_message(NameError, /foo/) {o["foo"]}
assert_raise_with_message(NameError, /foo/) {o[:foo]}
end
@ -166,8 +166,8 @@ module TestStruct
o = klass.new(1)
o[0] = 2
assert_equal(2, o[:a])
assert_raise(IndexError) { o[-2] = 3 }
assert_raise(IndexError) { o[1] = 3 }
assert_raise_with_message(IndexError, /offset -2\b/) {o[-2] = 3}
assert_raise_with_message(IndexError, /offset 1\b/) {o[1] = 3}
assert_raise_with_message(NameError, /foo/) {o["foo"] = 3}
assert_raise_with_message(NameError, /foo/) {o[:foo] = 3}
end