aboutsummaryrefslogtreecommitdiffstats
path: root/struct.c
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
commit6af392c73dc9be5ea09080d3d24e76bf1d7638f3 (patch)
treedc06bd74a568571a2996dee55475d9a3a812aa81 /struct.c
parent56cfbfc297d9e1d7820e6bece4cefed556401e2c (diff)
downloadruby-6af392c73dc9be5ea09080d3d24e76bf1d7638f3.tar.gz
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
Diffstat (limited to 'struct.c')
-rw-r--r--struct.c120
1 files changed, 52 insertions, 68 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;