The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ltablib.cpp
Go to the documentation of this file.
1 /*
2 ** Library for Table Manipulation
3 ** See Copyright Notice in lua.h
4 */
5 
6 
7 #include <stddef.h>
8 
9 #define ltablib_c
10 #define LUA_LIB
11 
12 #include "lua.h"
13 
14 #include "lauxlib.h"
15 #include "lualib.h"
16 
17 
18 #define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n))
19 
20 
21 
22 #if defined(LUA_COMPAT_MAXN)
23 static int maxn (lua_State *L) {
24  lua_Number max = 0;
26  lua_pushnil(L); /* first key */
27  while (lua_next(L, 1)) {
28  lua_pop(L, 1); /* remove value */
29  if (lua_type(L, -1) == LUA_TNUMBER) {
30  lua_Number v = lua_tonumber(L, -1);
31  if (v > max) max = v;
32  }
33  }
34  lua_pushnumber(L, max);
35  return 1;
36 }
37 #endif
38 
39 
40 static int tinsert (lua_State *L) {
41  int e = aux_getn(L, 1) + 1; /* first empty element */
42  int pos; /* where to insert new element */
43  switch (lua_gettop(L)) {
44  case 2: { /* called with only 2 arguments */
45  pos = e; /* insert new element at the end */
46  break;
47  }
48  case 3: {
49  int i;
50  pos = luaL_checkint(L, 2); /* 2nd argument is the position */
51  luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds");
52  for (i = e; i > pos; i--) { /* move up elements */
53  lua_rawgeti(L, 1, i-1);
54  lua_rawseti(L, 1, i); /* t[i] = t[i-1] */
55  }
56  break;
57  }
58  default: {
59  return luaL_error(L, "wrong number of arguments to " LUA_QL("insert"));
60  }
61  }
62  lua_rawseti(L, 1, pos); /* t[pos] = v */
63  return 0;
64 }
65 
66 
67 static int tremove (lua_State *L) {
68  int size = aux_getn(L, 1);
69  int pos = luaL_optint(L, 2, size);
70  if (pos != size) /* validate 'pos' if given */
71  luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds");
72  lua_rawgeti(L, 1, pos); /* result = t[pos] */
73  for ( ; pos < size; pos++) {
74  lua_rawgeti(L, 1, pos+1);
75  lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */
76  }
77  lua_pushnil(L);
78  lua_rawseti(L, 1, pos); /* t[pos] = nil */
79  return 1;
80 }
81 
82 
83 static void addfield (lua_State *L, luaL_Buffer *b, int i) {
84  lua_rawgeti(L, 1, i);
85  if (!lua_isstring(L, -1))
86  luaL_error(L, "invalid value (%s) at index %d in table for "
87  LUA_QL("concat"), luaL_typename(L, -1), i);
88  luaL_addvalue(b);
89 }
90 
91 
92 static int tconcat (lua_State *L) {
93  luaL_Buffer b;
94  size_t lsep;
95  int i, last;
96  const char *sep = luaL_optlstring(L, 2, "", &lsep);
98  i = luaL_optint(L, 3, 1);
99  last = luaL_opt(L, luaL_checkint, 4, luaL_len(L, 1));
100  luaL_buffinit(L, &b);
101  for (; i < last; i++) {
102  addfield(L, &b, i);
103  luaL_addlstring(&b, sep, lsep);
104  }
105  if (i == last) /* add last value (if interval was not empty) */
106  addfield(L, &b, i);
107  luaL_pushresult(&b);
108  return 1;
109 }
110 
111 
112 /*
113 ** {======================================================
114 ** Pack/unpack
115 ** =======================================================
116 */
117 
118 static int pack (lua_State *L) {
119  int n = lua_gettop(L); /* number of elements to pack */
120  lua_createtable(L, n, 1); /* create result table */
121  lua_pushinteger(L, n);
122  lua_setfield(L, -2, "n"); /* t.n = number of elements */
123  if (n > 0) { /* at least one element? */
124  int i;
125  lua_pushvalue(L, 1);
126  lua_rawseti(L, -2, 1); /* insert first element */
127  lua_replace(L, 1); /* move table into index 1 */
128  for (i = n; i >= 2; i--) /* assign other elements */
129  lua_rawseti(L, 1, i);
130  }
131  return 1; /* return table */
132 }
133 
134 
135 static int unpack (lua_State *L) {
136  int i, e, n;
137  luaL_checktype(L, 1, LUA_TTABLE);
138  i = luaL_optint(L, 2, 1);
139  e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1));
140  if (i > e) return 0; /* empty range */
141  n = e - i + 1; /* number of elements */
142  if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */
143  return luaL_error(L, "too many results to unpack");
144  lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
145  while (i++ < e) /* push arg[i + 1...e] */
146  lua_rawgeti(L, 1, i);
147  return n;
148 }
149 
150 /* }====================================================== */
151 
152 
153 
154 /*
155 ** {======================================================
156 ** Quicksort
157 ** (based on `Algorithms in MODULA-3', Robert Sedgewick;
158 ** Addison-Wesley, 1993.)
159 ** =======================================================
160 */
161 
162 
163 static void set2 (lua_State *L, int i, int j) {
164  lua_rawseti(L, 1, i);
165  lua_rawseti(L, 1, j);
166 }
167 
168 static int sort_comp (lua_State *L, int a, int b) {
169  if (!lua_isnil(L, 2)) { /* function? */
170  int res;
171  lua_pushvalue(L, 2);
172  lua_pushvalue(L, a-1); /* -1 to compensate function */
173  lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */
174  lua_call(L, 2, 1);
175  res = lua_toboolean(L, -1);
176  lua_pop(L, 1);
177  return res;
178  }
179  else /* a < b? */
180  return lua_compare(L, a, b, LUA_OPLT);
181 }
182 
183 static void auxsort (lua_State *L, int l, int u) {
184  while (l < u) { /* for tail recursion */
185  int i, j;
186  /* sort elements a[l], a[(l+u)/2] and a[u] */
187  lua_rawgeti(L, 1, l);
188  lua_rawgeti(L, 1, u);
189  if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */
190  set2(L, l, u); /* swap a[l] - a[u] */
191  else
192  lua_pop(L, 2);
193  if (u-l == 1) break; /* only 2 elements */
194  i = (l+u)/2;
195  lua_rawgeti(L, 1, i);
196  lua_rawgeti(L, 1, l);
197  if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */
198  set2(L, i, l);
199  else {
200  lua_pop(L, 1); /* remove a[l] */
201  lua_rawgeti(L, 1, u);
202  if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */
203  set2(L, i, u);
204  else
205  lua_pop(L, 2);
206  }
207  if (u-l == 2) break; /* only 3 elements */
208  lua_rawgeti(L, 1, i); /* Pivot */
209  lua_pushvalue(L, -1);
210  lua_rawgeti(L, 1, u-1);
211  set2(L, i, u-1);
212  /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
213  i = l; j = u-1;
214  for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */
215  /* repeat ++i until a[i] >= P */
216  while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
217  if (i>=u) luaL_error(L, "invalid order function for sorting");
218  lua_pop(L, 1); /* remove a[i] */
219  }
220  /* repeat --j until a[j] <= P */
221  while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
222  if (j<=l) luaL_error(L, "invalid order function for sorting");
223  lua_pop(L, 1); /* remove a[j] */
224  }
225  if (j<i) {
226  lua_pop(L, 3); /* pop pivot, a[i], a[j] */
227  break;
228  }
229  set2(L, i, j);
230  }
231  lua_rawgeti(L, 1, u-1);
232  lua_rawgeti(L, 1, i);
233  set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */
234  /* a[l..i-1] <= a[i] == P <= a[i+1..u] */
235  /* adjust so that smaller half is in [j..i] and larger one in [l..u] */
236  if (i-l < u-i) {
237  j=l; i=i-1; l=i+2;
238  }
239  else {
240  j=i+1; i=u; u=j-2;
241  }
242  auxsort(L, j, i); /* call recursively the smaller one */
243  } /* repeat the routine for the larger one */
244 }
245 
246 static int sort (lua_State *L) {
247  int n = aux_getn(L, 1);
248  luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */
249  if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
251  lua_settop(L, 2); /* make sure there is two arguments */
252  auxsort(L, 1, n);
253  return 0;
254 }
255 
256 /* }====================================================== */
257 
258 
259 static const luaL_Reg tab_funcs[] = {
260  {"concat", tconcat},
261 #if defined(LUA_COMPAT_MAXN)
262  {"maxn", maxn},
263 #endif
264  {"insert", tinsert},
265  {"pack", pack},
266  {"unpack", unpack},
267  {"remove", tremove},
268  {"sort", sort},
269  {NULL, NULL}
270 };
271 
272 
274  luaL_newlib(L, tab_funcs);
275 #if defined(LUA_COMPAT_UNPACK)
276  /* _G.unpack = table.unpack */
277  lua_getfield(L, -1, "unpack");
278  lua_setglobal(L, "unpack");
279 #endif
280  return 1;
281 }
282 
LUA_API void lua_rawgeti(lua_State *L, int idx, int n)
Definition: lapi.cpp:643
#define lua_isnoneornil(L, n)
Definition: lua.h:337
LUALIB_API void luaL_addvalue(luaL_Buffer *B)
Definition: lauxlib.cpp:487
static void set2(lua_State *L, int i, int j)
Definition: ltablib.cpp:163
LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
Definition: lapi.cpp:667
LUA_API void lua_getfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:622
LUA_API void lua_replace(lua_State *L, int idx)
Definition: lapi.cpp:211
LUA_API void lua_settop(lua_State *L, int idx)
Definition: lapi.cpp:159
LUA_API int lua_type(lua_State *L, int idx)
Definition: lapi.cpp:243
static void auxsort(lua_State *L, int l, int u)
Definition: ltablib.cpp:183
LUALIB_API const char * luaL_optlstring(lua_State *L, int narg, const char *def, size_t *len)
Definition: lauxlib.cpp:366
int pos
Definition: formula.cpp:800
LUALIB_API void luaL_checktype(lua_State *L, int narg, int t)
Definition: lauxlib.cpp:347
LUALIB_API void luaL_pushresult(luaL_Buffer *B)
Definition: lauxlib.cpp:473
LUA_API int lua_gettop(lua_State *L)
Definition: lapi.cpp:154
#define lua_tonumber(L, i)
Definition: lua.h:318
#define luaL_typename(L, i)
Definition: lauxlib.h:122
LUALIB_API void luaL_checkstack(lua_State *L, int space, const char *msg)
Definition: lauxlib.cpp:335
#define LUA_TFUNCTION
Definition: lua.h:83
#define luaL_argcheck(L, cond, numarg, extramsg)
Definition: lauxlib.h:113
static int pack(lua_State *L)
Definition: ltablib.cpp:118
#define lua_pop(L, n)
Definition: lua.h:322
GLdouble l
Definition: glew.h:6966
static void addfield(lua_State *L, luaL_Buffer *b, int i)
Definition: ltablib.cpp:83
#define LUA_OPLT
Definition: lua.h:194
GLdouble GLdouble GLdouble b
Definition: glew.h:6966
LUA_API int lua_compare(lua_State *L, int index1, int index2, int op)
Definition: lapi.cpp:310
LUA_API void lua_setglobal(lua_State *L, const char *var)
Definition: lapi.cpp:728
LUA_API int lua_isstring(lua_State *L, int idx)
Definition: lapi.cpp:268
#define LUA_QL(x)
Definition: luaconf.h:198
static int unpack(lua_State *L)
Definition: ltablib.cpp:135
#define luaL_opt(L, f, n, d)
Definition: lauxlib.h:132
LUAMOD_API int luaopen_table(lua_State *L)
Definition: ltablib.cpp:273
LUA_API int lua_toboolean(lua_State *L, int idx)
Definition: lapi.cpp:377
const GLdouble * v
Definition: glew.h:1359
LUALIB_API void luaL_buffinit(lua_State *L, luaL_Buffer *B)
Definition: lauxlib.cpp:498
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:7319
#define LUA_TNUMBER
Definition: lua.h:80
static int tinsert(lua_State *L)
Definition: ltablib.cpp:40
static int sort_comp(lua_State *L, int a, int b)
Definition: ltablib.cpp:168
LUALIB_API void luaL_addlstring(luaL_Buffer *B, const char *s, size_t l)
Definition: lauxlib.cpp:461
LUA_API void lua_pushnil(lua_State *L)
Definition: lapi.cpp:459
LUA_API void lua_pushnumber(lua_State *L, lua_Number n)
Definition: lapi.cpp:467
static int tconcat(lua_State *L)
Definition: ltablib.cpp:92
GLuint res
Definition: glew.h:9258
#define lua_isnil(L, n)
Definition: lua.h:333
static int tremove(lua_State *L)
Definition: ltablib.cpp:67
#define aux_getn(L, n)
Definition: ltablib.cpp:18
#define LUAMOD_API
Definition: luaconf.h:163
size_t i
Definition: function.cpp:1057
LUA_API void lua_rawseti(lua_State *L, int idx, int n)
Definition: lapi.cpp:778
LUA_API void lua_pushvalue(lua_State *L, int idx)
Definition: lapi.cpp:229
static int sort(lua_State *L)
Definition: ltablib.cpp:246
#define luaL_newlib(L, l)
Definition: lauxlib.h:111
#define lua_call(L, n, r)
Definition: lua.h:252
LUALIB_API int luaL_error(lua_State *L, const char *fmt,...)
Definition: lauxlib.cpp:198
static const luaL_Reg tab_funcs[]
Definition: ltablib.cpp:259
static int maxn(lua_State *L)
Definition: ltablib.cpp:23
GLsizeiptr size
Definition: glew.h:1649
GLclampd n
Definition: glew.h:5903
#define luaL_checkint(L, n)
Definition: lauxlib.h:117
#define luaL_optint(L, n, d)
Definition: lauxlib.h:118
LUA_API int lua_checkstack(lua_State *L, int size)
Definition: lapi.cpp:86
#define e
LUALIB_API int luaL_len(lua_State *L, int idx)
Definition: lauxlib.cpp:727
#define LUA_TTABLE
Definition: lua.h:82
LUA_API void lua_pushinteger(lua_State *L, lua_Integer n)
Definition: lapi.cpp:477
LUA_NUMBER lua_Number
Definition: lua.h:102
LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:752
LUA_API int lua_next(lua_State *L, int idx)
Definition: lapi.cpp:1108