diff --git a/src/lgc.c b/src/lgc.c index e14a3d2..305347b 100644 --- a/src/lgc.c +++ b/src/lgc.c @@ -287,6 +287,7 @@ static void traverserope (global_State *g, TRope *r) { if (r->tsr.right->tsr.tt == LUA_TSTRING) stringmark(cast(TString *, r->tsr.right)); else markobject(g, r->tsr.right); } + if (r->tsr.res) stringmark(r->tsr.res); } diff --git a/src/lobject.h b/src/lobject.h index 32ec197..c8ffe43 100644 --- a/src/lobject.h +++ b/src/lobject.h @@ -250,6 +250,7 @@ typedef union TRope { union TRope * left; union TRope * right; size_t len; + TString *res; } tsr; } TRope; diff --git a/src/lstring.c b/src/lstring.c index 594c398..4287ef3 100644 --- a/src/lstring.c +++ b/src/lstring.c @@ -117,6 +117,7 @@ TRope *luaS_concat (lua_State *L, TRope *l, TRope *r) { rope->tsr.right = r; rope->tsr.len = (l->tsr.tt == LUA_TSTRING ? cast(TString *, l)->tsv.len : (l->tsr.tt == LUA_TSUBSTR ? cast(TSubString *, l)->tss.len : l->tsr.len)) + (r->tsr.tt == LUA_TSTRING ? cast(TString *, r)->tsv.len : (r->tsr.tt == LUA_TSUBSTR ? cast(TSubString *, r)->tss.len : r->tsr.len)); + rope->tsr.res = NULL; return rope; } @@ -125,6 +126,7 @@ TString *luaS_build (lua_State *L, TRope *rope) { TString *s; TRope **stack; if (rope->tsr.tt == LUA_TSTRING || rope->tsr.tt == LUA_TSUBSTR) return cast(TString *, rope); + if (rope->tsr.res) return rope->tsr.res; buffer = cur = luaZ_openspace(L, &G(L)->buff, rope->tsr.len); stack = G(L)->ropestack; do { @@ -161,6 +163,7 @@ TString *luaS_build (lua_State *L, TRope *rope) { rope = rope->tsr.right; } while (stack >= G(L)->ropestack); s = luaS_newlstr(L, buffer, cur - buffer); + rope->tsr.res = s; return s; } diff --git a/src/lstrlib.c b/src/lstrlib.c index e20d2e3..4b13f9a 100644 --- a/src/lstrlib.c +++ b/src/lstrlib.c @@ -105,13 +105,18 @@ static int str_upper (lua_State *L) { static int str_rep (lua_State *L) { size_t l; - luaL_Buffer b; + char * str; + void * ud; const char *s = luaL_checklstring(L, 1, &l); - int n = luaL_checkint(L, 2); - luaL_buffinit(L, &b); - while (n-- > 0) - luaL_addlstring(&b, s, l); - luaL_pushresult(&b); + int n = luaL_checkint(L, 2), i; + if (n == 0) lua_pushliteral(L, ""); + else if (n == 1) lua_pushvalue(L, 1); + else { + str = lua_getallocf(L, &ud)(ud, NULL, 0, l * n); + for (i = 0; i < n; i++) memcpy(str + (i * l), s, l); + lua_pushlstring(L, str, l * n); + lua_getallocf(L, &ud)(ud, str, l * n, 0); + } return 1; }