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

ruby-changes:18703

From: nobu <ko1@a...>
Date: Sun, 30 Jan 2011 13:06:39 +0900 (JST)
Subject: [ruby-changes:18703] Ruby:r30729 (trunk): * string.c (rb_str_ellipsize): new function to ellipsize a string.

nobu	2011-01-30 13:01:58 +0900 (Sun, 30 Jan 2011)

  New Revision: 30729

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

  Log:
    * string.c (rb_str_ellipsize): new function to ellipsize a string.

  Added files:
    trunk/ext/-test-/string/ellipsize.c
    trunk/test/-ext-/string/test_ellipsize.rb
  Modified files:
    trunk/ChangeLog
    trunk/include/ruby/intern.h
    trunk/string.c

Index: include/ruby/intern.h
===================================================================
--- include/ruby/intern.h	(revision 30728)
+++ include/ruby/intern.h	(revision 30729)
@@ -712,6 +712,7 @@
 VALUE rb_str_length(VALUE);
 long rb_str_offset(VALUE, long);
 size_t rb_str_capacity(VALUE);
+VALUE rb_str_ellipsize(VALUE, long);
 #if defined __GNUC__
 #define rb_str_new_cstr(str) __extension__ (	\
 {						\
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 30728)
+++ ChangeLog	(revision 30729)
@@ -1,5 +1,7 @@
-Sun Jan 30 12:56:13 2011  Nobuyoshi Nakada  <nobu@r...>
+Sun Jan 30 13:01:54 2011  Nobuyoshi Nakada  <nobu@r...>
 
+	* string.c (rb_str_ellipsize): new function to ellipsize a string.
+
 	* include/ruby/encoding.h (rb_enc_step_back): new function to step
 	  back n characters.
 
Index: string.c
===================================================================
--- string.c	(revision 30728)
+++ string.c	(revision 30729)
@@ -7137,6 +7137,57 @@
     return cr == ENC_CODERANGE_7BIT ? Qtrue : Qfalse;
 }
 
+/**
+ * Shortens _str_ and adds three dots, an ellipsis, if it is longer
+ * than _len_ characters.
+ *
+ * \param str	the string to ellipsize.
+ * \param len	the maximum string length.
+ * \return	the ellipsized string.
+ * \pre 	_len_ must not be negative.
+ * \post	the length of the returned string in characters is less than or equal to _len_.
+ * \post	If the length of _str_ is less than or equal _len_, returns _str_ itself.
+ * \post	the encoded of returned string is equal to the encoded of _str_.
+ * \post	the class of returned string is equal to the class of _str_.
+ * \note	the length is counted in characters.
+ */
+VALUE
+rb_str_ellipsize(VALUE str, long len)
+{
+    static const char ellipsis[] = "...";
+    const long ellipsislen = sizeof(ellipsis) - 1;
+    rb_encoding *const enc = rb_enc_get(str);
+    const long blen = RSTRING_LEN(str);
+    const char *const p = RSTRING_PTR(str), *e = p + blen;
+    VALUE estr, ret = 0;
+
+    if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);
+    if (len * rb_enc_mbminlen(enc) >= blen ||
+	(e = rb_enc_nth(p, e, len, enc)) - p == blen) {
+	ret = str;
+    }
+    else if (len <= ellipsislen ||
+	     !(e = rb_enc_step_back(p, e, e, len = ellipsislen, enc))) {
+	if (rb_enc_asciicompat(enc)) {
+	    ret = rb_str_new_with_class(str, ellipsis, len);
+	    rb_enc_associate(ret, enc);
+	}
+	else {
+	    estr = rb_usascii_str_new(ellipsis, len);
+	    ret = rb_str_encode(estr, rb_enc_from_encoding(enc), 0, Qnil);
+	}
+    }
+    else if (ret = rb_str_subseq(str, 0, e - p), rb_enc_asciicompat(enc)) {
+	rb_str_cat(ret, ellipsis, ellipsislen);
+    }
+    else {
+	estr = rb_str_encode(rb_usascii_str_new(ellipsis, ellipsislen),
+			     rb_enc_from_encoding(enc), 0, Qnil);
+	rb_str_append(ret, estr);
+    }
+    return ret;
+}
+
 /**********************************************************************
  * Document-class: Symbol
  *
Index: ext/-test-/string/ellipsize.c
===================================================================
--- ext/-test-/string/ellipsize.c	(revision 0)
+++ ext/-test-/string/ellipsize.c	(revision 30729)
@@ -0,0 +1,13 @@
+#include "ruby.h"
+
+static VALUE
+bug_str_ellipsize(VALUE str, VALUE len)
+{
+    return rb_str_ellipsize(str, NUM2LONG(len));
+}
+
+void
+Init_ellipsize(VALUE klass)
+{
+    rb_define_method(klass, "ellipsize", bug_str_ellipsize, 1);
+}

Property changes on: ext/-test-/string/ellipsize.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: test/-ext-/string/test_ellipsize.rb
===================================================================
--- test/-ext-/string/test_ellipsize.rb	(revision 0)
+++ test/-ext-/string/test_ellipsize.rb	(revision 30729)
@@ -0,0 +1,46 @@
+require 'test/unit'
+require "-test-/string/string"
+
+class Test_StringEllipsize < Test::Unit::TestCase
+  def setup
+    @foobar = Bug::String.new("foobar")
+  end
+
+  def assert_equal_with_class(expected, result, *rest)
+    assert_equal(expected.encoding, result.encoding, *rest)
+    assert_equal(expected, result, result.encoding.name)
+    assert_instance_of(Bug::String, result, *rest)
+  end
+
+  def test_longer
+    assert_equal_with_class("", @foobar.ellipsize(0))
+    assert_equal_with_class(".", @foobar.ellipsize(1))
+    assert_equal_with_class("..", @foobar.ellipsize(2))
+    assert_equal_with_class("...", @foobar.ellipsize(3))
+    assert_equal_with_class("f...", @foobar.ellipsize(4))
+    assert_equal_with_class("fo...", @foobar.ellipsize(5))
+  end
+
+  def test_shorter
+    assert_same(@foobar, @foobar.ellipsize(6))
+    assert_same(@foobar, @foobar.ellipsize(7))
+  end
+
+  def test_negative_length
+    assert_raise(IndexError) {@foobar.ellipsize(-1)}
+  end
+
+  def test_nonascii
+    a = "\u3042"
+    encs = Encoding.list.each do |enc|
+      next if enc.dummy?
+      begin
+        s = a.encode(enc)
+        e = "...".encode(enc)
+      rescue
+      else
+        assert_equal_with_class(s*12+e, Bug::String.new(s*20).ellipsize(15))
+      end
+    end
+  end
+end

Property changes on: test/-ext-/string/test_ellipsize.rb
___________________________________________________________________
Added: svn:eol-style
   + LF


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

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