Re: [Clenup, fixes] ruby.h, string.c
From:
Michal Rokos <m.rokos@...>
Date:
2002-09-09 09:03:02 UTC
List:
ruby-core #456
Hi,
this version really works. (Sorry, I wanted to send it even if
it's not working, because I have no computer at home and was
friday...)
Michal
--- ../ruby-09-06/string.c Fri Sep 6 20:55:37 2002
+++ string.c Sat Sep 7 11:04:56 2002
@@ -27,7 +27,7 @@
VALUE rb_cString;
-#define STR_ASSOC FL_USER3
+#define STR_ASSOC FL_USER3
#define RESIZE_CAPA(str,capacity) do {\
REALLOC_N(RSTRING(str)->ptr, char, (capacity)+1);\
@@ -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;
}
@@ -212,12 +212,14 @@ rb_str_to_str(str)
return rb_convert_type(str, T_STRING, "String", "to_str");
}
+int str_independent _((VALUE));
+
static void
rb_str_shared_replace(str, str2)
VALUE str, str2;
{
if (str == str2) return;
- if (!FL_TEST(str, ELTS_SHARED)) free(RSTRING(str)->ptr);
+ if (str_independent(str)) free(RSTRING(str)->ptr);
if (NIL_P(str2)) {
RSTRING(str)->ptr = 0;
RSTRING(str)->len = 0;
@@ -236,7 +238,7 @@ rb_str_shared_replace(str, str2)
RSTRING(str2)->ptr = 0; /* abandon str2 */
RSTRING(str2)->len = 0;
RSTRING(str2)->aux.capa = 0;
- FL_UNSET(str, ELTS_SHARED|STR_ASSOC);
+ FL_UNSET(str2, ELTS_SHARED|STR_ASSOC);
if (OBJ_TAINTED(str2)) OBJ_TAINT(str);
}
@@ -249,17 +251,11 @@ rb_str_associate(str, add)
rb_ary_concat(RSTRING(str)->aux.shared, add);
}
else {
- if (FL_TEST(str, ELTS_SHARED)) {
- rb_str_modify(str);
- }
- else if (RSTRING(str)->aux.shared) {
- /* str_buf */
- if (RSTRING(str)->aux.capa != RSTRING(str)->len) {
- RESIZE_CAPA(str, RSTRING(str)->len);
- }
+ rb_str_modify(str);
+ 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,13 +394,21 @@ 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;
}
@@ -414,14 +418,18 @@ 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);
}
@@ -429,8 +437,9 @@ void
rb_str_modify(str)
VALUE str;
{
- if (!str_independent(str))
+ if (!str_independent(str)) {
str_make_independent(str);
+ }
}
VALUE
@@ -493,10 +502,6 @@ VALUE
rb_str_dup_frozen(str)
VALUE str;
{
- if (FL_TEST(str, ELTS_SHARED)) {
- OBJ_FREEZE(RSTRING(str)->aux.shared);
- return RSTRING(str)->aux.shared;
- }
if (OBJ_FROZEN(str)) return str;
str = rb_str_dup(str);
OBJ_FREEZE(str);
@@ -511,15 +516,17 @@ rb_str_resize(str, len)
if (len < 0) {
rb_raise(rb_eArgError, "negative string size (or size too big)");
}
-
+ rb_str_modify(str);
+
if (len != RSTRING(str)->len) {
- rb_str_modify(str);
-
if (RSTRING(str)->len < len || RSTRING(str)->len - len > 1024) {
- RESIZE_CAPA(str, len);
+ REALLOC_N(RSTRING(str)->ptr, char, len+1);
+ if (!FL_TEST(str, STR_ASSOC)) {
+ RSTRING(str)->aux.capa = len;
+ }
}
- RSTRING(str)->len = len;
RSTRING(str)->ptr[len] = '\0'; /* sentinel */
+ RSTRING(str)->len = len;
}
return str;
}
@@ -532,8 +539,14 @@ 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)) {
+ rb_bug("String with ASSOC in rb_str_buf_cat!");
}
capa = RSTRING(str)->aux.capa;
total = RSTRING(str)->len+len;
@@ -544,8 +557,8 @@ rb_str_buf_cat(str, ptr, len)
RESIZE_CAPA(str, capa);
}
memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
- RSTRING(str)->len = total;
RSTRING(str)->ptr[total] = '\0'; /* sentinel */
+ RSTRING(str)->len = total;
return str;
}
@@ -564,23 +577,27 @@ rb_str_cat(str, ptr, len)
const char *ptr;
long len;
{
+ if (len < 0) {
+ rb_raise(rb_eArgError, "negative string size (or size too big)");
+ }
+ if (len == 0) {
+ return str;
+ }
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 (FL_TEST(str, STR_ASSOC)) {
+ REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len+len+1);
if (ptr) {
memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
+ RSTRING(str)->ptr[RSTRING(str)->len + len] = '\0'; /* sentinel */
}
else {
- MEMZERO(RSTRING(str)->ptr + RSTRING(str)->len, char, len);
+ MEMZERO(RSTRING(str)->ptr + RSTRING(str)->len, char, len+1);
}
RSTRING(str)->len += len;
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
+ return str;
}
-
- return str;
+ return rb_str_buf_cat(str, ptr, len);
}
VALUE
@@ -597,12 +614,14 @@ 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)) {
+ rb_bug("String with ASSOC in rb_str_buf_append!");
}
capa = RSTRING(str)->aux.capa;
-
len = RSTRING(str)->len+RSTRING(str2)->len;
+
if (capa <= len) {
while (len > capa) {
capa = (capa + 1) * 2;
@@ -623,23 +642,23 @@ rb_str_append(str, str2)
{
long len;
- StringValue(str2);
rb_str_modify(str);
+ StringValue(str2);
+
if (RSTRING(str2)->len > 0) {
len = RSTRING(str)->len+RSTRING(str2)->len;
- if (!FL_TEST(str, ELTS_SHARED) && !FL_TEST(str, STR_ASSOC)) {
+ if (FL_TEST(str, STR_ASSOC)) {
+ REALLOC_N(RSTRING(str)->ptr, char, len+1);
+ memcpy(RSTRING(str)->ptr + RSTRING(str)->len,
+ RSTRING(str2)->ptr, RSTRING(str2)->len);
+ RSTRING(str)->ptr[len] = '\0'; /* sentinel */
+ RSTRING(str)->len = len;
+ }
+ else {
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);
-
return str;
}
@@ -1599,6 +1618,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 +1637,24 @@ 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)) {
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);
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 +2314,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 +2322,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 +2362,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 +2377,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
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-