summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro Matsumoto <[email protected]>2012-06-03 22:59:40 +0900
committerYukihiro Matsumoto <[email protected]>2012-06-03 22:59:40 +0900
commit3be1c8890774c04d65bbed87914e9453d1496eed (patch)
treef4c5a74cfce4d9650aa92e1289ddfcbc4903746d
parente66587439a0b2026ad56ba3548245a6d25d62b67 (diff)
downloadmruby-3be1c8890774c04d65bbed87914e9453d1496eed.tar.gz
mruby-3be1c8890774c04d65bbed87914e9453d1496eed.zip
str_modify() revives string buffer kept in shared structure if refcnt == 1
-rw-r--r--src/string.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/src/string.c b/src/string.c
index d7749c27b..d09d8942b 100644
--- a/src/string.c
+++ b/src/string.c
@@ -57,23 +57,29 @@ static void
str_modify(mrb_state *mrb, struct RString *s)
{
if (s->flags & MRB_STR_SHARED) {
- char *ptr, *p;
- long len;
struct mrb_shared_string *shared = s->aux.shared;
- p = s->buf;
- len = s->len;
- ptr = mrb_malloc(mrb, sizeof(char)*(len+1));
- if (p) {
- memcpy(ptr, p, len);
+ if (shared->refcnt == 1 && s->buf == shared->buf) {
+ s->buf = shared->buf;
+ s->aux.capa = shared->len;
+ mrb_free(mrb, shared);
+ }
+ else {
+ char *ptr, *p;
+ long len;
+
+ p = s->buf;
+ len = s->len;
+ ptr = mrb_malloc(mrb, len+1);
+ if (p) {
+ memcpy(ptr, p, len);
+ }
+ ptr[len] = 0;
+ s->buf = ptr;
+ s->aux.capa = len;
+ mrb_str_decref(mrb, shared);
}
- ptr[len] = 0;
- s->buf = ptr;
- s->len = len;
- s->aux.capa = len;
s->flags &= ~MRB_STR_SHARED;
-
- mrb_str_decref(mrb, shared);
}
}