summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-11-16 05:46:50 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-11-16 05:46:50 +0000
commit9044b126e5d4516b28718a76c162edfc77d4a933 (patch)
treedc06bd74a568571a2996dee55475d9a3a812aa81
parentf4fbc7d2a6691a7f789a8a644705039d9bbd0ffe (diff)
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
-rw-r--r--struct.c120
-rw-r--r--test/ruby/test_struct.rb8
2 files changed, 56 insertions, 72 deletions
diff --git a/struct.c b/struct.c
index 817e0a1b9b..df627b3955 100644
--- a/struct.c
+++ b/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);
+ long i;
+ VALUE idx = *name;
+
+ 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;
}
- rb_name_err_raise("no member '%1$s' in struct", s, name);
+}
- UNREACHABLE;
+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;
diff --git a/test/ruby/test_struct.rb b/test/ruby/test_struct.rb
index df859f75cb..f51432cfd6 100644
--- a/test/ruby/test_struct.rb
+++ b/test/ruby/test_struct.rb
@@ -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