-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlrotable.cpp
134 lines (119 loc) · 3.94 KB
/
lrotable.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* Read-only tables for Lua */
#include <string.h>
#include "lrotable.h"
#include "lua.h"
#include "lauxlib.h"
#include "lstring.h"
#include "lobject.h"
#include "lapi.h"
/* Local defines */
#define LUAR_FINDFUNCTION 0
#define LUAR_FINDVALUE 1
/* Externally defined read-only table array */
LUALIB_API const luaR_table lua_rotable[];
/* Find a global "read only table" in the constant lua_rotable array */
void* luaR_findglobal(const char *name, unsigned len) {
unsigned i;
if (strlen(name) > LUA_MAX_ROTABLE_NAME)
return NULL;
for (i=0; lua_rotable[i].name; i ++)
if (*lua_rotable[i].name != '\0' && strlen(lua_rotable[i].name) == len && !strncmp(lua_rotable[i].name, name, len)) {
return (void*)(lua_rotable[i].pentries);
}
return NULL;
}
/* Find an entry in a rotable and return it */
static const TValue* luaR_auxfind(const luaR_entry *pentry, const char *strkey, luaR_numkey numkey, unsigned *ppos) {
const TValue *res = NULL;
unsigned i = 0;
if (pentry == NULL)
return NULL;
while(pentry->key.type != LUA_TNIL) {
if ((strkey && (pentry->key.type == LUA_TSTRING) && (!strcmp(pentry->key.id.strkey, strkey))) ||
(!strkey && (pentry->key.type == LUA_TNUMBER) && ((luaR_numkey)pentry->key.id.numkey == numkey))) {
res = &pentry->value;
break;
}
i ++; pentry ++;
}
if (res && ppos)
*ppos = i;
return res;
}
int luaR_findfunction(lua_State *L, const luaR_entry *ptable) {
const TValue *res = NULL;
const char *key = luaL_checkstring(L, 2);
res = luaR_auxfind(ptable, key, 0, NULL);
if (res && ttislightfunction(res)) {
luaA_pushobject(L, res);
return 1;
}
else
return 0;
}
/* Find an entry in a rotable and return its type
If "strkey" is not NULL, the function will look for a string key,
otherwise it will look for a number key */
const TValue* luaR_findentry(void *data, const char *strkey, luaR_numkey numkey, unsigned *ppos) {
return luaR_auxfind((const luaR_entry*)data, strkey, numkey, ppos);
}
/* Find the metatable of a given table */
void* luaR_getmeta(void *data) {
#ifdef LUA_META_ROTABLES
const TValue *res = luaR_auxfind((const luaR_entry*)data, "__metatable", 0, NULL);
return res && ttisrotable(res) ? rvalue(res) : NULL;
#else
return NULL;
#endif
}
static void luaR_next_helper(lua_State *L, const luaR_entry *pentries, int pos, TValue *key, TValue *val) {
setnilvalue(key);
setnilvalue(val);
if (pentries[pos].key.type != LUA_TNIL) {
/* Found an entry */
if (pentries[pos].key.type == LUA_TSTRING)
setsvalue(L, key, luaS_newro(L, pentries[pos].key.id.strkey))
else
setnvalue(key, (lua_Number)pentries[pos].key.id.numkey)
setobj2s(L, val, &pentries[pos].value);
}
}
/* next (used for iteration) */
void luaR_next(lua_State *L, void *data, TValue *key, TValue *val) {
const luaR_entry* pentries = (const luaR_entry*)data;
char strkey[LUA_MAX_ROTABLE_NAME + 1], *pstrkey = NULL;
luaR_numkey numkey = 0;
unsigned keypos;
/* Special case: if key is nil, return the first element of the rotable */
if (ttisnil(key))
luaR_next_helper(L, pentries, 0, key, val);
else if (ttisstring(key) || ttisnumber(key)) {
/* Find the previoud key again */
if (ttisstring(key)) {
luaR_getcstr(strkey, rawtsvalue(key), LUA_MAX_ROTABLE_NAME);
pstrkey = strkey;
} else
numkey = (luaR_numkey)nvalue(key);
luaR_findentry(data, pstrkey, numkey, &keypos);
/* Advance to next key */
keypos ++;
luaR_next_helper(L, pentries, keypos, key, val);
}
}
/* Convert a Lua string to a C string */
void luaR_getcstr(char *dest, const TString *src, size_t maxsize) {
if (src->tsv.len+1 > maxsize)
dest[0] = '\0';
else {
memcpy(dest, getstr(src), src->tsv.len);
dest[src->tsv.len] = '\0';
}
}
/* Return 1 if the given pointer is a rotable */
#ifdef LUA_META_ROTABLES
extern char stext;
extern char etext;
int luaR_isrotable(void *p) {
return &stext <= ( char* )p && ( char* )p <= &etext;
}
#endif