lrotable.c 4.3 KB

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