lua-users home
lua-l archive

Read-Only Tables Patch

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


After doing a great amount of reading and experimentation I decided that the existing methods for creating read-only tables in Lua 5.1 was untenable. For such a simple thing it seemed rather ridiculous to have to use an empty proxy-table along with or instead of redefinitions of the several table related functions. It seemed that there should be a simpler solution. So I went about poking around in the code and came up with a solution that works for me. You can find the patch below that adds Read-Only table support to Lua-5.1.1. This facility is controlled by the '__readonly' entry in a table's metatable. If the value of '__readonly' is a function it is called with semantics identical to '__newindex' that is: mt = { __readonly = function(table, key, value) print("Attempted to modify a read-only table!") end } If the value of '__readonly' is anything other than a function a runtime error is generated. I'm sure if I were a little more acquainted with the code that I could have been a little more clever in this regard (such as taking a custom error as a string) If I've done something horribly wrong, or have put this in an inappropriate place, or there are other implications that I haven't thought of please let me know. This patch "feels" kind of hackish as I am not intimately familiar with the code base, however, it seems to be working find for me:
	mytab = { key1 = "val1", key2 = "val2" }
	mt = { __readonly = true }
	setmetatable(mytab, mt)
	mytab["key3"] = "val3"
	stdin:1: Attempt to modify a Read-Only Table!
	stack traceback:
 	stdin:1: in main chunk
	 [C]: ?
While some of the existing "solutions" are not too difficult to accomplish in Lua, when trying to implement them in C, it becomes a bit of a challenge for something that should be so simple, and in fact the change to the code was very minimal.
Thank you for your time and consideration,
Michael Grubb
P.S.
It is a rare thing to compile a piece of software without ANY compiler warnings. Thank you for your attention to detail.
The patch is below:
diff -ruN lua-rot-5.1.1/src/ltm.c lua-5.1.1/src/ltm.c
--- lua-rot-5.1.1/src/ltm.c	2006年11月10日 15:39:56.000000000 -0600
+++ lua-5.1.1/src/ltm.c	2006年01月10日 06:50:00.000000000 -0600
@@ -30,11 +30,8 @@
void luaT_init (lua_State *L) {
 static const char *const luaT_eventname[] = { /* ORDER TM */
 "__index", "__newindex",
- "__gc", "__mode",
-#ifdef LUA_READONLY_TABLES
-	"__readonly",
-#endif
-	"__eq", "__add", "__sub", "__mul", "__div", "__mod",
+ "__gc", "__mode", "__eq",
+ "__add", "__sub", "__mul", "__div", "__mod",
 "__pow", "__unm", "__len", "__lt", "__le",
 "__concat", "__call"
 };
diff -ruN lua-rot-5.1.1/src/ltm.h lua-5.1.1/src/ltm.h
--- lua-rot-5.1.1/src/ltm.h	2006年11月10日 15:39:59.000000000 -0600
+++ lua-5.1.1/src/ltm.h	2005年06月06日 08:30:25.000000000 -0500
@@ -20,9 +20,6 @@
 TM_NEWINDEX,
 TM_GC,
 TM_MODE,
-#ifdef LUA_READONLY_TABLES
- TM_READONLY,
-#endif
 TM_EQ, /* last tag method with `fast' access */
 TM_ADD,
 TM_SUB,
diff -ruN lua-rot-5.1.1/src/luaconf.h lua-5.1.1/src/luaconf.h
--- lua-rot-5.1.1/src/luaconf.h	2006年11月10日 15:39:47.000000000 -0600
+++ lua-5.1.1/src/luaconf.h	2006年04月10日 13:27:23.000000000 -0500
@@ -747,12 +747,6 @@
#endif
-/*
-@@ LUA_READONLY_TABLES controls whether to enable read-only table
-support by way of the __readonly metatable entry. CHANGE it (define it)
-to enable Read-Only support.
-*/
-#define LUA_READONLY_TABLES
/* =================================================================== */
diff -ruN lua-rot-5.1.1/src/lvm.c lua-5.1.1/src/lvm.c
--- lua-rot-5.1.1/src/lvm.c	2006年11月10日 14:26:17.000000000 -0600
+++ lua-5.1.1/src/lvm.c	2006年06月05日 10:58:59.000000000 -0500
@@ -140,22 +140,11 @@
 if (ttistable(t)) { /* `t' is a table? */
 Table *h = hvalue(t);
 TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
-#ifdef LUA_READONLY_TABLES
-	 if ( (tm = fasttm(L, h->metatable, TM_READONLY)) != NULL )
-	 {
-		 if (ttisfunction(tm)) {
-			 callTM(L, tm, t, key, val);
-			 return;
-		 }
-		 else
-			 luaG_runerror(L, "Attempt to modify a Read-Only Table!");
-	 }
-#endif
 if (!ttisnil(oldval) || /* result is no nil? */
(tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
- 	setobj2t(L, oldval, val);
- 	luaC_barriert(L, h, val);
- 	return;
+ setobj2t(L, oldval, val);
+ luaC_barriert(L, h, val);
+ return;
 }
 /* else will try the tag method */
 }

AltStyle によって変換されたページ (->オリジナル) /