1 /* $Header: //info.ravenbrook.com/project/jili/version/1.1/code/mnj/lua/TableLib.java#1 $
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject
11 * to the following conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 import java
.util
.Enumeration
;
30 * Contains Lua's table library.
31 * The library can be opened using the {@link #open} method.
33 public final class TableLib
extends LuaJavaCallback
35 // Each function in the table library corresponds to an instance of
36 // this class which is associated (the 'which' member) with an integer
37 // which is unique within this class. They are taken from the following
39 private static final int CONCAT
= 1;
40 private static final int INSERT
= 2;
41 private static final int MAXN
= 3;
42 private static final int REMOVE
= 4;
43 private static final int SORT
= 5;
46 * Which library function this object represents. This value should
47 * be one of the "enums" defined in the class.
51 /** Constructs instance, filling in the 'which' member. */
52 private TableLib(int which
)
58 * Implements all of the functions in the Lua table library. Do not
60 * @param L the Lua state in which to execute.
61 * @return number of returned parameters, as per convention.
63 public int luaFunction(Lua L
)
82 * Opens the string library into the given Lua state. This registers
83 * the symbols of the string library in a newly created table called
85 * @param L The Lua state into which to open.
87 public static void open(Lua L
)
91 r(L
, "concat", CONCAT
);
92 r(L
, "insert", INSERT
);
94 r(L
, "remove", REMOVE
);
98 /** Register a function. */
99 private static void r(Lua L
, String name
, int which
)
101 TableLib f
= new TableLib(which
);
102 Object lib
= L
.getGlobal("table");
103 L
.setField(lib
, name
, f
);
106 /** Implements table.concat. */
107 private static int concat(Lua L
)
109 String sep
= L
.optString(2, "");
110 L
.checkType(1, Lua
.TTABLE
);
111 int i
= L
.optInt(3, 1);
112 int last
= L
.optInt(4, Lua
.objLen(L
.value(1)));
113 StringBuffer b
= new StringBuffer();
114 Object t
= L
.value(1);
115 for (; i
<= last
; ++i
)
117 Object v
= Lua
.rawGetI(t
, i
);
118 L
.argCheck(Lua
.isString(v
), 1, "table contains non-strings");
119 b
.append(L
.toString(v
));
121 b
.append(L
.toString(sep
));
123 L
.pushString(b
.toString());
127 /** Implements table.insert. */
128 private static int insert(Lua L
)
130 int e
= aux_getn(L
, 1) + 1; // first empty element
131 int pos
; // where to insert new element
132 Object t
= L
.value(1);
135 case 2: // called with only 2 arguments
136 pos
= e
; // insert new element at the end
142 pos
= L
.checkInt(2); // 2nd argument is the position
144 e
= pos
; // grow array if necessary
145 for (i
= e
; i
> pos
; --i
) // move up elements
148 L
.rawSetI(t
, i
, Lua
.rawGetI(t
, i
-1));
154 return L
.error("wrong number of arguments to 'insert'");
156 L
.rawSetI(t
, pos
, L
.value(-1)); // t[pos] = v
160 /** Implements table.maxn. */
161 private static int maxn(Lua L
)
164 L
.checkType(1, Lua
.TTABLE
);
165 LuaTable t
= (LuaTable
)L
.value(1);
166 Enumeration
<Object
> e
= t
.keys();
167 while (e
.hasMoreElements())
169 Object o
= e
.nextElement();
170 if (Lua
.type(o
) == Lua
.TNUMBER
)
172 double v
= L
.toNumber(o
);
181 /** Implements table.remove. */
182 private static int remove(Lua L
)
184 int e
= aux_getn(L
, 1);
185 int pos
= L
.optInt(2, e
);
187 return 0; // table is 'empty'
188 Object t
= L
.value(1);
189 Object o
= Lua
.rawGetI(t
, pos
); // result = t[pos]
192 L
.rawSetI(t
, pos
, Lua
.rawGetI(t
, pos
+1)); // t[pos] = t[pos+1]
194 L
.rawSetI(t
, e
, Lua
.NIL
); // t[e] = nil
199 /** Implements table.sort. */
200 private static int sort(Lua L
)
202 int n
= aux_getn(L
, 1);
203 if (!L
.isNoneOrNil(2)) // is there a 2nd argument?
204 L
.checkType(2, Lua
.TFUNCTION
);
205 L
.setTop(2); // make sure there is two arguments
210 static void auxsort(Lua L
, int l
, int u
)
212 Object t
= L
.value(1);
213 while (l
< u
) // for tail recursion
217 // sort elements a[l], a[l+u/2], and a[u]
218 Object o1
= Lua
.rawGetI(t
, l
);
219 Object o2
= Lua
.rawGetI(t
, u
);
220 if (sort_comp(L
, o2
, o1
)) // a[u] < a[l]?
226 break; // only 2 elements
228 o1
= Lua
.rawGetI(t
, i
);
229 o2
= Lua
.rawGetI(t
, l
);
230 if (sort_comp(L
, o1
, o2
)) // a[i]<a[l]?
237 o2
= Lua
.rawGetI(t
, u
);
238 if (sort_comp(L
, o2
, o1
)) // a[u]<a[i]?
245 break; // only 3 elements
246 final Object p
= Lua
.rawGetI(t
, i
); // Pivot
247 o2
= Lua
.rawGetI(t
, u
-1);
249 L
.rawSetI(t
, u
-1, p
);
250 // a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2
253 // NB: Pivot P is in p
254 while (true) // invariant: a[l..i] <= P <= a[j..u]
256 // repeat ++i until a[i] >= P
259 o1
= Lua
.rawGetI(t
, ++i
);
260 if (!sort_comp(L
, o1
, p
))
263 L
.error("invalid order function for sorting");
265 // repreat --j until a[j] <= P
268 o2
= Lua
.rawGetI(t
, --j
);
269 if (!sort_comp(L
, p
, o2
))
272 L
.error("invalid order function for sorting");
279 o1
= Lua
.rawGetI(t
, u
-1);
280 o2
= Lua
.rawGetI(t
, i
);
281 L
.rawSetI(t
, u
-1, o2
);
282 L
.rawSetI(t
, i
, o1
); // swap pivot (a[u-1]) with a[i]
283 // a[l..i-1 <= a[i] == P <= a[i+1..u]
284 // adjust so that smaller half is in [j..i] and larger one in [l..u]
297 auxsort(L
, j
, i
); // call recursively the smaller one
298 } // repeat the routine for the larger one
301 private static boolean sort_comp(Lua L
, Object a
, Object b
)
303 if (!Lua
.isNil(L
.value(2))) // function?
309 boolean res
= L
.toBoolean(L
.value(-1));
315 return L
.lessThan(a
, b
);
319 private static int aux_getn(Lua L
, int n
)
321 L
.checkType(n
, Lua
.TTABLE
);
322 LuaTable t
= (LuaTable
)L
.value(n
);