From: Michal Rokos Date: 2002-09-09T18:03:02+09:00 Subject: Re: [Clenup, fixes] ruby.h, string.c 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; iptr; 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 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-