ltablib.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. ** $Id: ltablib.c,v 1.6 2002/06/13 13:44:50 roberto Exp roberto $
  3. ** Library for Table Manipulation
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <stddef.h>
  7. #include "lua.h"
  8. #include "lauxlib.h"
  9. #include "luadebug.h"
  10. #include "lualib.h"
  11. static int luaB_foreachi (lua_State *L) {
  12. int n, i;
  13. luaL_check_type(L, 1, LUA_TTABLE);
  14. luaL_check_type(L, 2, LUA_TFUNCTION);
  15. n = lua_getn(L, 1);
  16. for (i=1; i<=n; i++) {
  17. lua_pushvalue(L, 2); /* function */
  18. lua_pushnumber(L, i); /* 1st argument */
  19. lua_rawgeti(L, 1, i); /* 2nd argument */
  20. lua_upcall(L, 2, 1);
  21. if (!lua_isnil(L, -1))
  22. return 1;
  23. lua_pop(L, 1); /* remove nil result */
  24. }
  25. return 0;
  26. }
  27. static int luaB_foreach (lua_State *L) {
  28. luaL_check_type(L, 1, LUA_TTABLE);
  29. luaL_check_type(L, 2, LUA_TFUNCTION);
  30. lua_pushnil(L); /* first key */
  31. for (;;) {
  32. if (lua_next(L, 1) == 0)
  33. return 0;
  34. lua_pushvalue(L, 2); /* function */
  35. lua_pushvalue(L, -3); /* key */
  36. lua_pushvalue(L, -3); /* value */
  37. lua_upcall(L, 2, 1);
  38. if (!lua_isnil(L, -1))
  39. return 1;
  40. lua_pop(L, 2); /* remove value and result */
  41. }
  42. }
  43. static void aux_setn (lua_State *L, int t, int n) {
  44. lua_pushliteral(L, "n");
  45. lua_pushnumber(L, n);
  46. lua_rawset(L, t);
  47. }
  48. static int luaB_getn (lua_State *L) {
  49. luaL_check_type(L, 1, LUA_TTABLE);
  50. lua_pushnumber(L, lua_getn(L, 1));
  51. return 1;
  52. }
  53. static int luaB_tinsert (lua_State *L) {
  54. int v = lua_gettop(L); /* number of arguments */
  55. int n, pos;
  56. luaL_check_type(L, 1, LUA_TTABLE);
  57. n = lua_getn(L, 1);
  58. if (v == 2) /* called with only 2 arguments */
  59. pos = n+1;
  60. else {
  61. v = 3; /* function may be called with more than 3 args */
  62. pos = luaL_check_int(L, 2); /* 2nd argument is the position */
  63. }
  64. if (pos > n+1) n = pos-1;
  65. aux_setn(L, 1, n+1); /* t.n = n+1 */
  66. for (; n>=pos; n--) {
  67. lua_rawgeti(L, 1, n);
  68. lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */
  69. }
  70. lua_pushvalue(L, v);
  71. lua_rawseti(L, 1, pos); /* t[pos] = v */
  72. return 0;
  73. }
  74. static int luaB_tremove (lua_State *L) {
  75. int pos, n;
  76. luaL_check_type(L, 1, LUA_TTABLE);
  77. n = lua_getn(L, 1);
  78. pos = luaL_opt_int(L, 2, n);
  79. if (n <= 0) return 0; /* table is `empty' */
  80. aux_setn(L, 1, n-1); /* t.n = n-1 */
  81. lua_rawgeti(L, 1, pos); /* result = t[pos] */
  82. for ( ;pos<n; pos++) {
  83. lua_rawgeti(L, 1, pos+1);
  84. lua_rawseti(L, 1, pos); /* a[pos] = a[pos+1] */
  85. }
  86. lua_pushnil(L);
  87. lua_rawseti(L, 1, n); /* t[n] = nil */
  88. return 1;
  89. }
  90. /*
  91. ** {======================================================
  92. ** Quicksort
  93. ** (based on `Algorithms in MODULA-3', Robert Sedgewick;
  94. ** Addison-Wesley, 1993.)
  95. */
  96. static void set2 (lua_State *L, int i, int j) {
  97. lua_rawseti(L, 1, i);
  98. lua_rawseti(L, 1, j);
  99. }
  100. static int sort_comp (lua_State *L, int a, int b) {
  101. /* WARNING: the caller (auxsort) must ensure stack space */
  102. if (!lua_isnoneornil(L, 2)) { /* function? */
  103. int res;
  104. lua_pushvalue(L, 2);
  105. lua_pushvalue(L, a-1); /* -1 to compensate function */
  106. lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */
  107. lua_upcall(L, 2, 1);
  108. res = lua_toboolean(L, -1);
  109. lua_pop(L, 1);
  110. return res;
  111. }
  112. else /* a < b? */
  113. return lua_lessthan(L, a, b);
  114. }
  115. static void auxsort (lua_State *L, int l, int u) {
  116. while (l < u) { /* for tail recursion */
  117. int i, j;
  118. /* sort elements a[l], a[(l+u)/2] and a[u] */
  119. lua_rawgeti(L, 1, l);
  120. lua_rawgeti(L, 1, u);
  121. if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */
  122. set2(L, l, u); /* swap a[l] - a[u] */
  123. else
  124. lua_pop(L, 2);
  125. if (u-l == 1) break; /* only 2 elements */
  126. i = (l+u)/2;
  127. lua_rawgeti(L, 1, i);
  128. lua_rawgeti(L, 1, l);
  129. if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */
  130. set2(L, i, l);
  131. else {
  132. lua_pop(L, 1); /* remove a[l] */
  133. lua_rawgeti(L, 1, u);
  134. if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */
  135. set2(L, i, u);
  136. else
  137. lua_pop(L, 2);
  138. }
  139. if (u-l == 2) break; /* only 3 elements */
  140. lua_rawgeti(L, 1, i); /* Pivot */
  141. lua_pushvalue(L, -1);
  142. lua_rawgeti(L, 1, u-1);
  143. set2(L, i, u-1);
  144. /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
  145. i = l; j = u-1;
  146. for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */
  147. /* repeat ++i until a[i] >= P */
  148. while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
  149. if (i>u) luaL_error(L, "invalid order function for sorting");
  150. lua_pop(L, 1); /* remove a[i] */
  151. }
  152. /* repeat --j until a[j] <= P */
  153. while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
  154. if (j<l) luaL_error(L, "invalid order function for sorting");
  155. lua_pop(L, 1); /* remove a[j] */
  156. }
  157. if (j<i) {
  158. lua_pop(L, 3); /* pop pivot, a[i], a[j] */
  159. break;
  160. }
  161. set2(L, i, j);
  162. }
  163. lua_rawgeti(L, 1, u-1);
  164. lua_rawgeti(L, 1, i);
  165. set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */
  166. /* a[l..i-1] <= a[i] == P <= a[i+1..u] */
  167. /* adjust so that smaller half is in [j..i] and larger one in [l..u] */
  168. if (i-l < u-i) {
  169. j=l; i=i-1; l=i+2;
  170. }
  171. else {
  172. j=i+1; i=u; u=j-2;
  173. }
  174. auxsort(L, j, i); /* call recursively the smaller one */
  175. } /* repeat the routine for the larger one */
  176. }
  177. static int luaB_sort (lua_State *L) {
  178. int n;
  179. luaL_check_type(L, 1, LUA_TTABLE);
  180. n = lua_getn(L, 1);
  181. if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
  182. luaL_check_type(L, 2, LUA_TFUNCTION);
  183. lua_settop(L, 2); /* make sure there is two arguments */
  184. auxsort(L, 1, n);
  185. return 0;
  186. }
  187. /* }====================================================== */
  188. static const luaL_reg tab_funcs[] = {
  189. {"foreach", luaB_foreach},
  190. {"foreachi", luaB_foreachi},
  191. {"getn", luaB_getn},
  192. {"sort", luaB_sort},
  193. {"insert", luaB_tinsert},
  194. {"remove", luaB_tremove},
  195. {NULL, NULL}
  196. };
  197. LUALIB_API int lua_tablibopen (lua_State *L) {
  198. luaL_opennamedlib(L, LUA_TABLIBNAME, tab_funcs, 0);
  199. return 0;
  200. }