-// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL]
+// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
package org.xwt.js;
import org.xwt.util.*;
-import java.io.*;
import java.util.*;
/** A JavaScript JSArray */
-public class JSArray extends JSCallable {
- private Vec vec = new Vec();
+public class JSArray extends JS {
+ private static final Object NULL = new Object();
+
public JSArray() { }
- public JSArray(int size) { vec.setSize(size); }
+ public JSArray(int size) { setSize(size); }
+
private static int intVal(Object o) {
if (o instanceof Number) {
int intVal = ((Number)o).intValue();
return Integer.parseInt(s);
}
- public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) {
+ public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
//#switch(method)
- case "pop": return vec.pop();
+ case "pop": {
+ int oldSize = size();
+ if(oldSize == 0) return null;
+ return removeElementAt(oldSize-1);
+ }
case "reverse": return reverse();
case "toString": return join(",");
case "shift":
if(length() == 0) return null;
- Object o = vec.elementAt(0);
- vec.removeElementAt(0);
- return o;
+ return removeElementAt(0);
case "join":
return join(nargs == 0 ? "," : JS.toString(a0));
case "sort":
int start = toInt(nargs < 1 ? null : a0);
int end = nargs < 2 ? length() : toInt(a1);
return slice(start, end);
- case "push":
- for(int i=0; i<nargs; i++) vec.push(i==0?a0:i==1?a1:i==2?a2:rest[i-3]);
- return N(vec.size());
+ case "push": {
+ int oldSize = size();
+ for(int i=0; i<nargs; i++) insertElementAt(i==0?a0:i==1?a1:i==2?a2:rest[i-3],oldSize+i);
+ return N(oldSize + nargs);
+ }
case "unshift":
- for(int i=0; i<nargs; i++) vec.insertElementAt(i==0?a0:i==1?a1:i==2?a2:rest[i-3], i);
- return N(vec.size());
+ for(int i=0; i<nargs; i++) insertElementAt(i==0?a0:i==1?a1:i==2?a2:rest[i-3],i);
+ return N(size());
case "splice":
JSArray array = new JSArray();
for(int i=0; i<nargs; i++) array.addElement(i==0?a0:i==1?a1:i==2?a2:rest[i-3]);
return super.callMethod(method, a0, a1, a2, rest, nargs);
}
- public Object get(Object key) throws JS.Exn {
- if (key instanceof Number) {
- int i = intVal(key);
- if (i == Integer.MIN_VALUE) return super.get(key);
- try {
- return vec.elementAt(i);
- } catch (ArrayIndexOutOfBoundsException e) {
- return null;
- }
+ public Object get(Object key) throws JSExn {
+ int i = intVal(key);
+ if (i != Integer.MIN_VALUE) {
+ if (i < 0 || i >= size()) return null;
+ return elementAt(i);
}
//#switch(key)
case "pop": return METHOD;
case "push": return METHOD;
case "unshift": return METHOD;
case "splice": return METHOD;
- case "length": return N(vec.size());
+ case "length": return N(size());
//#end
return super.get(key);
}
- public void put(Object key, Object val) {
- if (key.equals("length")) vec.setSize(toNumber(val).intValue());
+ public void put(Object key, Object val) throws JSExn {
+ if (key.equals("length")) setSize(toInt(val));
int i = intVal(key);
- if (i == Integer.MIN_VALUE) super.put(key, val);
+ if (i == Integer.MIN_VALUE)
+ super.put(key, val);
else {
- if (i >= vec.size()) vec.setSize(i+1);
- vec.setElementAt(val, i);
+ int oldSize = size();
+ if(i < oldSize) {
+ setElementAt(val,i);
+ } else {
+ if(i > oldSize) setSize(i);
+ insertElementAt(val,i);
+ }
}
}
public Enumeration keys() {
return new Enumeration() {
int cur = 0;
- public boolean hasMoreElements() { return cur >= vec.size(); }
+ public boolean hasMoreElements() { return cur >= size(); }
public Object nextElement() {
- if (cur >= vec.size()) throw new NoSuchElementException();
+ if (cur >= size()) throw new NoSuchElementException();
return new Integer(cur++);
}
};
}
- public void setSize(int i) { vec.setSize(i); }
- public int length() { return vec.size(); }
- public Object elementAt(int i) { return vec.elementAt(i); }
- public void addElement(Object o) { vec.addElement(o); }
- public void setElementAt(Object o, int i) { vec.setElementAt(o, i); }
- public int size() { return vec.size(); }
+ public final void setSize(int newSize) {
+ // FEATURE: This could be done a lot more efficiently in BalancedTree
+ int oldSize = size();
+ for(int i=oldSize;i<newSize;i++) insertElementAt(null,i);
+ for(int i=oldSize-1;i>=newSize;i--) removeElementAt(i);
+ }
+
+ public final int length() { return size(); }
+ public final Object elementAt(int i) {
+ if(i < 0 || i >= size()) throw new ArrayIndexOutOfBoundsException(i);
+ Object o = getNode(i);
+ return o == NULL ? null : o;
+ }
+ public final void addElement(Object o) {
+ insertNode(size(),o==null ? NULL : o);
+ }
+ public final void setElementAt(Object o, int i) {
+ if(i < 0 || i >= size()) throw new ArrayIndexOutOfBoundsException(i);
+ replaceNode(i,o==null ? NULL : o);
+ }
+ public final void insertElementAt(Object o, int i) {
+ if(i < 0 || i > size()) throw new ArrayIndexOutOfBoundsException(i);
+ insertNode(i,o==null ? NULL : o);
+ }
+ public final Object removeElementAt(int i) {
+ if(i < 0 || i >= size()) throw new ArrayIndexOutOfBoundsException(i);
+ Object o = deleteNode(i);
+ return o == NULL ? null : o;
+ }
+
+ public final int size() { return treeSize(); }
public String typeName() { return "array"; }
private Object join(String sep) {
- int length = vec.size();
+ int length = size();
if(length == 0) return "";
StringBuffer sb = new StringBuffer(64);
int i=0;
return sb.toString();
}
+ // FEATURE: Implement this more efficiently
private Object reverse() {
- Vec oldVec = vec;
- int size = oldVec.size();
+ int size = size();
if(size < 2) return this;
- vec = new Vec(size);
- for(int i=size-1;i>=0;i--) vec.addElement(oldVec.elementAt(i));
+ Vec vec = toVec();
+ clear();
+ for(int i=size-1,j=0;i>=0;i--,j++) insertElementAt(vec.elementAt(i),j);
return this;
}
return JS.toString(a).compareTo(JS.toString(b));
}
};
- private Object sort(Object tmp) {
- if(tmp instanceof JSCallable) {
+ private Object sort(Object tmp) throws JSExn {
+ Vec vec = toVec();
+ if(tmp instanceof JS) {
final JSArray funcArgs = new JSArray(2);
- final JSCallable jsFunc = (JSCallable) tmp;
+ final JS jsFunc = (JS) tmp;
vec.sort(new Vec.CompareFunc() {
public int compare(Object a, Object b) {
- funcArgs.setElementAt(a,0);
- funcArgs.setElementAt(b,1);
- return JS.toInt(jsFunc.call(a, b, null, null, 2));
+ try {
+ funcArgs.setElementAt(a,0);
+ funcArgs.setElementAt(b,1);
+ return JS.toInt(jsFunc.call(a, b, null, null, 2));
+ } catch (Exception e) {
+ // FIXME
+ throw new JSRuntimeExn(e.toString());
+ }
}
});
} else {
vec.sort(defaultSort);
}
+ setFromVec(vec);
return this;
}
return ret;
}
- public String coerceToString() { return JS.toString(join(",")); }
+ protected Vec toVec() {
+ int count = size();
+ Vec vec = new Vec();
+ vec.setSize(count);
+ for(int i=0;i<count;i++) {
+ Object o = getNode(i);
+ vec.setElementAt(o == NULL ? null : o,i);
+ }
+ return vec;
+ }
+
+ protected void setFromVec(Vec vec) {
+ int count = vec.size();
+ clear();
+ for(int i=0;i<count;i++) {
+ Object o = vec.elementAt(i);
+ insertNode(i,o==null ? NULL : o);
+ }
+ }
+
+ public String toString() { return JS.toString(join(",")); }
}