lrotable.c 4.0 KB

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