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

ruby-changes:29867

From: nobu <ko1@a...>
Date: Thu, 11 Jul 2013 20:18:13 +0900 (JST)
Subject: [ruby-changes:29867] nobu:r41919 (trunk): string.c: multi-byte terminator

nobu	2013-07-11 20:17:59 +0900 (Thu, 11 Jul 2013)

  New Revision: 41919

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

  Log:
    string.c: multi-byte terminator
    
    * string.c (rb_string_value_cstr): fill minimum length of the encoding
      as the terminator.

  Modified files:
    trunk/ChangeLog
    trunk/ext/-test-/string/cstr.c
    trunk/string.c
    trunk/test/-ext-/string/test_cstr.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 41918)
+++ ChangeLog	(revision 41919)
@@ -1,4 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
-Thu Jul 11 20:17:51 2013  Nobuyoshi Nakada  <nobu@r...>
+Thu Jul 11 20:17:57 2013  Nobuyoshi Nakada  <nobu@r...>
+
+	* string.c (rb_string_value_cstr): fill minimum length of the encoding
+	  as the terminator.
 
 	* string.c (rb_string_value_cstr): check null char in char, not in
 	  byte.
Index: string.c
===================================================================
--- string.c	(revision 41918)
+++ string.c	(revision 41919)
@@ -91,6 +91,15 @@ VALUE rb_cSymbol; https://github.com/ruby/ruby/blob/trunk/string.c#L91
     }\
 } while (0)
 
+#define TERM_LEN(str) rb_enc_mbminlen(rb_enc_get(str))
+#define TERM_FILL(ptr, termlen) do {\
+    char *const term_fill_ptr = (ptr);\
+    const int term_fill_len = (termlen);\
+    *term_fill_ptr = '\0';\
+    if (UNLIKELY(term_fill_len > 1))\
+	memset(term_fill_ptr, 0, term_fill_len);\
+} while (0)
+
 #define RESIZE_CAPA(str,capacity) do {\
     if (STR_EMBED_P(str)) {\
 	if ((capacity) > RSTRING_EMBED_LEN_MAX) {\
@@ -1471,6 +1480,25 @@ str_null_char(const char *s, long len, r https://github.com/ruby/ruby/blob/trunk/string.c#L1480
     return 0;
 }
 
+static char *
+str_fill_term(VALUE str, char *s, long len, int termlen, rb_encoding *enc)
+{
+    long capa = rb_str_capacity(str) + 1;
+    int n;
+
+    if (capa < len + termlen) {
+	rb_str_modify_expand(str, len + termlen - capa);
+    }
+    else {
+	const char *e = s + len;
+	if (!rb_enc_ascget(e, e + termlen, &n, enc)) return s;
+	rb_str_modify(str);
+    }
+    s = RSTRING_PTR(str);
+    TERM_FILL(s + len, termlen);
+    return s;
+}
+
 char *
 rb_string_value_cstr(volatile VALUE *ptr)
 {
@@ -1484,8 +1512,8 @@ rb_string_value_cstr(volatile VALUE *ptr https://github.com/ruby/ruby/blob/trunk/string.c#L1512
 	if (str_null_char(s, len, enc)) {
 	    rb_raise(rb_eArgError, "string contains null char");
 	}
+	return str_fill_term(str, s, len, minlen, enc);
     }
-    else
     if (!s || memchr(s, 0, len)) {
 	rb_raise(rb_eArgError, "string contains null byte");
     }
Index: ext/-test-/string/cstr.c
===================================================================
--- ext/-test-/string/cstr.c	(revision 41918)
+++ ext/-test-/string/cstr.c	(revision 41919)
@@ -1,16 +1,22 @@ https://github.com/ruby/ruby/blob/trunk/ext/-test-/string/cstr.c#L1
 #include "ruby.h"
+#include "ruby/encoding.h"
 
 static VALUE
 bug_str_cstr_term(VALUE str)
 {
     long len;
     char *s;
+    int c;
+    rb_encoding *enc;
+
     rb_str_modify(str);
     len = RSTRING_LEN(str);
     RSTRING_PTR(str)[len] = 'x';
     s = StringValueCStr(str);
     rb_gc();
-    return INT2NUM(s[len]);
+    enc = rb_enc_get(str);
+    c = rb_enc_codepoint(&s[len], &s[len+rb_enc_mbminlen(enc)], enc);
+    return INT2NUM(c);
 }
 
 void
Index: test/-ext-/string/test_cstr.rb
===================================================================
--- test/-ext-/string/test_cstr.rb	(revision 41918)
+++ test/-ext-/string/test_cstr.rb	(revision 41919)
@@ -19,18 +19,24 @@ class Test_StringCStr < Test::Unit::Test https://github.com/ruby/ruby/blob/trunk/test/-ext-/string/test_cstr.rb#L19
 
   def test_wchar_embed
     WCHARS.each do |enc|
-      s = Bug::String.new("ab".encode(enc))
+      s = Bug::String.new("\u{4022}a".encode(enc))
       assert_nothing_raised(ArgumentError) {s.cstr_term}
+      s.set_len(s.bytesize / 2)
+      assert_equal(1, s.size)
+      assert_equal(0, s.cstr_term)
     end
   end
 
   def test_wchar_long
-    str = "abcdef"
+    str = "\u{4022}abcdef"
     n = 100
     len = str.size * n
     WCHARS.each do |enc|
       s = Bug::String.new(str.encode(enc))*n
       assert_nothing_raised(ArgumentError) {s.cstr_term}
+      s.set_len(s.bytesize / 2)
+      assert_equal(len / 2, s.size)
+      assert_equal(0, s.cstr_term)
     end
   end
 end

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

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