[ruby-dev:31801] Re: RSTRING(value)->ptr == NULL ?

From: Nobuyoshi Nakada <nobu@...>
Date: 2007-09-20 07:30:10 UTC
List: ruby-dev #31801
なかだです。

At Thu, 20 Sep 2007 14:12:43 +0900,
Tanaka Akira wrote in [ruby-dev:31800]:
> [ruby-core:1177] で似た指摘がされています。そのスレッドにお
> いてまつもとさんは [ruby-core:1185] で 1.8.0 には空文字列で
> も ptr は "" を指すようにすると発言しています。

そんな話もありましたねぇ。

> また、1.9 では RSTRING_PTR(str) は " ".chop.dup は NULL にな
> りません。

RSTRING_PTR()の実装自体が大きく変わってますから。

> なお、[ruby-core:1185] と [ruby-dev:31778] の発言には食い違
> いがありますが、よくあることです。私の推測としては、NULL に
> なっているのは単なる修正洩れである可能性が高いと思います。

もう最初からNULLにはしないということでもいいと思いますが、こんな
とこでどうでしょうか。


Index: string.c
===================================================================
--- string.c	(revision 13449)
+++ string.c	(working copy)
@@ -60,11 +60,15 @@ str_frozen_check(s)
 }
 
+static VALUE str_alloc0 _((VALUE, int));
 static VALUE str_alloc _((VALUE));
+static VALUE str_alloc1 _((VALUE));
+
 static VALUE
-str_alloc(klass)
+str_alloc0(klass, flags)
     VALUE klass;
+    int flags;
 {
     NEWOBJ(str, struct RString);
-    OBJSETUP(str, klass, T_STRING);
+    OBJSETUP(str, klass, flags);
 
     str->ptr = 0;
@@ -75,4 +79,23 @@ str_alloc(klass)
 }
 
+static const char null_str[] = "";
+#define null_str (char *)null_str
+
+static VALUE
+str_alloc(klass)
+    VALUE klass;
+{
+    VALUE str = str_alloc0(klass, T_STRING | ELTS_SHARED);
+    RSTRING(str)->ptr = null_str;
+    return str;
+}
+
+static VALUE
+str_alloc1(klass)
+    VALUE klass;
+{
+    return str_alloc0(klass, T_STRING);
+}
+
 static VALUE
 str_new(klass, ptr, len)
@@ -87,5 +110,5 @@ str_new(klass, ptr, len)
     }
 
-    str = str_alloc(klass);
+    str = str_alloc1(klass);
     RSTRING(str)->len = len;
     RSTRING(str)->aux.capa = len;
@@ -146,5 +169,4 @@ str_new3(klass, str)
     RSTRING(str2)->ptr = RSTRING(str)->ptr;
     RSTRING(str2)->aux.shared = str;
-    FL_SET(str2, ELTS_SHARED);
 
     return str2;
@@ -165,5 +187,5 @@ str_new4(klass, str)
     VALUE klass, str;
 {
-    VALUE str2 = str_alloc(klass);
+    VALUE str2 = str_alloc1(klass);
 
     RSTRING(str2)->len = RSTRING(str)->len;
@@ -224,5 +246,5 @@ rb_str_buf_new(capa)
     long capa;
 {
-    VALUE str = str_alloc(rb_cString);
+    VALUE str = str_alloc1(rb_cString);
 
     if (capa < STR_BUF_MIN_SIZE) {
@@ -258,4 +280,6 @@ rb_str_to_str(str)
 }
 
+static int str_independent _((VALUE));
+
 static void
 rb_str_shared_replace(str, str2)
@@ -263,6 +287,5 @@ rb_str_shared_replace(str, str2)
 {
     if (str == str2) return;
-    rb_str_modify(str);
-    if (!FL_TEST(str, ELTS_SHARED)) free(RSTRING(str)->ptr);
+    if (str_independent(str)) xfree(RSTRING(str)->ptr);
     if (NIL_P(str2)) {
 	RSTRING(str)->ptr = 0;
@@ -539,6 +570,4 @@ rb_str_associated(str)
 }
 
-static char *null_str = "";
-
 VALUE
 rb_string_value(ptr)
@@ -2266,6 +2295,9 @@ rb_str_replace(str, str2)
 	RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared;
     }
+    else if (!RSTRING(str2)->len) {
+	FL_SET(str, ELTS_SHARED);
+	RSTRING(str)->ptr = null_str;
+    }
     else {
-	rb_str_modify(str);
 	rb_str_resize(str, RSTRING(str2)->len);
 	memcpy(RSTRING(str)->ptr, RSTRING(str2)->ptr, RSTRING(str2)->len);


-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

In This Thread