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
|
* @return The removed item, or {@link #NONE} if not removed
|
||||||
*/
|
*/
|
||||||
public LuaValue remove(int pos) {
|
public LuaValue remove(int pos) {
|
||||||
int n = rawlen();
|
int n = length();
|
||||||
if ( pos == 0 )
|
if ( pos == 0 )
|
||||||
pos = n;
|
pos = n;
|
||||||
else if (pos > n)
|
else if (pos > n)
|
||||||
return NONE;
|
return NONE;
|
||||||
LuaValue v = rawget(pos);
|
LuaValue v = get(pos);
|
||||||
for ( LuaValue r=v; !r.isnil(); ) {
|
for ( LuaValue r=v; !r.isnil(); ) {
|
||||||
r = rawget(pos+1);
|
r = get(pos+1);
|
||||||
rawset(pos++, r);
|
set(pos++, r);
|
||||||
}
|
}
|
||||||
return v.isnil()? NONE: v;
|
return v.isnil()? NONE: v;
|
||||||
}
|
}
|
||||||
@@ -319,10 +319,10 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
*/
|
*/
|
||||||
public void insert(int pos, LuaValue value) {
|
public void insert(int pos, LuaValue value) {
|
||||||
if ( pos == 0 )
|
if ( pos == 0 )
|
||||||
pos = rawlen()+1;
|
pos = length()+1;
|
||||||
while ( ! value.isnil() ) {
|
while ( ! value.isnil() ) {
|
||||||
LuaValue v = rawget( pos );
|
LuaValue v = get( pos );
|
||||||
rawset(pos++, value);
|
set(pos++, value);
|
||||||
value = v;
|
value = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -789,40 +789,35 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
if (m_metatable != null && m_metatable.useWeakValues()) {
|
if (m_metatable != null && m_metatable.useWeakValues()) {
|
||||||
dropWeakArrayValues();
|
dropWeakArrayValues();
|
||||||
}
|
}
|
||||||
LuaValue[] array = this.array;
|
int n = length();
|
||||||
int n = array.length;
|
|
||||||
while ( n > 0 && array[n-1] == null )
|
|
||||||
--n;
|
|
||||||
if ( n > 1 )
|
if ( n > 1 )
|
||||||
heapSort(n, comparator.isnil() ? null : comparator);
|
heapSort(n, comparator.isnil() ? null : comparator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void heapSort(int count, LuaValue cmpfunc) {
|
private void heapSort(int count, LuaValue cmpfunc) {
|
||||||
heapify(count, cmpfunc);
|
heapify(count, cmpfunc);
|
||||||
LuaValue[] array = this.array;
|
for ( int end=count; end>1; ) {
|
||||||
for ( int end=count-1; end>0; ) {
|
LuaValue a = get(end); // swap(end, 1)
|
||||||
LuaValue a = array[end]; // swap(end, 0)
|
set(end, get(1));
|
||||||
array[end] = array[0];
|
set(1, a);
|
||||||
array[0] = a;
|
siftDown(1, --end, cmpfunc);
|
||||||
siftDown(0, --end, cmpfunc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void heapify(int count, LuaValue cmpfunc) {
|
private void heapify(int count, LuaValue cmpfunc) {
|
||||||
for ( int start=count/2-1; start>=0; --start )
|
for ( int start=count/2; start>0; --start )
|
||||||
siftDown(start, count - 1, cmpfunc);
|
siftDown(start, count, cmpfunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void siftDown(int start, int end, LuaValue cmpfunc) {
|
private void siftDown(int start, int end, LuaValue cmpfunc) {
|
||||||
LuaValue[] array = this.array;
|
for ( int root=start; root*2 <= end; ) {
|
||||||
for ( int root=start; root*2+1 <= end; ) {
|
int child = root*2;
|
||||||
int child = root*2+1;
|
|
||||||
if (child < end && compare(child, child + 1, cmpfunc))
|
if (child < end && compare(child, child + 1, cmpfunc))
|
||||||
++child;
|
++child;
|
||||||
if (compare(root, child, cmpfunc)) {
|
if (compare(root, child, cmpfunc)) {
|
||||||
LuaValue a = array[root]; // swap(root, child)
|
LuaValue a = get(root); // swap(root, child)
|
||||||
array[root] = array[child];
|
set(root, get(child));
|
||||||
array[child] = a;
|
set(child, a);
|
||||||
root = child;
|
root = child;
|
||||||
} else
|
} else
|
||||||
return;
|
return;
|
||||||
@@ -830,16 +825,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean compare(int i, int j, LuaValue cmpfunc) {
|
private boolean compare(int i, int j, LuaValue cmpfunc) {
|
||||||
LuaValue a, b;
|
LuaValue a = get(i), b = get(j);
|
||||||
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);
|
|
||||||
}
|
|
||||||
if ( a == null || b == null )
|
if ( a == null || b == null )
|
||||||
return false;
|
return false;
|
||||||
if ( cmpfunc != null ) {
|
if ( cmpfunc != null ) {
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ public class TableLib extends TwoArgFunction {
|
|||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
LuaTable t = args.checktable(1);
|
LuaTable t = args.checktable(1);
|
||||||
// do not waste resource for calc rawlen if arg3 is not nil
|
// 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));
|
return t.unpack(args.optint(2, 1), args.optint(3, len));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user