Преглед на файлове

new auxiliary functions for `type' manipulation

Roberto Ierusalimschy преди 22 години
родител
ревизия
40cfb0691e
променени са 3 файла, в които са добавени 56 реда и са изтрити 39 реда
  1. 40 14
      lauxlib.c
  2. 7 4
      lauxlib.h
  3. 9 21
      liolib.c

+ 40 - 14
lauxlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.c,v 1.94 2003/02/11 09:44:38 roberto Exp roberto $
+** $Id: lauxlib.c,v 1.95 2003/02/11 15:32:31 roberto Exp roberto $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -103,6 +103,45 @@ LUALIB_API int luaL_findstring (const char *name, const char *const list[]) {
 }
 
 
+LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
+  lua_pushstring(L, tname);
+  lua_rawget(L, LUA_REGISTRYINDEX);  /* get registry.name */
+  if (!lua_isnil(L, -1))  /* name already in use? */
+    return 0;  /* leave previous value on top, but return 0 */
+  lua_pop(L, 1);
+  lua_newtable(L);  /* create metatable */
+  lua_pushstring(L, tname);
+  lua_pushvalue(L, -2);
+  lua_rawset(L, LUA_REGISTRYINDEX);  /* registry.name = metatable */
+  lua_pushvalue(L, -1);
+  lua_pushstring(L, tname);
+  lua_rawset(L, LUA_REGISTRYINDEX);  /* registry[metatable] = name */
+  return 1;
+}
+
+
+LUALIB_API void  luaL_getmetatable (lua_State *L, const char *tname) {
+  lua_pushstring(L, tname);
+  lua_rawget(L, LUA_REGISTRYINDEX);
+}
+
+
+LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
+  const char *tn;
+  if (!lua_getmetatable(L, ud)) return NULL;  /* no metatable? */
+  lua_rawget(L, LUA_REGISTRYINDEX);  /* get registry[metatable] */
+  tn = lua_tostring(L, -1);
+  if (tn && (strcmp(tn, tname) == 0)) {
+    lua_pop(L, 1);
+    return lua_touserdata(L, ud);
+  }
+  else {
+    lua_pop(L, 1);
+    return NULL;
+  }
+}
+
+
 LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
   if (!lua_checkstack(L, space))
     luaL_error(L, "stack overflow (%s)", mes);
@@ -121,19 +160,6 @@ LUALIB_API void luaL_checkany (lua_State *L, int narg) {
 }
 
 
-LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
-  if (!lua_getmetatable(L, ud)) return NULL;  /* no metatable? */
-  lua_pushstring(L, tname);
-  lua_rawget(L, LUA_REGISTRYINDEX);
-  if (!lua_rawequal(L, -1, -2)) {
-    lua_pop(L, 2);
-    return NULL;
-  }
-  lua_pop(L, 2);
-  return lua_touserdata(L, ud);
-}
-
-
 LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
   const char *s = lua_tostring(L, narg);
   if (!s) tag_error(L, narg, LUA_TSTRING);

+ 7 - 4
lauxlib.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.h,v 1.57 2003/01/27 13:46:16 roberto Exp roberto $
+** $Id: lauxlib.h,v 1.58 2003/02/11 15:32:31 roberto Exp roberto $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -16,7 +16,7 @@
 
 
 #ifndef LUALIB_API
-#define LUALIB_API	extern
+#define LUALIB_API	LUA_API
 #endif
 
 
@@ -33,7 +33,6 @@ LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *e);
 LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *e);
 LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname);
 LUALIB_API int luaL_argerror (lua_State *L, int numarg, const char *extramsg);
-LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname);
 LUALIB_API const char *luaL_checklstring (lua_State *L, int numArg, size_t *l);
 LUALIB_API const char *luaL_optlstring (lua_State *L, int numArg,
                                            const char *def, size_t *l);
@@ -44,6 +43,10 @@ LUALIB_API void luaL_checkstack (lua_State *L, int sz, const char *msg);
 LUALIB_API void luaL_checktype (lua_State *L, int narg, int t);
 LUALIB_API void luaL_checkany (lua_State *L, int narg);
 
+LUALIB_API int   luaL_newmetatable (lua_State *L, const char *tname);
+LUALIB_API void  luaL_getmetatable (lua_State *L, const char *tname);
+LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname);
+
 LUALIB_API void luaL_where (lua_State *L, int lvl);
 LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...);
 
@@ -115,7 +118,7 @@ LUALIB_API void luaL_pushresult (luaL_Buffer *B);
 
 
 /*
-** Compatibility macros
+** Compatibility macros and functions
 */
 
 LUALIB_API int   lua_dofile (lua_State *L, const char *filename);

+ 9 - 21
liolib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: liolib.c,v 2.36 2003/03/14 19:00:16 roberto Exp roberto $
+** $Id: liolib.c,v 2.37 2003/03/14 19:08:11 roberto Exp roberto $
 ** Standard I/O (and system) library
 ** See Copyright Notice in lua.h
 */
@@ -87,21 +87,15 @@ static int pushresult (lua_State *L, int i, const char *filename) {
 
 
 static FILE **topfile (lua_State *L, int findex) {
-  FILE **f = (FILE **)lua_touserdata(L, findex);
-  if (f == NULL || !lua_getmetatable(L, findex) ||
-                   !lua_rawequal(L, -1, lua_upvalueindex(1))) {
-    luaL_argerror(L, findex, "bad file");
-  }
-  lua_pop(L, 1);
+  FILE **f = (FILE **)luaL_checkudata(L, findex, FILEHANDLE);
+  if (f == NULL) luaL_argerror(L, findex, "bad file");
   return f;
 }
 
 
 static int io_type (lua_State *L) {
-  FILE **f = (FILE **)lua_touserdata(L, 1);
-  if (f == NULL || !lua_getmetatable(L, 1) ||
-                   !lua_rawequal(L, -1, lua_upvalueindex(1)))
-    lua_pushnil(L);
+  FILE **f = (FILE **)luaL_checkudata(L, 1, FILEHANDLE);
+  if (f == NULL) lua_pushnil(L);
   else if (*f == NULL)
     lua_pushliteral(L, "closed file");
   else
@@ -127,8 +121,7 @@ static FILE *tofile (lua_State *L, int findex) {
 static FILE **newfile (lua_State *L) {
   FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
   *pf = NULL;  /* file handle is currently `closed' */
-  lua_pushliteral(L, FILEHANDLE);
-  lua_rawget(L, LUA_REGISTRYINDEX);
+  luaL_getmetatable(L, FILEHANDLE);
   lua_setmetatable(L, -2);
   return pf;
 }
@@ -527,15 +520,12 @@ static const luaL_reg flib[] = {
 
 
 static void createmeta (lua_State *L) {
-  lua_pushliteral(L, FILEHANDLE);
-  lua_newtable(L);  /* push new metatable for file handles */
+  luaL_newmetatable(L, FILEHANDLE);  /* create new metatable for file handles */
   /* file methods */
   lua_pushliteral(L, "__index");
   lua_pushvalue(L, -2);  /* push metatable */
   lua_rawset(L, -3);  /* metatable.__index = metatable */
-  lua_pushvalue(L, -1);  /* push metatable (will be upvalue for library) */
-  luaL_openlib(L, NULL, flib, 1);
-  lua_rawset(L, LUA_REGISTRYINDEX);  /* registry.FILEHANDLE = metatable */
+  luaL_openlib(L, NULL, flib, 0);
 }
 
 /* }====================================================== */
@@ -748,10 +738,8 @@ static const luaL_reg syslib[] = {
 
 
 LUALIB_API int luaopen_io (lua_State *L) {
-  createmeta(L);
   luaL_openlib(L, LUA_OSLIBNAME, syslib, 0);
-  lua_pushliteral(L, FILEHANDLE);
-  lua_rawget(L, LUA_REGISTRYINDEX);
+  createmeta(L);
   lua_pushvalue(L, -1);
   luaL_openlib(L, LUA_IOLIBNAME, iolib, 1);
   /* put predefined file handles into `io' table */