External strings are as good as internal ones
A '__mode' metafield and an "n" key both can be external strings.
This commit is contained in:
6
lgc.c
6
lgc.c
@@ -594,10 +594,10 @@ static void traversestrongtable (global_State *g, Table *h) {
|
|||||||
*/
|
*/
|
||||||
static int getmode (global_State *g, Table *h) {
|
static int getmode (global_State *g, Table *h) {
|
||||||
const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
|
const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
|
||||||
if (mode == NULL || !ttisshrstring(mode))
|
if (mode == NULL || !ttisstring(mode))
|
||||||
return 0; /* ignore non-(short)string modes */
|
return 0; /* ignore non-string modes */
|
||||||
else {
|
else {
|
||||||
const char *smode = getshrstr(tsvalue(mode));
|
const char *smode = getstr(tsvalue(mode));
|
||||||
const char *weakkey = strchr(smode, 'k');
|
const char *weakkey = strchr(smode, 'k');
|
||||||
const char *weakvalue = strchr(smode, 'v');
|
const char *weakvalue = strchr(smode, 'v');
|
||||||
return ((weakkey != NULL) << 1) | (weakvalue != NULL);
|
return ((weakkey != NULL) << 1) | (weakvalue != NULL);
|
||||||
|
|||||||
2
ltm.c
2
ltm.c
@@ -287,7 +287,7 @@ void luaT_getvararg (CallInfo *ci, StkId ra, TValue *rc) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ttisshrstring(rc)) { /* short-string value? */
|
else if (ttisstring(rc)) { /* string value? */
|
||||||
size_t len;
|
size_t len;
|
||||||
const char *s = getlstr(tsvalue(rc), len);
|
const char *s = getlstr(tsvalue(rc), len);
|
||||||
if (len == 1 && s[0] == 'n') { /* key is "n"? */
|
if (len == 1 && s[0] == 'n') { /* key is "n"? */
|
||||||
|
|||||||
9
lvm.c
9
lvm.c
@@ -657,6 +657,11 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
|
|||||||
#define tostring(L,o) \
|
#define tostring(L,o) \
|
||||||
(ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1)))
|
(ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Check whether object is a short empty string to optimize concatenation.
|
||||||
|
** (External strings can be empty too; they will be concatenated like
|
||||||
|
** non-empty ones.)
|
||||||
|
*/
|
||||||
#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0)
|
#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0)
|
||||||
|
|
||||||
/* copy strings in stack from top - n up to top - 1 to buffer */
|
/* copy strings in stack from top - n up to top - 1 to buffer */
|
||||||
@@ -691,8 +696,8 @@ void luaV_concat (lua_State *L, int total) {
|
|||||||
setobjs2s(L, top - 2, top - 1); /* result is second op. */
|
setobjs2s(L, top - 2, top - 1); /* result is second op. */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* at least two non-empty string values; get as many as possible */
|
/* at least two string values; get as many as possible */
|
||||||
size_t tl = tsslen(tsvalue(s2v(top - 1)));
|
size_t tl = tsslen(tsvalue(s2v(top - 1))); /* total length */
|
||||||
TString *ts;
|
TString *ts;
|
||||||
/* collect total length and number of strings */
|
/* collect total length and number of strings */
|
||||||
for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) {
|
for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) {
|
||||||
|
|||||||
@@ -540,6 +540,23 @@ else
|
|||||||
assert(y == x)
|
assert(y == x)
|
||||||
local z = T.externstr(x) -- external allocated long string
|
local z = T.externstr(x) -- external allocated long string
|
||||||
assert(z == y)
|
assert(z == y)
|
||||||
|
|
||||||
|
local e = T.externstr("") -- empty external string
|
||||||
|
assert(e .. "x" == "x" and "x" .. e == "x")
|
||||||
|
assert(e .. e == "" and #e == 0)
|
||||||
|
|
||||||
|
-- external string as the "n" key in vararg table
|
||||||
|
local n = T.externstr("n")
|
||||||
|
local n0 = T.externstr("n\0")
|
||||||
|
local function aux (...t) assert(t[n0] == nil); return t[n] end
|
||||||
|
assert(aux(10, 20, 30) == 3)
|
||||||
|
|
||||||
|
-- external string as mode in weak table
|
||||||
|
local t = setmetatable({}, {__mode = T.externstr("kv")})
|
||||||
|
t[{}] = {}
|
||||||
|
assert(next(t))
|
||||||
|
collectgarbage()
|
||||||
|
assert(next(t) == nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
print('OK')
|
print('OK')
|
||||||
|
|||||||
Reference in New Issue
Block a user