浏览代码

new "primitive" getn

Roberto Ierusalimschy 20 年之前
父节点
当前提交
9ffae705ee
共有 7 个文件被更改,包括 101 次插入66 次删除
  1. 13 11
      lapi.c
  2. 10 39
      lauxlib.c
  3. 9 1
      lbaselib.c
  4. 49 1
      ltable.c
  5. 2 1
      ltable.h
  6. 12 9
      ltablib.c
  7. 6 4
      ltests.c

+ 13 - 11
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.30 2005/03/08 20:10:05 roberto Exp roberto $
+** $Id: lapi.c,v 2.31 2005/03/09 16:28:07 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -350,16 +350,18 @@ LUA_API const char *lua_tostring (lua_State *L, int idx) {
 
 LUA_API size_t lua_objsize (lua_State *L, int idx) {
   StkId o = index2adr(L, idx);
-  if (ttisstring(o))
-    return tsvalue(o)->len;
-  else if (ttisuserdata(o))
-    return uvalue(o)->len;
-  else {
-    size_t l;
-    lua_lock(L);  /* `luaV_tostring' may create a new string */
-    l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0);
-    lua_unlock(L);
-    return l;
+  switch (ttype(o)) {
+    case LUA_TSTRING: return tsvalue(o)->len;
+    case LUA_TUSERDATA: return uvalue(o)->len;
+    case LUA_TTABLE: return luaH_getn(hvalue(o));
+    case LUA_TNUMBER: {
+      size_t l;
+      lua_lock(L);  /* `luaV_tostring' may create a new string */
+      l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0);
+      lua_unlock(L);
+      return l;
+    }
+    default: return 0;
   }
 }
 

+ 10 - 39
lauxlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.c,v 1.128 2005/02/10 17:12:02 roberto Exp roberto $
+** $Id: lauxlib.c,v 1.129 2005/02/23 17:30:22 roberto Exp roberto $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -25,12 +25,7 @@
 #include "lauxlib.h"
 
 
-/* number of prereserved references (for internal use) */
-#define RESERVED_REFS	2
-
-/* reserved references */
-#define FREELIST_REF	1	/* free list of references */
-#define ARRAYSIZE_REF	2	/* array sizes */
+#define FREELIST_REF	0	/* free list of references */
 
 
 /* convert a stack index to positive */
@@ -275,6 +270,8 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
 ** =======================================================
 */
 
+#ifndef luaL_getn
+
 static int checkint (lua_State *L, int topop) {
   int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1;
   lua_pop(L, topop);
@@ -283,7 +280,7 @@ static int checkint (lua_State *L, int topop) {
 
 
 static void getsizes (lua_State *L) {
-  lua_rawgeti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF);
+  lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES");
   if (lua_isnil(L, -1)) {  /* no `size' table? */
     lua_pop(L, 1);  /* remove nil */
     lua_newtable(L);  /* create it */
@@ -292,7 +289,7 @@ static void getsizes (lua_State *L) {
     lua_pushliteral(L, "kv");
     lua_setfield(L, -2, "__mode");  /* metatable(N).__mode = "kv" */
     lua_pushvalue(L, -1);
-    lua_rawseti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF);  /* store in register */
+    lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES");  /* store in register */
   }
 }
 
@@ -307,31 +304,6 @@ LUALIB_API void luaL_setn (lua_State *L, int t, int n) {
 }
 
 
-/* find an `n' such that t[n] ~= nil and t[n+1] == nil */
-static int countn (lua_State *L, int t) {
-  int i = LUA_FIRSTINDEX - 1;
-  int j = 2;
-  /* find `i' such that i <= n < i*2 (= j) */
-  for (;;) {
-    lua_rawgeti(L, t, j);
-    if (lua_isnil(L, -1)) break;
-    lua_pop(L, 1);
-    i = j;
-    j = i*2;
-  }
-  lua_pop(L, 1);
-  /* i <= n < j; do a binary search */
-  while (i < j-1) {
-    int m = (i+j)/2;
-    lua_rawgeti(L, t, m);
-    if (lua_isnil(L, -1)) j = m;
-    else i = m;
-    lua_pop(L, 1);
-  }
-  return i - LUA_FIRSTINDEX + 1;
-}
-
-
 LUALIB_API int luaL_getn (lua_State *L, int t) {
   int n;
   t = abs_index(L, t);
@@ -341,9 +313,11 @@ LUALIB_API int luaL_getn (lua_State *L, int t) {
   if ((n = checkint(L, 2)) >= 0) return n;
   lua_getfield(L, t, "n");  /* else try t.n */
   if ((n = checkint(L, 1)) >= 0) return n;
-  return countn(L, t);
+  return lua_objsize(L, t);
 }
 
+#endif
+
 /* }====================================================== */
 
 
@@ -562,11 +536,8 @@ LUALIB_API int luaL_ref (lua_State *L, int t) {
     lua_rawseti(L, t, FREELIST_REF);  /* (t[FREELIST_REF] = t[ref]) */
   }
   else {  /* no free elements */
-    ref = luaL_getn(L, t);
-    if (ref < RESERVED_REFS)
-      ref = RESERVED_REFS;  /* skip reserved references */
+    ref = lua_objsize(L, t);
     ref++;  /* create new reference */
-    luaL_setn(L, t, ref);
   }
   lua_rawseti(L, t, ref);
   return ref;

+ 9 - 1
lbaselib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lbaselib.c,v 1.169 2005/02/28 17:24:41 roberto Exp roberto $
+** $Id: lbaselib.c,v 1.170 2005/03/11 15:51:08 roberto Exp roberto $
 ** Basic library
 ** See Copyright Notice in lua.h
 */
@@ -332,6 +332,13 @@ static int luaB_assert (lua_State *L) {
 }
 
 
+static int luaB_getn (lua_State *L) {
+  luaL_checktype(L, 1, LUA_TTABLE);
+  lua_pushinteger(L, lua_objsize(L, 1));
+  return 1;
+}
+
+
 static int luaB_unpack (lua_State *L) {
   int i = luaL_optint(L, 2, LUA_FIRSTINDEX);
   int e = luaL_optint(L, 3, -1);
@@ -448,6 +455,7 @@ static const luaL_reg base_funcs[] = {
   {"tostring", luaB_tostring},
   {"type", luaB_type},
   {"assert", luaB_assert},
+  {"getn", luaB_getn},
   {"unpack", luaB_unpack},
   {"select", luaB_select},
   {"rawequal", luaB_rawequal},

+ 49 - 1
ltable.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 2.17 2005/03/08 20:10:05 roberto Exp roberto $
+** $Id: ltable.c,v 2.18 2005/03/09 16:28:07 roberto Exp roberto $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -524,3 +524,51 @@ TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {
   }
 }
 
+
+static int unbound_search (Table *t, unsigned int j) {
+  unsigned int i = j;  /* i is zero or a present index */
+  j = j+1;
+  /* find `i' and `j' such that i is present and j is not */
+  while (!ttisnil(luaH_getnum(t, j))) {
+    i = j;
+    j = i*2;
+    if (j > cast(unsigned int, MAX_INT)) {  /* overflow? */
+      /* table was built with bad purposes: resort to linear search */
+      i = 1;
+      while (!ttisnil(luaH_getnum(t, i))) i++;
+      return i - 1;
+    }
+  }
+  /* now do a binary search between them */
+  while (i < j-1) {
+    unsigned int m = (i+j)/2;
+    if (ttisnil(luaH_getnum(t, m))) j = m;
+    else i = m;
+  }
+  return i;
+}
+
+
+/*
+** Try to find a boundary in table `t'. A `boundary' is an integer index
+** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
+*/
+int luaH_getn (Table *t) {
+  unsigned int j = t->sizearray;
+  if (j > 0 && ttisnil(&t->array[j - 1])) {
+    /* there is a boundary in the array part: (binary) search for it */
+    unsigned int i = 1;
+    if (ttisnil(&t->array[1 - 1])) return 0;
+    while (i < j - 1) {
+      unsigned int m = (i+j)/2;
+      if (ttisnil(&t->array[m - 1])) j = m;
+      else i = m;
+    }
+    return i;
+  }
+  /* else must find a boundary in hash part */
+  else if (t->node == &luaH_dummynode)  /* hash part is empty? */
+    return j;  /* that is easy... */
+  else return unbound_search(t, j);
+}
+

+ 2 - 1
ltable.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.h,v 2.4 2005/01/04 15:55:12 roberto Exp roberto $
+** $Id: ltable.h,v 2.5 2005/01/05 18:20:51 roberto Exp roberto $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -30,6 +30,7 @@ Table *luaH_new (lua_State *L, int narray, int lnhash);
 void luaH_resizearray (lua_State *L, Table *t, int nasize);
 void luaH_free (lua_State *L, Table *t);
 int luaH_next (lua_State *L, Table *t, StkId key);
+int luaH_getn (Table *t);
 
 /* exported only for debugging */
 Node *luaH_mainposition (const Table *t, const TValue *key);

+ 12 - 9
ltablib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltablib.c,v 1.26 2004/06/15 13:37:21 roberto Exp roberto $
+** $Id: ltablib.c,v 1.27 2004/12/07 18:28:47 roberto Exp roberto $
 ** Library for Table Manipulation
 ** See Copyright Notice in lua.h
 */
@@ -62,29 +62,32 @@ static int getn (lua_State *L) {
 
 static int setn (lua_State *L) {
   luaL_checktype(L, 1, LUA_TTABLE);
+#ifndef luaL_setn
   luaL_setn(L, 1, luaL_checkint(L, 2));
+#else
+  luaL_error(L, "`setn' is obsolete");
+#endif
   lua_pushvalue(L, 1);
   return 1;
 }
 
 
 static int tinsert (lua_State *L) {
-  int v = lua_gettop(L);  /* number of arguments */
   int e = aux_getn(L, 1) + LUA_FIRSTINDEX;  /* first empty element */
   int pos;  /* where to insert new element */
-  if (v == 2)  /* called with only 2 arguments */
+  if (lua_isnone(L, 3))  /* called with only 2 arguments */
     pos = e;  /* insert new element at the end */
   else {
+    int i;
     pos = luaL_checkint(L, 2);  /* 2nd argument is the position */
     if (pos > e) e = pos;  /* `grow' array if necessary */
-    v = 3;  /* function may be called with more than 3 args */
+    lua_settop(L, 3);  /* function may be called with more than 3 args */
+    for (i = e; i > pos; i--) {  /* move up elements */
+      lua_rawgeti(L, 1, i-1);
+      lua_rawseti(L, 1, i);  /* t[i] = t[i-1] */
+    }
   }
   luaL_setn(L, 1, e - LUA_FIRSTINDEX + 1);  /* new size */
-  while (--e >= pos) {  /* move up elements */
-    lua_rawgeti(L, 1, e);
-    lua_rawseti(L, 1, e+1);  /* t[e+1] = t[e] */
-  }
-  lua_pushvalue(L, v);
   lua_rawseti(L, 1, pos);  /* t[pos] = v */
   return 0;
 }

+ 6 - 4
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 2.19 2005/01/19 15:54:26 roberto Exp roberto $
+** $Id: ltests.c,v 2.20 2005/02/18 12:40:02 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -456,11 +456,11 @@ static int listlocals (lua_State *L) {
 
 static int get_limits (lua_State *L) {
   lua_createtable(L, 0, 5);
-  setnameval(L, "BITS_INT", LUA_BITSINT);
+  setnameval(L, "BITS_INT", LUAI_BITSINT);
   setnameval(L, "LFPF", LFIELDS_PER_FLUSH);
-  setnameval(L, "MAXVARS", MAXVARS);
+  setnameval(L, "MAXVARS", LUAI_MAXVARS);
   setnameval(L, "MAXSTACK", MAXSTACK);
-  setnameval(L, "MAXUPVALUES", MAXUPVALUES);
+  setnameval(L, "MAXUPVALUES", LUAI_MAXUPVALUES);
   setnameval(L, "NUM_OPCODES", NUM_OPCODES);
   return 1;
 }
@@ -970,12 +970,14 @@ static int testC (lua_State *L) {
       int i = getindex;
       lua_pushinteger(L1, luaL_getn(L1, i));
     }
+#ifndef luaL_setn
     else if EQ("setn") {
       int i = getindex;
       int n = cast(int, lua_tonumber(L1, -1));
       luaL_setn(L1, i, n);
       lua_pop(L1, 1);
     }
+#endif
     else if EQ("throw") {
 #ifdef __cplusplus
 static struct X { int x; } x;