Add support for metatags to table lib methods: sort, insert, remove, unpack.
```
do -- testing table library with metamethods
local function test (proxy, t)
for i = 1, 10 do
table.insert(proxy, 1, i)
end
assert(#proxy == 10 and #t == 10, tostring(#proxy)..'; '..tostring(#t))
for i = 1, 10 do
assert(t[i] == 11 - i)
end
table.sort(proxy)
for i = 1, 10 do
assert(t[i] == i and proxy[i] == i, i..': '..tostring(proxy[i])..'; '..tostring(t[i]))
end
assert(table.concat(proxy, ",") == "1,2,3,4,5,6,7,8,9,10")
for i = 1, 8 do
assert(table.remove(proxy, 1) == i)
end
assert(#proxy == 2 and #t == 2)
local a, b, c = table.unpack(proxy)
assert(a == 9 and b == 10 and c == nil)
end
-- all virtual
local t = {}
local proxy = setmetatable({}, {
__len = function () return #t end,
__index = t,
__newindex = t,
})
test(proxy, t)
-- only __newindex
local count = 0
t = setmetatable({}, {
__newindex = function (t,k,v) count = count + 1; rawset(t,k,v) end})
test(t, t)
assert(count == 10) -- after first 10, all other sets are not new
-- no __newindex
t = setmetatable({}, {
__index = function (_,k) return k + 1 end,
__len = function (_) return 5 end})
assert(table.concat(t, ";") == "2;3;4;5;6")
end
function check (a, f)
f = f or function (x,y) return x<y end;
for n = #a, 2, -1 do
local cmp = f(a[n], a[n-1])
if cmp then print(tostring(a)..'\n'..n..': "'..tostring(a[n])..'" < "'..tostring(a[n-1])..'"') end
assert(not cmp)
end
end
for b = 1, 2 do
a = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"}
if b == 2 then a[15] = 'Aaa' a[14] = 'Iii' a[13] = 'Mmm' end
print(#a)
table.sort(a)
check(a)
end
```
This commit is contained in:
@@ -299,15 +299,15 @@ public class LuaTable extends LuaValue implements Metatable {
|
||||
* @return The removed item, or {@link #NONE} if not removed
|
||||
*/
|
||||
public LuaValue remove(int pos) {
|
||||
int n = rawlen();
|
||||
int n = length();
|
||||
if ( pos == 0 )
|
||||
pos = n;
|
||||
else if (pos > n)
|
||||
return NONE;
|
||||
LuaValue v = rawget(pos);
|
||||
LuaValue v = get(pos);
|
||||
for ( LuaValue r=v; !r.isnil(); ) {
|
||||
r = rawget(pos+1);
|
||||
rawset(pos++, r);
|
||||
r = get(pos+1);
|
||||
set(pos++, r);
|
||||
}
|
||||
return v.isnil()? NONE: v;
|
||||
}
|
||||
@@ -319,10 +319,10 @@ public class LuaTable extends LuaValue implements Metatable {
|
||||
*/
|
||||
public void insert(int pos, LuaValue value) {
|
||||
if ( pos == 0 )
|
||||
pos = rawlen()+1;
|
||||
pos = length()+1;
|
||||
while ( ! value.isnil() ) {
|
||||
LuaValue v = rawget( pos );
|
||||
rawset(pos++, value);
|
||||
LuaValue v = get( pos );
|
||||
set(pos++, value);
|
||||
value = v;
|
||||
}
|
||||
}
|
||||
@@ -789,40 +789,35 @@ public class LuaTable extends LuaValue implements Metatable {
|
||||
if (m_metatable != null && m_metatable.useWeakValues()) {
|
||||
dropWeakArrayValues();
|
||||
}
|
||||
LuaValue[] array = this.array;
|
||||
int n = array.length;
|
||||
while ( n > 0 && array[n-1] == null )
|
||||
--n;
|
||||
int n = length();
|
||||
if ( n > 1 )
|
||||
heapSort(n, comparator.isnil() ? null : comparator);
|
||||
}
|
||||
|
||||
private void heapSort(int count, LuaValue cmpfunc) {
|
||||
heapify(count, cmpfunc);
|
||||
LuaValue[] array = this.array;
|
||||
for ( int end=count-1; end>0; ) {
|
||||
LuaValue a = array[end]; // swap(end, 0)
|
||||
array[end] = array[0];
|
||||
array[0] = a;
|
||||
siftDown(0, --end, cmpfunc);
|
||||
for ( int end=count; end>1; ) {
|
||||
LuaValue a = get(end); // swap(end, 1)
|
||||
set(end, get(1));
|
||||
set(1, a);
|
||||
siftDown(1, --end, cmpfunc);
|
||||
}
|
||||
}
|
||||
|
||||
private void heapify(int count, LuaValue cmpfunc) {
|
||||
for ( int start=count/2-1; start>=0; --start )
|
||||
siftDown(start, count - 1, cmpfunc);
|
||||
for ( int start=count/2; start>0; --start )
|
||||
siftDown(start, count, cmpfunc);
|
||||
}
|
||||
|
||||
private void siftDown(int start, int end, LuaValue cmpfunc) {
|
||||
LuaValue[] array = this.array;
|
||||
for ( int root=start; root*2+1 <= end; ) {
|
||||
int child = root*2+1;
|
||||
for ( int root=start; root*2 <= end; ) {
|
||||
int child = root*2;
|
||||
if (child < end && compare(child, child + 1, cmpfunc))
|
||||
++child;
|
||||
if (compare(root, child, cmpfunc)) {
|
||||
LuaValue a = array[root]; // swap(root, child)
|
||||
array[root] = array[child];
|
||||
array[child] = a;
|
||||
LuaValue a = get(root); // swap(root, child)
|
||||
set(root, get(child));
|
||||
set(child, a);
|
||||
root = child;
|
||||
} else
|
||||
return;
|
||||
@@ -830,16 +825,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
||||
}
|
||||
|
||||
private boolean compare(int i, int j, LuaValue cmpfunc) {
|
||||
LuaValue a, b;
|
||||
LuaValue[] array = this.array;
|
||||
Metatable m_metatable = this.m_metatable;
|
||||
if (m_metatable == null) {
|
||||
a = array[i];
|
||||
b = array[j];
|
||||
} else {
|
||||
a = m_metatable.arrayget(array, i);
|
||||
b = m_metatable.arrayget(array, j);
|
||||
}
|
||||
LuaValue a = get(i), b = get(j);
|
||||
if ( a == null || b == null )
|
||||
return false;
|
||||
if ( cmpfunc != null ) {
|
||||
|
||||
@@ -151,7 +151,7 @@ public class TableLib extends TwoArgFunction {
|
||||
public Varargs invoke(Varargs args) {
|
||||
LuaTable t = args.checktable(1);
|
||||
// do not waste resource for calc rawlen if arg3 is not nil
|
||||
int len = args.arg(3).isnil() ? t.rawlen() : 0;
|
||||
int len = args.arg(3).isnil() ? t.length() : 0;
|
||||
return t.unpack(args.optint(2, 1), args.optint(3, len));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user