diff src/luan/LuaTable.java @ 44:57054fa43189

implement table lib git-svn-id: https://luan-java.googlecode.com/svn/trunk@45 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Wed, 26 Dec 2012 23:53:25 +0000
parents e51906de0f11
children a443637829c1
line wrap: on
line diff
--- a/src/luan/LuaTable.java	Tue Dec 25 03:42:42 2012 +0000
+++ b/src/luan/LuaTable.java	Wed Dec 26 23:53:25 2012 +0000
@@ -1,23 +1,83 @@
 package luan;
 
 import java.util.Iterator;
+import java.util.ListIterator;
 import java.util.Map;
 import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 
 
 public class LuaTable {
-	private final Map<Object,Object> map = new HashMap<Object,Object>();
-	private LuaTable metatable;
+	private Map<Object,Object> map = null;
+	private List<Object> list = null;
+	private LuaTable metatable = null;
+
+	public LuaTable() {}
+
+	public LuaTable(List<Object> list) {
+		this.list = list;
+	}
 
 	@Override public String toString() {
 		return "table: " + Integer.toHexString(hashCode());
 	}
 
 	public Object get(Object key) {
+		if( list != null && key instanceof LuaNumber ) {
+			LuaNumber ln = (LuaNumber)key;
+			int i = (int)ln.n;
+			if( i == ln.n ) {
+				i--;
+				if( i>=0 && i<list.size() )
+					return list.get(i);
+			}
+		}
+		if( map==null )
+			return null;
 		return map.get(key);
 	}
 
 	public Object put(Object key,Object val) {
+		if( key instanceof LuaNumber ) {
+			LuaNumber ln = (LuaNumber)key;
+			int i = (int)ln.n;
+			if( i == ln.n ) {
+				i--;
+				if( list == null && i == 0 )
+					list = new ArrayList<Object>();
+				if( list != null ) {
+					if( i == list.size() ) {
+						if( val != null ) {
+							list.add(val);
+							if( map != null ) {
+								while(true) {
+									Object v = map.remove(LuaNumber.of(list.size()+1));
+									if( v == null )
+										break;
+									list.add(v);
+								}
+							}
+						}
+						return null;
+					} else if( i>=0 && i<list.size() ) {
+						Object old = list.get(i);
+						list.set(i,val);
+						if( val == null && i == list.size()-1 ) {
+							while( i>=0 && list.get(i)==null ) {
+								list.remove(i--);
+							}
+						}
+						return old;
+					}
+				}
+			}
+		}
+		if( map==null ) {
+			map = new HashMap<Object,Object>();
+		}
 		if( val == null ) {
 			return map.remove(key);
 		} else {
@@ -25,16 +85,82 @@
 		}
 	}
 
+	public void insert(int pos,Object value) {
+		if( list == null )
+			list = new ArrayList<Object>();
+		list.add(pos-1,value);
+	}
+
+	public Object remove(int pos) {
+		if( list == null )
+			list = new ArrayList<Object>();
+		return list.remove(pos-1);
+	}
+
+	public void sort(Comparator<Object> cmp) {
+		if( list != null )
+			Collections.sort(list,cmp);
+	}
+
 	public int length() {
-		int i = 0;
-		while( map.containsKey( new LuaNumber(i) ) ) {
-			i++;
-		}
-		return i;
+		return list==null ? 0 : list.size();
 	}
 
 	public Iterator<Map.Entry<Object,Object>> iterator() {
-		return map.entrySet().iterator();
+		if( list == null ) {
+			if( map == null )
+				return Collections.<Map.Entry<Object,Object>>emptyList().iterator();
+			return map.entrySet().iterator();
+		}
+		if( map == null )
+			return listIterator();
+		return new Iterator<Map.Entry<Object,Object>>() {
+			Iterator<Map.Entry<Object,Object>> iter = listIterator();
+			boolean isList = true;
+			public boolean hasNext() {
+				boolean b = iter.hasNext();
+				if( !b && isList ) {
+					iter = map.entrySet().iterator();
+					isList = false;
+					b = iter.hasNext();
+				}
+				return b;
+			}
+			public Map.Entry<Object,Object> next() {
+				return iter.next();
+			}
+			public void remove() {
+				throw new UnsupportedOperationException();
+			}
+		};
+	}
+
+	public Iterator<Map.Entry<Object,Object>> listIterator() {
+		if( list == null )
+			return Collections.<Map.Entry<Object,Object>>emptyList().iterator();
+		final ListIterator iter = list.listIterator();
+		return new Iterator<Map.Entry<Object,Object>>() {
+			public boolean hasNext() {
+				return iter.hasNext();
+			}
+			public Map.Entry<Object,Object> next() {
+				LuaNumber key = LuaNumber.of(iter.nextIndex()+1);
+				return new MapEntry(key,iter.next());
+			}
+			public void remove() {
+				throw new UnsupportedOperationException();
+			}
+		};
+	}
+
+	public Object[] listToArray() {
+		return list==null ? new Object[0] : list.toArray();
+	}
+
+	public LuaTable subList(int from,int to) {
+		if( list == null )
+			list = new ArrayList<Object>();
+		return new LuaTable(new ArrayList<Object>(list.subList(from-1,to-1)));
 	}
 
 	public LuaTable getMetatable() {
@@ -44,4 +170,26 @@
 	public void setMetatable(LuaTable metatable) {
 		this.metatable = metatable;
 	}
+
+	private static final class MapEntry implements Map.Entry<Object,Object> {
+		private final Object key;
+		private final Object value;
+
+		MapEntry(Object key,Object value) {
+			this.key = key;
+			this.value = value;
+		}
+
+		@Override public Object getKey() {
+			return key;
+		}
+
+		@Override public Object getValue() {
+			return value;
+		}
+
+		@Override public Object setValue(Object value) {
+			throw new UnsupportedOperationException();
+		}
+	}
 }