Преглед изворни кода

External strings are as good as internal ones

A '__mode' metafield and an "n" key both can be external strings.
Roberto I пре 2 месеци
родитељ
комит
5b7d998764
4 измењених фајлова са 28 додато и 6 уклоњено
  1. 3 3
      lgc.c
  2. 1 1
      ltm.c
  3. 7 2
      lvm.c
  4. 17 0
      testes/strings.lua

+ 3 - 3
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))
-    return 0;  /* ignore non-(short)string modes */
+  if (mode == NULL || !ttisstring(mode))
+    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);

+ 1 - 1
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"? */

+ 7 - 2
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 */
-      size_t tl = tsslen(tsvalue(s2v(top - 1)));
+      /* at least two string values; get as many as possible */
+      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++) {

+ 17 - 0
testes/strings.lua

@@ -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')