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

ruby-changes:21694

From: kosaki <ko1@a...>
Date: Mon, 14 Nov 2011 12:54:49 +0900 (JST)
Subject: [ruby-changes:21694] kosaki:r33743 (trunk): * include/ruby/ruby.h: add NUM2SHORT(), NUM2USHORT() macros.

kosaki	2011-11-14 12:54:34 +0900 (Mon, 14 Nov 2011)

  New Revision: 33743

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

  Log:
    * include/ruby/ruby.h: add NUM2SHORT(), NUM2USHORT() macros.
    * numeric.c: ditto.
    
    * test/-ext-/num2int/test_num2int.rb: add testcases for NUM2SHORT().
    * ext/-test-/num2int/num2int.c: ditto.

  Modified files:
    trunk/ChangeLog
    trunk/ext/-test-/num2int/num2int.c
    trunk/include/ruby/ruby.h
    trunk/numeric.c
    trunk/test/-ext-/num2int/test_num2int.rb

Index: include/ruby/ruby.h
===================================================================
--- include/ruby/ruby.h	(revision 33742)
+++ include/ruby/ruby.h	(revision 33743)
@@ -540,6 +540,25 @@
 #define FIX2UINT(x) ((unsigned int)FIX2ULONG(x))
 #endif
 
+short rb_num2short(VALUE);
+unsigned short rb_num2ushort(VALUE);
+short rb_fix2short(VALUE);
+unsigned short rb_fix2ushort(VALUE);
+#define FIX2SHORT(x) (rb_fix2short((VALUE)(x)))
+#define NUM2SHORT_internal(x) (FIXNUM_P(x) ? FIX2SHORT(x) : rb_num2short(x))
+#ifdef __GNUC__
+# define NUM2SHORT(x) \
+    __extension__ ({VALUE num2short_x = (x); NUM2SHORT_internal(num2short_x);})
+#else /* __GNUC__ */
+static inline short
+NUM2SHORT(VALUE x)
+{
+    return NUM2SHORT_internal(x);
+}
+#endif /* __GNUC__ */
+#define NUM2USHORT(x) rb_num2ushort((VALUE)(x))
+
+
 #ifdef HAVE_LONG_LONG
 LONG_LONG rb_num2ll(VALUE);
 unsigned LONG_LONG rb_num2ull(VALUE);
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 33742)
+++ ChangeLog	(revision 33743)
@@ -1,3 +1,11 @@
+Sun Nov 13 10:28:18 2011  KOSAKI Motohiro  <kosaki.motohiro@g...>
+
+	* include/ruby/ruby.h: add NUM2SHORT(), NUM2USHORT() macros.
+	* numeric.c: ditto.
+
+	* test/-ext-/num2int/test_num2int.rb: add testcases for NUM2SHORT().
+	* ext/-test-/num2int/num2int.c: ditto.
+
 Sun Nov 13 10:23:48 2011  KOSAKI Motohiro  <kosaki.motohiro@g...>
 
 	* bignum.c (rb_big2ull): fix off-by-twice bug of NUM2ULL.
Index: ext/-test-/num2int/num2int.c
===================================================================
--- ext/-test-/num2int/num2int.c	(revision 33742)
+++ ext/-test-/num2int/num2int.c	(revision 33743)
@@ -3,6 +3,28 @@
 extern VALUE rb_stdout;
 
 static VALUE
+print_num2short(VALUE obj, VALUE num)
+{
+    char buf[128];
+    VALUE str;
+
+    sprintf(buf, "%d", NUM2SHORT(num));
+    str = rb_str_new_cstr(buf);
+    rb_io_write(rb_stdout, str);
+}
+
+static VALUE
+print_num2ushort(VALUE obj, VALUE num)
+{
+    char buf[128];
+    VALUE str;
+
+    sprintf(buf, "%u", NUM2USHORT(num));
+    str = rb_str_new_cstr(buf);
+    rb_io_write(rb_stdout, str);
+}
+
+static VALUE
 print_num2int(VALUE obj, VALUE num)
 {
     char buf[128];
@@ -74,6 +96,9 @@
 {
     VALUE cNum2int = rb_path2class("TestNum2int::Num2int");
 
+    rb_define_singleton_method(cNum2int, "print_num2short", print_num2short, 1);
+    rb_define_singleton_method(cNum2int, "print_num2ushort", print_num2ushort, 1);
+
     rb_define_singleton_method(cNum2int, "print_num2int", print_num2int, 1);
     rb_define_singleton_method(cNum2int, "print_num2uint", print_num2uint, 1);
 
Index: numeric.c
===================================================================
--- numeric.c	(revision 33742)
+++ numeric.c	(revision 33743)
@@ -1953,6 +1953,80 @@
 }
 #endif
 
+void
+rb_out_of_short(SIGNED_VALUE num)
+{
+    rb_raise(rb_eRangeError, "integer %"PRIdVALUE " too %s to convert to `short'",
+	     num, num < 0 ? "small" : "big");
+}
+
+static void
+check_short(SIGNED_VALUE num)
+{
+    if ((SIGNED_VALUE)(short)num != num) {
+	rb_out_of_short(num);
+    }
+}
+
+static void
+check_ushort(VALUE num, VALUE sign)
+{
+    static const VALUE mask = ~(VALUE)USHRT_MAX;
+
+    if (RTEST(sign)) {
+	/* minus */
+	if ((num & mask) != mask || (num & ~mask) <= SHRT_MAX)
+#define VALUE_MSBMASK   ((VALUE)1 << ((sizeof(VALUE) * CHAR_BIT) - 1))
+	    rb_raise(rb_eRangeError, "integer %"PRIdVALUE " too small to convert to `unsigned short'", num|VALUE_MSBMASK);
+    }
+    else {
+	/* plus */
+	if ((num & mask) != 0)
+	    rb_raise(rb_eRangeError, "integer %"PRIuVALUE " too big to convert to `unsigned short'", num);
+    }
+}
+
+short
+rb_num2short(VALUE val)
+{
+    long num = rb_num2long(val);
+
+    check_short(num);
+    return num;
+}
+
+short
+rb_fix2short(VALUE val)
+{
+    long num = FIXNUM_P(val)?FIX2LONG(val):rb_num2long(val);
+
+    check_short(num);
+    return num;
+}
+
+unsigned short
+rb_num2ushort(VALUE val)
+{
+    VALUE num = rb_num2ulong(val);
+
+    check_ushort(num, rb_funcall(val, '<', 1, INT2FIX(0)));
+    return (unsigned long)num;
+}
+
+unsigned short
+rb_fix2ushort(VALUE val)
+{
+    unsigned long num;
+
+    if (!FIXNUM_P(val)) {
+	return rb_num2uint(val);
+    }
+    num = FIX2ULONG(val);
+
+    check_ushort(num, rb_funcall(val, '<', 1, INT2FIX(0)));
+    return num;
+}
+
 VALUE
 rb_num2fix(VALUE val)
 {
Index: test/-ext-/num2int/test_num2int.rb
===================================================================
--- test/-ext-/num2int/test_num2int.rb	(revision 33742)
+++ test/-ext-/num2int/test_num2int.rb	(revision 33743)
@@ -5,6 +5,10 @@
   end
   require '-test-/num2int/num2int'
 
+  SHRT_MIN = -32768
+  SHRT_MAX = 32767
+  USHRT_MAX = 65535
+
   INT_MIN = -2147483648
   INT_MAX = 2147483647
   UINT_MAX = 4294967295
@@ -29,6 +33,42 @@
   FIXNUM_MAX = LONG_MAX/2
   FIXNUM_MIN = LONG_MIN/2
 
+  def test_num2short
+    assert_output(SHRT_MIN.to_s) do
+      Num2int.print_num2short(SHRT_MIN)
+    end
+    assert_output(SHRT_MAX.to_s) do
+      Num2int.print_num2short(SHRT_MAX)
+    end
+    assert_raise(RangeError) do
+      Num2int.print_num2short(SHRT_MIN-1)
+    end
+    assert_raise(RangeError) do
+      Num2int.print_num2short(SHRT_MAX+1)
+    end
+  end
+
+  def test_num2ushort
+    assert_output("0") do
+      Num2int.print_num2ushort(0)
+    end
+    assert_output(USHRT_MAX.to_s) do
+      Num2int.print_num2ushort(USHRT_MAX)
+    end
+    assert_output(USHRT_MAX.to_s) do
+      Num2int.print_num2ushort(-1)
+    end
+    assert_output((SHRT_MAX+1).to_s) do
+      Num2int.print_num2ushort(SHRT_MIN)
+    end
+    assert_raise(RangeError) do
+      Num2int.print_num2ushort(SHRT_MIN-1)
+    end
+    assert_raise(RangeError) do
+      Num2int.print_num2ushort(USHRT_MAX+1)
+    end
+  end
+
   def test_num2int
     assert_output(INT_MIN.to_s) do
       Num2int.print_num2int(INT_MIN)

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

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