Mercurial Hosting > luan
comparison src/luan/LuanTable.java @ 1267:9fa8b8389578
add LuanTable.luan;
support metatable __gc();
add luan.sql;
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Mon, 12 Nov 2018 02:10:41 -0700 |
parents | 73d754b1889f |
children | 503bde9a7c80 |
comparison
equal
deleted
inserted
replaced
1266:05934fbf635a | 1267:9fa8b8389578 |
---|---|
12 import java.util.Set; | 12 import java.util.Set; |
13 import java.util.HashSet; | 13 import java.util.HashSet; |
14 | 14 |
15 | 15 |
16 public final class LuanTable implements LuanCloneable { | 16 public final class LuanTable implements LuanCloneable { |
17 private LuanState luan; | |
17 private Map map = null; | 18 private Map map = null; |
18 private List list = null; | 19 private List list = null; |
19 private LuanTable metatable = null; | 20 private LuanTable metatable = null; |
20 public LuanJavaOk javaOk; | 21 public LuanJavaOk javaOk; |
21 private LuanCloner cloner; | 22 private LuanCloner cloner; |
22 | 23 |
23 public LuanTable() {} | 24 public LuanTable(LuanState luan) { |
24 | 25 this.luan = luan; |
25 public LuanTable(List list) { | 26 } |
27 | |
28 public LuanTable(LuanState luan,List list) { | |
26 int n = list.size(); | 29 int n = list.size(); |
27 for( int i=0; i<n; i++ ) { | 30 for( int i=0; i<n; i++ ) { |
28 Object val = list.get(i); | 31 Object val = list.get(i); |
29 if( val != null ) | 32 if( val != null ) |
30 rawPut(i+1,val); | 33 rawPut(i+1,val); |
31 } | 34 } |
32 } | 35 } |
33 | 36 |
34 public LuanTable(Map map) { | 37 public LuanTable(LuanState luan,Map map) { |
38 this.luan = luan; | |
35 for( Object stupid : map.entrySet() ) { | 39 for( Object stupid : map.entrySet() ) { |
36 Map.Entry entry = (Map.Entry)stupid; | 40 Map.Entry entry = (Map.Entry)stupid; |
37 Object key = entry.getKey(); | 41 Object key = entry.getKey(); |
38 Object value = entry.getValue(); | 42 Object value = entry.getValue(); |
39 if( key != null && value != null ) | 43 if( key != null && value != null ) |
40 rawPut(key,value); | 44 rawPut(key,value); |
41 } | 45 } |
42 } | 46 } |
43 | 47 |
44 public LuanTable(Set set) { | 48 public LuanTable(LuanState luan,Set set) { |
49 this.luan = luan; | |
45 for( Object el : set ) { | 50 for( Object el : set ) { |
46 if( el != null ) | 51 if( el != null ) |
47 rawPut(el,Boolean.TRUE); | 52 rawPut(el,Boolean.TRUE); |
48 } | 53 } |
49 } | 54 } |
50 | 55 |
51 public LuanTable(LuanTable tbl) { | 56 public LuanTable(LuanTable tbl) { |
57 this.luan = tbl.luan; | |
52 if( tbl.map != null && !tbl.map.isEmpty() ) | 58 if( tbl.map != null && !tbl.map.isEmpty() ) |
53 this.map = new LinkedHashMap<Object,Object>(tbl.map); | 59 this.map = new LinkedHashMap<Object,Object>(tbl.map); |
54 if( tbl.rawLength() > 0 ) | 60 if( tbl.rawLength() > 0 ) |
55 this.list = new ArrayList<Object>(tbl.list); | 61 this.list = new ArrayList<Object>(tbl.list); |
56 this.metatable = tbl.metatable; | 62 this.metatable = tbl.metatable; |
57 } | 63 } |
58 | 64 |
59 @Override public LuanTable shallowClone() { | 65 @Override public LuanTable shallowClone() { |
60 return new LuanTable(); | 66 return new LuanTable(luan); |
61 } | 67 } |
62 | 68 |
63 @Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) { | 69 @Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) { |
64 check(); | 70 check(); |
65 LuanTable clone = (LuanTable)dc; | 71 LuanTable clone = (LuanTable)dc; |
83 cloner = null; | 89 cloner = null; |
84 } | 90 } |
85 } | 91 } |
86 | 92 |
87 private void deepenClone(LuanTable clone,LuanCloner cloner) { | 93 private void deepenClone(LuanTable clone,LuanCloner cloner) { |
94 clone.luan = (LuanState)cloner.clone(luan); | |
88 if( map != null ) { | 95 if( map != null ) { |
89 Map newMap = newMap(); | 96 Map newMap = newMap(); |
90 for( Object stupid : map.entrySet() ) { | 97 for( Object stupid : map.entrySet() ) { |
91 Map.Entry entry = (Map.Entry)stupid; | 98 Map.Entry entry = (Map.Entry)stupid; |
92 newMap.put( cloner.get(entry.getKey()), cloner.get(entry.getValue()) ); | 99 newMap.put( cloner.get(entry.getKey()), cloner.get(entry.getValue()) ); |
116 public Map rawMap() { | 123 public Map rawMap() { |
117 check(); | 124 check(); |
118 return map!=null ? map : Collections.emptyMap(); | 125 return map!=null ? map : Collections.emptyMap(); |
119 } | 126 } |
120 | 127 |
121 public String toString(LuanState luan) throws LuanException { | 128 public String toStringLuan() throws LuanException { |
122 Object h = getHandler(luan,"__to_string"); | 129 Object h = getHandler("__to_string"); |
123 if( h == null ) | 130 if( h == null ) |
124 return rawToString(); | 131 return rawToString(); |
125 LuanFunction fn = Luan.checkFunction(h); | 132 LuanFunction fn = Luan.checkFunction(h); |
126 return Luan.checkString( Luan.first( fn.call(luan,new Object[]{this}) ) ); | 133 return Luan.checkString( Luan.first( fn.call(luan,new Object[]{this}) ) ); |
127 } | 134 } |
128 | 135 |
129 public String rawToString() { | 136 public String rawToString() { |
130 return "table: " + Integer.toHexString(hashCode()); | 137 return "table: " + Integer.toHexString(hashCode()); |
131 } | 138 } |
132 | 139 |
133 public Object get(LuanState luan,Object key) throws LuanException { | 140 public Object get(Object key) throws LuanException { |
134 Object value = rawGet(key); | 141 Object value = rawGet(key); |
135 if( value != null ) | 142 if( value != null ) |
136 return value; | 143 return value; |
137 Object h = getHandler(luan,"__index"); | 144 Object h = getHandler("__index"); |
138 if( h==null ) | 145 if( h==null ) |
139 return null; | 146 return null; |
140 if( h instanceof LuanFunction ) { | 147 if( h instanceof LuanFunction ) { |
141 LuanFunction fn = (LuanFunction)h; | 148 LuanFunction fn = (LuanFunction)h; |
142 return Luan.first(fn.call(luan,new Object[]{this,key})); | 149 return Luan.first(fn.call(luan,new Object[]{this,key})); |
161 key = Double.valueOf(n.doubleValue()); | 168 key = Double.valueOf(n.doubleValue()); |
162 } | 169 } |
163 return map.get(key); | 170 return map.get(key); |
164 } | 171 } |
165 | 172 |
166 public void put(LuanState luan,Object key,Object value) throws LuanException { | 173 public void put(Object key,Object value) throws LuanException { |
167 Object h = getHandler(luan,"__new_index"); | 174 Object h = getHandler("__new_index"); |
168 if( h==null || rawGet(key)!=null ) { | 175 if( h==null || rawGet(key)!=null ) { |
169 rawPut(key,value); | 176 rawPut(key,value); |
170 return; | 177 return; |
171 } | 178 } |
172 if( h instanceof LuanFunction ) { | 179 if( h instanceof LuanFunction ) { |
174 fn.call(luan,new Object[]{this,key,value}); | 181 fn.call(luan,new Object[]{this,key,value}); |
175 return; | 182 return; |
176 } | 183 } |
177 if( h instanceof LuanTable ) { | 184 if( h instanceof LuanTable ) { |
178 LuanTable tbl = (LuanTable)h; | 185 LuanTable tbl = (LuanTable)h; |
179 tbl.put(luan,key,value); | 186 tbl.put(key,value); |
180 return; | 187 return; |
181 } | 188 } |
182 throw new LuanException("invalid type "+Luan.type(h)+" for metamethod __new_index"); | 189 throw new LuanException("invalid type "+Luan.type(h)+" for metamethod __new_index"); |
183 } | 190 } |
184 | 191 |
265 public void rawSort(Comparator<Object> cmp) { | 272 public void rawSort(Comparator<Object> cmp) { |
266 check(); | 273 check(); |
267 Collections.sort(list(),cmp); | 274 Collections.sort(list(),cmp); |
268 } | 275 } |
269 | 276 |
270 public int length(LuanState luan) throws LuanException { | 277 public int length() throws LuanException { |
271 Object h = getHandler(luan,"__len"); | 278 Object h = getHandler("__len"); |
272 if( h != null ) { | 279 if( h != null ) { |
273 LuanFunction fn = Luan.checkFunction(h); | 280 LuanFunction fn = Luan.checkFunction(h); |
274 return (Integer)Luan.first(fn.call(luan,new Object[]{this})); | 281 return (Integer)Luan.first(fn.call(luan,new Object[]{this})); |
275 } | 282 } |
276 return rawLength(); | 283 return rawLength(); |
279 public int rawLength() { | 286 public int rawLength() { |
280 check(); | 287 check(); |
281 return list==null ? 0 : list.size(); | 288 return list==null ? 0 : list.size(); |
282 } | 289 } |
283 | 290 |
284 public Iterable<Map.Entry> iterable(LuanState luan) throws LuanException { | 291 public Iterable<Map.Entry> iterable() throws LuanException { |
285 final Iterator<Map.Entry> iter = iterator(luan); | 292 final Iterator<Map.Entry> iter = iterator(); |
286 return new Iterable<Map.Entry>() { | 293 return new Iterable<Map.Entry>() { |
287 public Iterator<Map.Entry> iterator() { | 294 public Iterator<Map.Entry> iterator() { |
288 return iter; | 295 return iter; |
289 } | 296 } |
290 }; | 297 }; |
297 return iter; | 304 return iter; |
298 } | 305 } |
299 }; | 306 }; |
300 } | 307 } |
301 | 308 |
302 public Iterator<Map.Entry> iterator(final LuanState luan) throws LuanException { | 309 public Iterator<Map.Entry> iterator() throws LuanException { |
303 if( getHandler(luan,"__pairs") == null ) | 310 if( getHandler("__pairs") == null ) |
304 return rawIterator(); | 311 return rawIterator(); |
305 final LuanFunction fn = pairs(luan); | 312 final LuanFunction fn = pairs(); |
306 return new Iterator<Map.Entry>() { | 313 return new Iterator<Map.Entry>() { |
307 private Map.Entry<Object,Object> next = getNext(); | 314 private Map.Entry<Object,Object> next = getNext(); |
308 | 315 |
309 private Map.Entry<Object,Object> getNext() { | 316 private Map.Entry<Object,Object> getNext() { |
310 try { | 317 try { |
334 throw new UnsupportedOperationException(); | 341 throw new UnsupportedOperationException(); |
335 } | 342 } |
336 }; | 343 }; |
337 } | 344 } |
338 | 345 |
339 public LuanFunction pairs(LuanState luan) throws LuanException { | 346 public LuanFunction pairs() throws LuanException { |
340 Object h = getHandler(luan,"__pairs"); | 347 Object h = getHandler("__pairs"); |
341 if( h != null ) { | 348 if( h != null ) { |
342 if( h instanceof LuanFunction ) { | 349 if( h instanceof LuanFunction ) { |
343 LuanFunction fn = (LuanFunction)h; | 350 LuanFunction fn = (LuanFunction)h; |
344 Object obj = Luan.first(fn.call(luan,new Object[]{this})); | 351 Object obj = Luan.first(fn.call(luan,new Object[]{this})); |
345 if( !(obj instanceof LuanFunction) ) | 352 if( !(obj instanceof LuanFunction) ) |
418 }; | 425 }; |
419 } | 426 } |
420 | 427 |
421 public LuanTable rawSubList(int from,int to) { | 428 public LuanTable rawSubList(int from,int to) { |
422 check(); | 429 check(); |
423 LuanTable tbl = new LuanTable(); | 430 LuanTable tbl = new LuanTable(luan); |
424 tbl.list = new ArrayList<Object>(list().subList(from-1,to-1)); | 431 tbl.list = new ArrayList<Object>(list().subList(from-1,to-1)); |
425 return tbl; | 432 return tbl; |
426 } | 433 } |
427 | 434 |
428 public LuanTable getMetatable() { | 435 public LuanTable getMetatable() { |
433 public void setMetatable(LuanTable metatable) { | 440 public void setMetatable(LuanTable metatable) { |
434 check(); | 441 check(); |
435 this.metatable = metatable; | 442 this.metatable = metatable; |
436 } | 443 } |
437 | 444 |
438 public Object getHandler(LuanState luan,String op) throws LuanException { | 445 public Object getHandler(String op) throws LuanException { |
439 check(); | 446 check(); |
440 return metatable==null ? null : metatable.get(luan,op); | 447 return metatable==null ? null : metatable.get(op); |
441 } | 448 } |
442 | 449 |
443 private Map<Object,Object> newMap() { | 450 private Map<Object,Object> newMap() { |
444 return new LinkedHashMap<Object,Object>(); | 451 return new LinkedHashMap<Object,Object>(); |
445 } | 452 } |
446 | 453 |
447 public boolean isSet(LuanState luan) throws LuanException { | 454 public boolean isSet() throws LuanException { |
448 for( Map.Entry<Object,Object> entry : iterable(luan) ) { | 455 for( Map.Entry<Object,Object> entry : iterable() ) { |
449 if( !entry.getValue().equals(Boolean.TRUE) ) | 456 if( !entry.getValue().equals(Boolean.TRUE) ) |
450 return false; | 457 return false; |
451 } | 458 } |
452 return true; | 459 return true; |
453 } | 460 } |
454 | 461 |
455 public Set<Object> asSet(LuanState luan) throws LuanException { | 462 public Set<Object> asSet() throws LuanException { |
456 Set<Object> set = new HashSet<Object>(); | 463 Set<Object> set = new HashSet<Object>(); |
457 for( Map.Entry<Object,Object> entry : iterable(luan) ) { | 464 for( Map.Entry<Object,Object> entry : iterable() ) { |
458 set.add(entry.getKey()); | 465 set.add(entry.getKey()); |
459 } | 466 } |
460 return set; | 467 return set; |
461 } | 468 } |
462 | 469 |
463 public Map<Object,Object> asMap(LuanState luan) throws LuanException { | 470 public Map<Object,Object> asMap() throws LuanException { |
464 Map<Object,Object> map = newMap(); | 471 Map<Object,Object> map = newMap(); |
465 for( Map.Entry<Object,Object> entry : iterable(luan) ) { | 472 for( Map.Entry<Object,Object> entry : iterable() ) { |
466 map.put(entry.getKey(),entry.getValue()); | 473 map.put(entry.getKey(),entry.getValue()); |
467 } | 474 } |
468 return map; | 475 return map; |
469 } | 476 } |
470 | 477 |
493 n += map.size(); | 500 n += map.size(); |
494 if( list != null ) | 501 if( list != null ) |
495 n += list.size(); | 502 n += list.size(); |
496 return n; | 503 return n; |
497 } | 504 } |
505 | |
506 protected void finalize() throws Throwable { | |
507 Object h = getHandler("__gc"); | |
508 if( h != null ) { | |
509 LuanFunction fn = Luan.checkFunction(h); | |
510 fn.call(luan,new Object[]{this}); | |
511 } | |
512 super.finalize(); | |
513 } | |
514 | |
498 } | 515 } |