[前][次][番号順一覧][スレッド一覧]

ruby-changes:40503

From: nobu <ko1@a...>
Date: Mon, 16 Nov 2015 14:47:26 +0900 (JST)
Subject: [ruby-changes:40503] nobu:r52584 (trunk): struct.c: fix index in message

nobu	2015-11-16 14:46:50 +0900 (Mon, 16 Nov 2015)

  New Revision: 52584

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=52584

  Log:
    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.

  Modified files:
    trunk/struct.c
    trunk/test/ruby/test_struct.rb
Index: struct.c
===================================================================
--- struct.c	(revision 52583)
+++ struct.c	(revision 52584)
@@ -816,16 +816,57 @@ rb_struct_init_copy(VALUE copy, VALUE s) https://github.com/ruby/ruby/blob/trunk/struct.c#L816
     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);
     }
-    rb_name_err_raise("no member '%1$s' in struct", s, name);
+    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;
+    }
+}
 
-    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) https://github.com/ruby/ruby/blob/trunk/struct.c#L889
 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, https://github.com/ruby/ruby/blob/trunk/struct.c#L916
 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;
Index: test/ruby/test_struct.rb
===================================================================
--- test/ruby/test_struct.rb	(revision 52583)
+++ test/ruby/test_struct.rb	(revision 52584)
@@ -155,8 +155,8 @@ module TestStruct https://github.com/ruby/ruby/blob/trunk/test/ruby/test_struct.rb#L155
     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 https://github.com/ruby/ruby/blob/trunk/test/ruby/test_struct.rb#L166
     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

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]