Re: [Cleanup, fixes] string.c
From:
Michal Rokos <m.rokos@...>
Date:
2002-09-09 11:57:06 UTC
List:
ruby-core #468
Hi,
based on matz's recomendations I made new version.
(Massive deletes are because matz said "discard".)
Michal
PS: Personally I think that to have more checks is not as bad. (I'm not
so much OK with, "It is assured, so don't check it." I'm little worried
about future...)
Index: string.c
===================================================================
RCS file: /src/ruby/string.c,v
retrieving revision 1.117
diff -u -p -r1.117 string.c
--- string.c 2002/09/03 05:20:06 1.117
+++ string.c 2002/09/09 11:54:41
@@ -61,18 +61,18 @@ str_new(klass, ptr, len)
if (len < 0) {
rb_raise(rb_eArgError, "negative string size (or size too big)");
}
-
str = rb_obj_alloc(klass);
RSTRING(str)->len = len;
RSTRING(str)->aux.capa = len;
RSTRING(str)->ptr = ALLOC_N(char,len+1);
+
if (ptr) {
memcpy(RSTRING(str)->ptr, ptr, len);
+ RSTRING(str)->ptr[len] = '\0';
}
else {
- MEMZERO(RSTRING(str)->ptr, char, len);
+ MEMZERO(RSTRING(str)->ptr, char, len+1);
}
- RSTRING(str)->ptr[len] = '\0';
return str;
}
@@ -218,28 +218,18 @@ rb_str_shared_replace(str, str2)
{
if (str == str2) return;
if (!FL_TEST(str, ELTS_SHARED)) free(RSTRING(str)->ptr);
- if (NIL_P(str2)) {
- RSTRING(str)->ptr = 0;
- RSTRING(str)->len = 0;
- RSTRING(str)->aux.capa = 0;
- return;
- }
+
RSTRING(str)->ptr = RSTRING(str2)->ptr;
RSTRING(str)->len = RSTRING(str2)->len;
- if (FL_TEST(str2, ELTS_SHARED|STR_ASSOC)) {
- FL_SET(str, RBASIC(str2)->flags & (ELTS_SHARED|STR_ASSOC));
- RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared;
- }
- else {
- RSTRING(str)->aux.capa = RSTRING(str2)->aux.capa;
- }
+ RSTRING(str)->aux.capa = RSTRING(str2)->aux.capa;
RSTRING(str2)->ptr = 0; /* abandon str2 */
RSTRING(str2)->len = 0;
RSTRING(str2)->aux.capa = 0;
- FL_UNSET(str, ELTS_SHARED|STR_ASSOC);
if (OBJ_TAINTED(str2)) OBJ_TAINT(str);
}
+void str_make_independent _((VALUE));
+
void
rb_str_associate(str, add)
VALUE str, add;
@@ -250,16 +240,12 @@ rb_str_associate(str, add)
}
else {
if (FL_TEST(str, ELTS_SHARED)) {
- rb_str_modify(str);
+ str_make_independent(str);
}
- else if (RSTRING(str)->aux.shared) {
- /* str_buf */
- if (RSTRING(str)->aux.capa != RSTRING(str)->len) {
- RESIZE_CAPA(str, RSTRING(str)->len);
- }
+ if (RSTRING(str)->aux.capa != RSTRING(str)->len) {
+ RESIZE_CAPA(str, RSTRING(str)->len);
}
RSTRING(str)->aux.shared = add;
- FL_UNSET(str, ELTS_SHARED);
FL_SET(str, STR_ASSOC);
}
}
@@ -398,30 +384,42 @@ rb_str_format(str, arg)
return rb_f_sprintf(2, argv);
}
-static int
-str_independent(str)
+void
+rb_str_modify_check(str)
VALUE str;
{
if (OBJ_FROZEN(str)) rb_error_frozen("string");
- if (!OBJ_TAINTED(str) && rb_safe_level() >= 4)
+ if (!OBJ_TAINTED(str) && rb_safe_level() >= 4) {
rb_raise(rb_eSecurityError, "Insecure: can't modify string");
+ }
+}
+
+int
+str_independent(str)
+ VALUE str;
+{
+ rb_str_modify_check(str);
if (!FL_TEST(str, ELTS_SHARED)) return 1;
return 0;
}
-static void
+void
str_make_independent(str)
VALUE str;
{
char *ptr;
+ long len = RSTRING(str)->len;
- ptr = ALLOC_N(char, RSTRING(str)->len+1);
+ ptr = ALLOC_N(char, len+1);
if (RSTRING(str)->ptr) {
- memcpy(ptr, RSTRING(str)->ptr, RSTRING(str)->len);
+ memcpy(ptr, RSTRING(str)->ptr, len);
+ ptr[len] = '\0';
+ }
+ else {
+ MEMZERO(ptr, char, len+1);
}
- ptr[RSTRING(str)->len] = 0;
RSTRING(str)->ptr = ptr;
- RSTRING(str)->aux.capa = RSTRING(str)->len;
+ RSTRING(str)->aux.capa = len;
FL_UNSET(str, ELTS_SHARED|STR_ASSOC);
}
@@ -532,10 +530,18 @@ rb_str_buf_cat(str, ptr, len)
{
long capa, total;
- if (FL_TEST(str, ELTS_SHARED)) {
- rb_str_modify(str);
+ if (len < 0) {
+ rb_raise(rb_eArgError, "negative string size (or size too big)");
+ }
+ if (len == 0) return str;
+ rb_str_modify(str);
+ if (FL_TEST(str, STR_ASSOC)) {
+ FL_UNSET(str, STR_ASSOC);
+ capa = RSTRING(str)->len;
}
- capa = RSTRING(str)->aux.capa;
+ else {
+ capa = RSTRING(str)->aux.capa;
+ }
total = RSTRING(str)->len+len;
if (capa <= total) {
while (total > capa) {
@@ -564,23 +570,7 @@ rb_str_cat(str, ptr, len)
const char *ptr;
long len;
{
- rb_str_modify(str);
- if (len > 0) {
- if (!FL_TEST(str, ELTS_SHARED) && !FL_TEST(str, STR_ASSOC)) {
- return rb_str_buf_cat(str, ptr, len);
- }
- RESIZE_CAPA(str, RSTRING(str)->len + len);
- if (ptr) {
- memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
- }
- else {
- MEMZERO(RSTRING(str)->ptr + RSTRING(str)->len, char, len);
- }
- RSTRING(str)->len += len;
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
- }
-
- return str;
+ return rb_str_buf_cat(str, ptr, len);
}
VALUE
@@ -597,12 +587,16 @@ rb_str_buf_append(str, str2)
{
long capa, len;
- if (FL_TEST(str, ELTS_SHARED)) {
- rb_str_modify(str);
+ rb_str_modify(str);
+ if (FL_TEST(str, STR_ASSOC)) {
+ FL_UNSET(str, STR_ASSOC);
+ capa = RSTRING(str)->len;
}
- capa = RSTRING(str)->aux.capa;
-
+ else {
+ capa = RSTRING(str)->aux.capa;
+ }
len = RSTRING(str)->len+RSTRING(str2)->len;
+
if (capa <= len) {
while (len > capa) {
capa = (capa + 1) * 2;
@@ -621,25 +615,11 @@ VALUE
rb_str_append(str, str2)
VALUE str, str2;
{
- long len;
-
StringValue(str2);
- rb_str_modify(str);
- if (RSTRING(str2)->len > 0) {
- len = RSTRING(str)->len+RSTRING(str2)->len;
- if (!FL_TEST(str, ELTS_SHARED) && !FL_TEST(str, STR_ASSOC)) {
- rb_str_buf_append(str, str2);
- OBJ_INFECT(str, str2);
- return str;
- }
- RESIZE_CAPA(str, len);
- memcpy(RSTRING(str)->ptr + RSTRING(str)->len,
- RSTRING(str2)->ptr, RSTRING(str2)->len);
- RSTRING(str)->len += RSTRING(str2)->len;
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
- }
- OBJ_INFECT(str, str2);
+ rb_str_buf_append(str, str2);
+
+ OBJ_INFECT(str, str2);
return str;
}
@@ -1599,6 +1579,7 @@ rb_str_gsub_bang(argc, argv, str)
VALUE *argv;
VALUE str;
{
+ rb_str_modify_check(str);
return str_gsub(argc, argv, str, 1);
}
@@ -1617,23 +1598,27 @@ rb_str_replace(str, str2)
{
if (str == str2) return str;
+ rb_str_modify_check(str);
StringValue(str2);
+
if (FL_TEST(str2, ELTS_SHARED)) {
- if (str_independent(str)) {
+ if (!FL_TEST(str, ELTS_SHARED)) {
free(RSTRING(str)->ptr);
}
RSTRING(str)->len = RSTRING(str2)->len;
RSTRING(str)->ptr = RSTRING(str2)->ptr;
- FL_SET(str, RBASIC(str2)->flags & (ELTS_SHARED|STR_ASSOC));
RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared;
+ FL_SET(str, ELTS_SHARED);
}
else {
- rb_str_modify(str);
+ if (FL_TEST(str, ELTS_SHARED)) {
+ str_make_independent(str);
+ }
rb_str_resize(str, RSTRING(str2)->len);
memcpy(RSTRING(str)->ptr, RSTRING(str2)->ptr, RSTRING(str2)->len);
if (FL_TEST(str2, STR_ASSOC)) {
- FL_SET(str, RBASIC(str2)->flags & (ELTS_SHARED|STR_ASSOC));
RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared;
+ FL_SET(str, STR_ASSOC);
}
}
@@ -2293,6 +2278,7 @@ rb_str_delete_bang(argc, argv, str)
if (argc < 1) {
rb_raise(rb_eArgError, "wrong number of arguments");
}
+ rb_str_modify(str);
for (i=0; i<argc; i++) {
VALUE s = argv[i];
@@ -2300,8 +2286,6 @@ rb_str_delete_bang(argc, argv, str)
tr_setup_table(s, squeez, init);
init = 0;
}
-
- rb_str_modify(str);
s = t = RSTRING(str)->ptr;
if (!s || RSTRING(str)->len == 0) return Qnil;
send = s + RSTRING(str)->len;
@@ -2342,6 +2326,7 @@ rb_str_squeeze_bang(argc, argv, str)
int init = 1;
int i;
+ rb_str_modify(str);
if (argc == 0) {
for (i=0; i<256; i++) {
squeez[i] = 1;
@@ -2356,8 +2341,6 @@ rb_str_squeeze_bang(argc, argv, str)
init = 0;
}
}
-
- rb_str_modify(str);
s = t = RSTRING(str)->ptr;
if (!s || RSTRING(str)->len == 0) return Qnil;
send = s + RSTRING(str)->len;
--
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Michal Rokos Czech Technical University, Prague
E-mail:m.rokos@sh.cvut.cz ICQ:36118339 Jabber:majkl@jabber.cz
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-