From b2d0f22dee87651bca4e16e287cab61dc303db19 Mon Sep 17 00:00:00 2001 From: Yukihiro Matsumoto Date: Sat, 2 Jun 2012 04:12:23 +0900 Subject: ensure str_modify is called at the beginning of modifying methods --- src/string.c | 217 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 110 insertions(+), 107 deletions(-) (limited to 'src/string.c') diff --git a/src/string.c b/src/string.c index 044083848..26ed7b052 100644 --- a/src/string.c +++ b/src/string.c @@ -38,25 +38,15 @@ static mrb_value get_pat(mrb_state *mrb, mrb_value pat, mrb_int quote); static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2); static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, long beg, long len); -#define RESIZE_CAPA(str,capacity) do {\ - RSTRING(str)->buf = mrb_realloc(mrb, RSTRING(str)->buf, (capacity)+1);\ - RSTRING_CAPA(str) = capacity;\ -} while (0) - -#define STR_SET_LEN(str, n) do { \ - RSTRING(str)->len = (n);\ -} while (0) - -#define STR_DEC_LEN(str) do {\ - RSTRING(str)->len--;\ +#define RESIZE_CAPA(s,capacity) do {\ + s->buf = mrb_realloc(mrb, s->buf, (capacity)+1);\ + s->aux.capa = capacity;\ } while (0) static void -str_modify(mrb_state *mrb, mrb_value str) +str_modify(mrb_state *mrb, struct RString *s) { - struct RString *s = mrb_str_ptr(str); - - if (MRB_STR_SHARED_P(str)) { + if (s->flags & MRB_STR_SHARED) { char *ptr, *p; long len; @@ -70,7 +60,7 @@ str_modify(mrb_state *mrb, mrb_value str) s->buf = ptr; s->len = len; s->aux.capa = len; - MRB_STR_UNSET_NOCAPA(str); + s->flags &= ~MRB_STR_SHARED; } } @@ -78,18 +68,19 @@ mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, int len) { int slen; + struct RString *s = mrb_str_ptr(str); - str_modify(mrb, str); - slen = RSTRING_LEN(str); + str_modify(mrb, s); + slen = s->len; if (len != slen) { if (slen < len || slen -len > 1024) { - RSTRING_PTR(str) = mrb_realloc(mrb, RSTRING_PTR(str), len+1); + s->buf = mrb_realloc(mrb, s->buf, len+1); } - if (!MRB_STR_NOCAPA_P(str)) { - RSTRING_CAPA(str) = len; + if (!(s->flags & MRB_STR_SHARED)) { + s->aux.capa = len; } - RSTRING(str)->len = len; - RSTRING(str)->buf[len] = '\0'; /* sentinel */ + s->len = len; + s->buf[len] = '\0'; /* sentinel */ } return str; } @@ -176,21 +167,21 @@ mrb_str_buf_new(mrb_state *mrb, int capa) return mrb_obj_value(s); } -mrb_value -str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, int len) +static void +str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len) { long capa, total, off = -1; - str_modify(mrb, str); - if (ptr >= RSTRING_PTR(str) && ptr <= RSTRING_END(str)) { - off = ptr - RSTRING_PTR(str); + str_modify(mrb, s); + if (ptr >= s->buf && ptr <= s->buf + s->len) { + off = ptr - s->buf; } - if (len == 0) return mrb_fixnum_value(0); - capa = RSTRING_CAPA(str); - if (RSTRING_LEN(str) >= LONG_MAX - len) { + if (len == 0) return; + capa = s->aux.capa; + if (s->len >= LONG_MAX - len) { mrb_raise(mrb, E_ARGUMENT_ERROR, "string sizes too big"); } - total = RSTRING_LEN(str)+len; + total = s->len+len; if (capa <= total) { while (total > capa) { if (capa + 1 >= LONG_MAX / 2) { @@ -199,23 +190,22 @@ str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, int len) } capa = (capa + 1) * 2; } - RESIZE_CAPA(str, capa); + RESIZE_CAPA(s, capa); } if (off != -1) { - ptr = RSTRING_PTR(str) + off; + ptr = s->buf + off; } - memcpy(RSTRING_PTR(str) + RSTRING_LEN(str), ptr, len); - STR_SET_LEN(str, total); - RSTRING_PTR(str)[total] = '\0'; /* sentinel */ - - return str; + memcpy(s->buf + s->len, ptr, len); + s->len = total; + s->buf[total] = '\0'; /* sentinel */ } mrb_value mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, int len) { if (len == 0) return str; - return str_buf_cat(mrb, str, ptr, len); + str_buf_cat(mrb, mrb_str_ptr(str), ptr, len); + return str; } mrb_value @@ -337,7 +327,7 @@ mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other) struct RString *s1 = mrb_str_ptr(self), *s2; int len; - str_modify(mrb, self); + str_modify(mrb, s1); if (mrb_type(other) != MRB_TT_STRING) { other = mrb_str_to_str(mrb, other); } @@ -863,19 +853,20 @@ mrb_str_aref_m(mrb_state *mrb, mrb_value str) static mrb_value mrb_str_capitalize_bang(mrb_state *mrb, mrb_value str) { - char *s, *send; + char *p, *pend; int modify = 0; + struct RString *s = mrb_str_ptr(str); - str_modify(mrb, str); - if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return mrb_nil_value(); - s = RSTRING_PTR(str); send = RSTRING_END(str); - if (ISLOWER(*s)) { - *s = toupper(*s); + str_modify(mrb, s); + if (s->len == 0 || !s->buf) return mrb_nil_value(); + p = s->buf; pend = s->buf + s->len; + if (ISLOWER(*p)) { + *p = toupper(*p); modify = 1; } - while (++s < send) { - if (ISUPPER(*s)) { - *s = tolower(*s); + while (++p < pend) { + if (ISUPPER(*p)) { + *p = tolower(*p); modify = 1; } } @@ -920,21 +911,22 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) mrb_int newline; char *p, *pp; long len, rslen; + struct RString *s = mrb_str_ptr(str); - str_modify(mrb, str); - len = RSTRING_LEN(str); + str_modify(mrb, s); + len = s->len; if (mrb_get_args(mrb, "|S", &rs) == 0) { if (len == 0) return mrb_nil_value(); smart_chomp: - if (RSTRING_PTR(str)[len-1] == '\n') { - STR_DEC_LEN(str); - if (RSTRING_LEN(str) > 0 && - RSTRING_PTR(str)[RSTRING_LEN(str)-1] == '\r') { - STR_DEC_LEN(str); + if (s->buf[len-1] == '\n') { + s->len--; + if (s->len > 0 && + s->buf[s->len-1] == '\r') { + s->len--; } } - else if (RSTRING_PTR(str)[len-1] == '\r') { - STR_DEC_LEN(str); + else if (s->buf[len-1] == '\r') { + s->len--; } else { return mrb_nil_value(); @@ -943,7 +935,7 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) } if (len == 0 || mrb_nil_p(rs)) return mrb_nil_value(); - p = RSTRING_PTR(str); + p = s->buf; rslen = RSTRING_LEN(rs); if (rslen == 0) { while (len>0 && p[len-1] == '\n') { @@ -951,8 +943,8 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) if (len>0 && p[len-1] == '\r') len--; } - if (len < RSTRING_LEN(str)) { - STR_SET_LEN(str, len); + if (len < s->len) { + s->len = len; p[len] = '\0'; return str; } @@ -969,7 +961,7 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) if (p[len-1] == newline && (rslen <= 1 || memcmp(RSTRING_PTR(rs), pp, rslen) == 0)) { - STR_SET_LEN(str, len - rslen); + s->len = len - rslen; p[len] = '\0'; return str; } @@ -1017,18 +1009,20 @@ mrb_str_chomp(mrb_state *mrb, mrb_value self) static mrb_value mrb_str_chop_bang(mrb_state *mrb, mrb_value str) { - str_modify(mrb, str); - if (RSTRING_LEN(str) > 0) { + struct RString *s = mrb_str_ptr(str); + + str_modify(mrb, s); + if (s->len > 0) { int len; - len = RSTRING_LEN(str) - 1; - if (RSTRING_PTR(str)[len] == '\n') { + len = s->len - 1; + if (s->buf[len] == '\n') { if (len > 0 && - RSTRING_PTR(str)[len-1] == '\r') { + s->buf[len-1] == '\r') { len--; } } - STR_SET_LEN(str, len); - RSTRING_PTR(str)[len] = '\0'; + s->len = len; + s->buf[len] = '\0'; return str; } return mrb_nil_value(); @@ -1071,18 +1065,19 @@ mrb_str_chop(mrb_state *mrb, mrb_value self) static mrb_value mrb_str_downcase_bang(mrb_state *mrb, mrb_value str) { - char *s, *send; + char *p, *pend; int modify = 0; + struct RString *s = mrb_str_ptr(str); - str_modify(mrb, str); - s = RSTRING_PTR(str); - send = RSTRING_END(str); - while (s < send) { - if (ISUPPER(*s)) { - *s = tolower(*s); + str_modify(mrb, s); + p = s->buf; + pend = s->buf + s->len; + while (p < pend) { + if (ISUPPER(*p)) { + *p = tolower(*p); modify = 1; } - s++; + p++; } if (modify) return str; @@ -1244,6 +1239,7 @@ str_gsub(mrb_state *mrb, mrb_value str, mrb_int bang) mrb_int offset, blen, len, last; char *sp, *cp; + if (bang) str_modify(mrb, mrb_str_ptr(self)); mrb_get_args(mrb, "*", &argv, &argc); switch (argc) { case 1: @@ -1362,8 +1358,10 @@ mrb_str_gsub(mrb_state *mrb, mrb_value self) static mrb_value mrb_str_gsub_bang(mrb_state *mrb, mrb_value self) { - str_modify(mrb, self); - return str_gsub(mrb, self, 1); + striuct RString *s = mrb_str_ptr(self); + + str_modify(mrb, s); + return str_gsub(mrb, s, 1); } #endif //INCLUDE_REGEXP @@ -1535,6 +1533,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2) { int len = s2->len; + str_modify(mrb, s1); s1->buf = mrb_realloc(mrb, s1->buf, len); memcpy(s1->buf, s2->buf, len); s1->len = s2->len; @@ -1740,16 +1739,17 @@ mrb_str_reverse(mrb_state *mrb, mrb_value str) static mrb_value mrb_str_reverse_bang(mrb_state *mrb, mrb_value str) { - char *s, *e; + struct RString *s = mrb_str_ptr(str); + char *p, *e; char c; - str_modify(mrb, str); - if (RSTRING(str)->len > 1) { - s = RSTRING(str)->buf; - e = s + RSTRING(str)->len - 1; - while (s < e) { - c = *s; - *s++ = *e; + str_modify(mrb, s); + if (s->len > 1) { + p = s->buf; + e = p + s->len - 1; + while (p < e) { + c = *p; + *p++ = *e; *e-- = c; } } @@ -2702,18 +2702,19 @@ mrb_str_to_s(mrb_state *mrb, mrb_value self) static mrb_value mrb_str_upcase_bang(mrb_state *mrb, mrb_value str) { - char *s, *send; + struct RString *s = mrb_str_ptr(str); + char *p, *pend; int modify = 0; - str_modify(mrb, str); - s = RSTRING_PTR(str); - send = RSTRING_END(str); - while (s < send) { - if (ISLOWER(*s)) { - *s = toupper(*s); + str_modify(mrb, s); + p = RSTRING_PTR(str); + pend = RSTRING_END(str); + while (p < pend) { + if (ISLOWER(*p)) { + *p = toupper(*p); modify = 1; } - s++; + p++; } if (modify) return str; @@ -2848,18 +2849,20 @@ mrb_str_dump(mrb_state *mrb, mrb_value str) mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, long len) { - if (len < 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "negative string size (or size too big)"); - } - if (0/*STR_ASSOC_P(str)*/) { - mrb_realloc(mrb, RSTRING(str)->buf, RSTRING(str)->len+len+1); - memcpy(RSTRING(str)->buf + RSTRING(str)->len, ptr, len); - RSTRING(str)->len += len; - RSTRING(str)->buf[RSTRING(str)->len] = '\0'; /* sentinel */ - return str; - } + struct RString *s = mrb_str_ptr(str); - return str_buf_cat(mrb, str, ptr, len); + if (len < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "negative string size (or size too big)"); + } + if (0/*STR_ASSOC_P(str)*/) { + mrb_realloc(mrb, s->buf, s->len+len+1); + memcpy(s->buf + s->len, ptr, len); + s->len += len; + s->buf[s->len] = '\0'; /* sentinel */ + return str; + } + str_buf_cat(mrb, s, ptr, len); + return str; } mrb_value -- cgit v1.2.3