diff options
| author | Yukihiro Matsumoto <[email protected]> | 2012-05-31 19:16:48 +0900 |
|---|---|---|
| committer | Yukihiro Matsumoto <[email protected]> | 2012-05-31 19:16:48 +0900 |
| commit | 326fc888e4d1a3a9b0f1dcbad13094cf8f4fe1e3 (patch) | |
| tree | 8172380c8de91059bacc5142f64560d9ddb686c5 | |
| parent | 71a480fb536f8a3d67550a6d5f23151332eb48e8 (diff) | |
| download | mruby-326fc888e4d1a3a9b0f1dcbad13094cf8f4fe1e3.tar.gz mruby-326fc888e4d1a3a9b0f1dcbad13094cf8f4fe1e3.zip | |
allow string shared body
| -rw-r--r-- | include/mruby/string.h | 8 | ||||
| -rw-r--r-- | src/gc.c | 5 | ||||
| -rw-r--r-- | src/string.c | 101 |
3 files changed, 72 insertions, 42 deletions
diff --git a/include/mruby/string.h b/include/mruby/string.h index fca28cf72..df1305a79 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -30,7 +30,10 @@ extern const char mrb_digitmap[]; struct RString { MRUBY_OBJECT_HEADER; int len; - int capa; + union { + int capa; + struct RString *shared; + } aux; char *buf; }; @@ -38,7 +41,7 @@ struct RString { #define RSTRING(s) ((struct RString*)((s).value.p)) #define RSTRING_PTR(s) (RSTRING(s)->buf) #define RSTRING_LEN(s) (RSTRING(s)->len) -#define RSTRING_CAPA(s) (RSTRING(s)->capa) +#define RSTRING_CAPA(s) (RSTRING(s)->aux.capa) #define RSTRING_END(s) (RSTRING(s)->buf + RSTRING(s)->len) #define MRB_STR_SHARED 256 @@ -64,7 +67,6 @@ mrb_value str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr); char *mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr); -mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, long beg, long len); size_t mrb_str_sublen(mrb_state *mrb, mrb_value str, long pos); mrb_value mrb_str_size(mrb_state *mrb, mrb_value self); long mrb_str_offset(mrb_state *mrb, mrb_value str, long pos); @@ -360,14 +360,11 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj) case MRB_TT_STRING: { -#if 0 struct RString *s = (struct RString*)obj; while (s->flags & MRB_STR_SHARED) { - s = s->aux.shared; - if (!s) break; + mrb_gc_mark(mrb, (struct RBasic*)s->aux.shared); } -#endif } break; diff --git a/src/string.c b/src/string.c index a42565084..dc6dcfafe 100644 --- a/src/string.c +++ b/src/string.c @@ -36,6 +36,7 @@ const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; static mrb_value get_pat(mrb_state *mrb, mrb_value pat, mrb_int quote); #endif //INCLUDE_REGEXP static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2); +static mrb_value 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);\ @@ -50,11 +51,35 @@ static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString RSTRING(str)->len--;\ } while (0) +static void +str_modify(mrb_state *mrb, mrb_value str) +{ + struct RString *s = mrb_str_ptr(str); + + if (MRB_STR_SHARED_P(str)) { + char *ptr, *p; + long len; + + p = s->buf; + len = s->len; + ptr = mrb_malloc(mrb, sizeof(char)*(len+1)); + if (p) { + memcpy(ptr, p, len); + } + ptr[len] = 0; + s->buf = ptr; + s->len = len; + s->aux.capa = len; + MRB_STR_UNSET_NOCAPA(str); + } +} + mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, size_t len) { size_t slen; + str_modify(mrb, str); slen = RSTRING_LEN(str); if (len != slen) { if (slen < len || slen -len > 1024) { @@ -104,7 +129,7 @@ str_alloc(mrb_state *mrb) s->buf = 0; s->len = 0; - s->capa = 0; + s->aux.capa = 0; return mrb_obj_value(s); } @@ -126,11 +151,10 @@ str_dup(mrb_state *mrb, mrb_value str) } static mrb_value -str_new(mrb_state *mrb, enum mrb_vtype ttype, const char *p, size_t len) +str_new(mrb_state *mrb, const char *p, size_t len) { mrb_value str; - //str = str_alloc(mrb); str = mrb_str_buf_new(mrb, len); if (p) { memcpy(RSTRING_PTR(str), p, len); @@ -143,7 +167,10 @@ str_new(mrb_state *mrb, enum mrb_vtype ttype, const char *p, size_t len) static mrb_value mrb_str_new_with_class(mrb_state *mrb, mrb_value obj, const char *ptr, long len) { - return str_new(mrb, mrb_type(obj), ptr, len); + mrb_value str2 = str_new(mrb, ptr, len); + + mrb_str_ptr(str2)->c = mrb_str_ptr(obj)->c; + return str2; } static mrb_value @@ -163,7 +190,7 @@ mrb_str_buf_new(mrb_state *mrb, size_t capa) capa = STR_BUF_MIN_SIZE; } s->len = 0; - s->capa = capa; + s->aux.capa = capa; s->buf = mrb_malloc(mrb, capa+1); s->buf[0] = '\0'; @@ -175,6 +202,7 @@ str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len) { long capa, total, off = -1; + str_modify(mrb, str); if (ptr >= RSTRING_PTR(str) && ptr <= RSTRING_END(str)) { off = ptr - RSTRING_PTR(str); } @@ -232,7 +260,7 @@ mrb_str_new(mrb_state *mrb, const char *p, size_t len) memcpy(s->buf, p, len); } s->len = len; - s->capa = len; + s->aux.capa = len; s->buf[len] ='\0'; return mrb_obj_value(s); } @@ -265,7 +293,7 @@ mrb_str_new_cstr(mrb_state *mrb, const char *p) memcpy(s->buf, p, len); s->buf[len] = 0; s->len = len; - s->capa = len; + s->aux.capa = len; return mrb_obj_value(s); } @@ -318,8 +346,8 @@ mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other) s2 = mrb_str_ptr(other); len = s1->len + s2->len; - if (s1->capa < len) { - s1->capa = len; + if (s1->aux.capa < len) { + s1->aux.capa = len; s1->buf = mrb_realloc(mrb, s1->buf, len+1); } memcpy(s1->buf+s1->len, s2->buf, s2->len); @@ -702,7 +730,7 @@ mrb_str_dup(mrb_state *mrb, mrb_value str) dup->buf[s->len] = 0; } dup->len = s->len; - dup->capa = s->len; + dup->aux.capa = s->len; return mrb_obj_value(dup); } @@ -746,7 +774,7 @@ num_index: case 2/*OTHER*/: return mrb_nil_value(); default: - tmp = mrb_str_subseq(mrb, str, beg, len); + tmp = str_subseq(mrb, str, beg, len); return tmp; } } @@ -847,6 +875,7 @@ mrb_str_capitalize_bang(mrb_state *mrb, mrb_value str) char *s, *send; int modify = 0; + 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)) { @@ -901,6 +930,7 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) char *p, *pp; long len, rslen; + str_modify(mrb, str); len = RSTRING_LEN(str); if (mrb_get_args(mrb, "|S", &rs) == 0) { if (len == 0) return mrb_nil_value(); @@ -996,6 +1026,7 @@ 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) { size_t len; len = RSTRING_LEN(str) - 1; @@ -1052,6 +1083,7 @@ mrb_str_downcase_bang(mrb_state *mrb, mrb_value str) char *s, *send; int modify = 0; + str_modify(mrb, str); s = RSTRING_PTR(str); send = RSTRING_END(str); while (s < send) { @@ -1171,12 +1203,20 @@ mrb_str_new_frozen(mrb_state *mrb, mrb_value orig) return str_dup(mrb, orig); } -mrb_value -mrb_str_subseq(mrb_state *mrb, mrb_value str, long beg, long len) +static mrb_value +str_subseq(mrb_state *mrb, mrb_value str, long beg, long len) { mrb_value str2; + struct RString *orig, *s; + + str2 = mrb_str_new_with_class(mrb, str, 0, 0); + orig = mrb_str_ptr(str); + s = mrb_str_ptr(str2); + s->buf = orig->buf + beg; + s->len = len; + s->aux.shared = orig; + s->flags |= MRB_STR_SHARED; - str2 = mrb_str_new_with_class(mrb, str, RSTRING_PTR(str)+beg, len); return str2; } @@ -1184,7 +1224,6 @@ mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, int len) { mrb_value str2; - char *p, *s = RSTRING_PTR(str); if (len < 0) return mrb_nil_value(); if (!RSTRING_LEN(str)) { @@ -1199,19 +1238,8 @@ mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, int len) len = RSTRING_LEN(str) - beg; if (len <= 0) { len = 0; - p = 0; - } - else - p = s + beg; - - if (len > STR_BUF_MIN_SIZE && beg + len == RSTRING_LEN(str)) { - str2 = mrb_str_new(mrb, s, RSTRING_LEN(str)); - RSTRING(str2)->buf += RSTRING(str2)->len - len; - RSTRING(str2)->len = len; - } - else { - str2 = mrb_str_new_with_class(mrb, str, p, len); } + str2 = str_subseq(mrb, str, beg, len); return str2; } @@ -1365,7 +1393,7 @@ mrb_str_gsub(mrb_state *mrb, mrb_value self) static mrb_value mrb_str_gsub_bang(mrb_state *mrb, mrb_value self) { - //return str_gsub(argc, argv, self, 1); + str_modify(mrb, self); return str_gsub(mrb, self, 1); } #endif //INCLUDE_REGEXP @@ -1541,7 +1569,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2) s1->buf = mrb_realloc(mrb, s1->buf, len); memcpy(s1->buf, s2->buf, len); s1->len = s2->len; - s2->capa = s2->len; + s2->aux.capa = s2->len; return mrb_obj_value(s1); } @@ -1745,6 +1773,7 @@ mrb_str_reverse_bang(mrb_state *mrb, mrb_value str) char *s, *e; char c; + str_modify(mrb, str); if (RSTRING(str)->len > 1) { s = RSTRING(str)->buf; e = s + RSTRING(str)->len - 1; @@ -2092,7 +2121,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) { mrb_value *argv; int argc; - mrb_value spat; + mrb_value spat = mrb_nil_value(); mrb_value limit; enum {awk, string, regexp} split_type = string; long beg, end, i = 0; @@ -2173,7 +2202,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) } } else if (ascii_isspace(c)) { - mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, beg, end-beg)); + mrb_ary_push(mrb, result, str_subseq(mrb, str, beg, end-beg)); skip = 1; beg = ptr - bptr; if (!mrb_nil_p(limit)) ++i; @@ -2200,7 +2229,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) break; } else if (last_null == 1) { - mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, beg, len)); + mrb_ary_push(mrb, result, str_subseq(mrb, str, beg, len)); beg = start; } else { @@ -2213,7 +2242,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) } } else { - mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, beg, end-beg)); + mrb_ary_push(mrb, result, str_subseq(mrb, str, beg, end-beg)); beg = start = END(0); } last_null = 0; @@ -2223,7 +2252,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) if (BEG(idx) == END(idx)) tmp = str_new_empty(mrb, str); else - tmp = mrb_str_subseq(mrb, str, BEG(idx), END(idx)-BEG(idx)); + tmp = str_subseq(mrb, str, BEG(idx), END(idx)-BEG(idx)); mrb_ary_push(mrb, result, tmp); } if (!mrb_nil_p(limit) && lim <= ++i) break; @@ -2236,7 +2265,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) if (RSTRING_LEN(str) == beg) tmp = str_new_empty(mrb, str); else - tmp = mrb_str_subseq(mrb, str, beg, RSTRING_LEN(str)-beg); + tmp = str_subseq(mrb, str, beg, RSTRING_LEN(str)-beg); mrb_ary_push(mrb, result, tmp); } if (mrb_nil_p(limit) && lim == 0) { @@ -2272,6 +2301,7 @@ mrb_block_given_p() static mrb_value mrb_str_sub_bang(mrb_state *mrb, mrb_value str) { + str_modify(mrb, str); return mrb_nil_value(); } #endif //INCLUDE_REGEXP @@ -2705,6 +2735,7 @@ mrb_str_upcase_bang(mrb_state *mrb, mrb_value str) char *s, *send; int modify = 0; + str_modify(mrb, str); s = RSTRING_PTR(str); send = RSTRING_END(str); while (s < send) { |
