/
KahluaArray.java
162 lines (142 loc) · 3.85 KB
/
KahluaArray.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package se.krka.kahlua.vm;
public class KahluaArray implements KahluaTable {
private KahluaTable metatable;
private Object[] data;
private int len;
private boolean recalculateLen;
public KahluaArray() {
data = new Object[16];
len = 0;
}
public int len() {
if (recalculateLen) {
int index = this.len - 1;
Object[] data = this.data;
while (index >= 0) {
if (data[index] != null) {
break;
}
index--;
}
this.len = index + 1;
recalculateLen = false;
}
return len;
}
public KahluaTableIterator iterator() {
return new KahluaTableIterator() {
private Double curKey;
private Object curValue;
private int index = 1;
public int call(LuaCallFrame callFrame, int nArguments) {
if (advance()) {
return callFrame.push(getKey(), getValue());
}
return 0;
}
public boolean advance() {
while (true) {
if (index > len()) {
return false;
}
Object value = rawget(index);
if (value != null) {
int localIndex = index;
index++;
curKey = KahluaUtil.toDouble(localIndex);
curValue = value;
return true;
}
index++;
}
}
public Object getKey() {
return curKey;
}
public Object getValue() {
return curValue;
}
};
}
public boolean isEmpty() {
return len() == 0;
}
public void wipe() {
for (int i = 0; i < data.length; i++) {
data[i] = null;
}
len = 0;
}
public Object rawget(int index) {
if (index < 1 || index > len) {
return null;
}
return data[(index - 1)];
}
public void rawset(int index, Object value) {
if (index <= 0) {
KahluaUtil.fail("Index out of range: " + index);
}
if (index >= len) {
if (value == null) {
if (index == len) {
data[index - 1] = value;
recalculateLen = true;
}
return;
}
if (data.length < index) {
int newMaxLen = 2 * index;
int newCap = newMaxLen - 1;
Object[] newData = new Object[newCap];
System.arraycopy(data, 0, newData, 0, len);
data = newData;
}
len = index;
}
data[(index - 1)] = value;
}
private int getKeyIndex(Object key) {
if (key instanceof Double) {
Double d = (Double) key;
return d.intValue();
}
return -1;
}
public Object rawget(Object key) {
int index = getKeyIndex(key);
return rawget(index);
}
public void rawset(Object key, Object value) {
int index = getKeyIndex(key);
if (index == -1) {
KahluaUtil.fail("Invalid table key: " + key);
}
rawset(index, value);
}
public Object next(Object key) {
int index;
if (key == null) {
index = 0;
} else {
index = getKeyIndex(key);
if (index <= 0 || index > len) {
KahluaUtil.fail("invalid key to 'next'");
return null;
}
}
while (index < len) {
if (data[index] != null) {
return KahluaUtil.toDouble(index + 1);
}
index++;
}
return null;
}
public KahluaTable getMetatable() {
return metatable;
}
public void setMetatable(KahluaTable metatable) {
this.metatable = metatable;
}
}