public ArrayImpl() { }
public ArrayImpl(int size) { vec.setSize(size); }
private static int intVal(Object o) {
- if (o instanceof Number) {
- int intVal = ((Number)o).intValue();
- if (intVal == ((Number)o).doubleValue()) return intVal;
- return Integer.MIN_VALUE;
- }
- if (!(o instanceof String)) return Integer.MIN_VALUE;
- String s = (String)o;
- for(int i=0; i<s.length(); i++) if (s.charAt(i) < '0' || s.charAt(i) > '9') return Integer.MIN_VALUE;
- return Integer.parseInt(s);
- }
- public Object get(Object key) throws JS.Exn {
- // FIXME: HACK!
- if (key.equals("cascade")) return org.xwt.Trap.cascadeFunction;
- if (key.equals("trapee")) return org.xwt.Trap.currentTrapee();
- if (key.equals("length")) return new Long(vec.size());
- int i = intVal(key);
- if (i == Integer.MIN_VALUE) return super.get(key);
- try {
- return vec.elementAt(i);
- } catch (ArrayIndexOutOfBoundsException e) {
- return null;
- }
- }
- public void put(Object key, Object val) {
- if (key.equals("length")) vec.setSize(toNumber(val).intValue());
- int i = intVal(key);
- if (i == Integer.MIN_VALUE) super.put(key, val);
- else {
- if (i >= vec.size()) vec.setSize(i+1);
- vec.setElementAt(val, i);
- }
+ if (o instanceof Number) {
+ int intVal = ((Number)o).intValue();
+ if (intVal == ((Number)o).doubleValue()) return intVal;
+ return Integer.MIN_VALUE;
+ }
+ if (!(o instanceof String)) return Integer.MIN_VALUE;
+ String s = (String)o;
+ for(int i=0; i<s.length(); i++) if (s.charAt(i) < '0' || s.charAt(i) > '9') return Integer.MIN_VALUE;
+ return Integer.parseInt(s);
+ }
+
+ public Object callMethod(Object method, JS.Array args,boolean justChecking) {
+ if(method.equals("push")) {
+ if(justChecking) return Boolean.TRUE;
+ for(int i=0;i<args.length();i++)
+ vec.push(args.elementAt(i));
+ return new Integer(vec.size());
+ }
+ if(method.equals("pop")) {
+ if(justChecking) return Boolean.TRUE;
+ return vec.pop(); // this'll return null on size()==0
+ }
+ if(method.equals("shift")) {
+ if(justChecking) return Boolean.TRUE;
+ if(length() > 0) {
+ Object o = vec.elementAt(0);
+ vec.removeElementAt(0);
+ return o;
+ } else {
+ return null;
+ }
+ }
+ if(method.equals("unshift")) {
+ if(justChecking) return Boolean.TRUE;
+ // FEATURE: could be optimized a bit with some help from Vec
+ for(int i=0;i<args.length();i++)
+ vec.insertElementAt(args.elementAt(i),i);
+ return new Integer(vec.size());
+ }
+ if(method.equals("slice")) return justChecking ? Boolean.TRUE : slice(args);
+ if(method.equals("join")) return justChecking ? Boolean.TRUE : join(args);
+ if(method.equals("reverse")) return justChecking ? Boolean.TRUE : reverse(args);
+ if(method.equals("toString")) return justChecking ? Boolean.TRUE : join(",");
+ if(method.equals("sort")) return justChecking ? Boolean.TRUE : sort(args);
+ if(method.equals("splice")) return justChecking ? Boolean.TRUE : splice(args);
+ return super.callMethod(method,args,justChecking);
+ }
+
+
+ // we use _get instead of get solely to work around a GCJ bug
+ public Object _get(Object key) throws JS.Exn {
+ if (key.equals("length")) return new Long(vec.size());
+
+ int i = intVal(key);
+ if (i == Integer.MIN_VALUE) return super.get(key);
+ try {
+ return vec.elementAt(i);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return null;
+ }
+ }
+ // we use _put instead of put solely to work around a GCJ bug
+ public void _put(Object key, Object val) {
+ if (key.equals("length")) vec.setSize(toNumber(val).intValue());
+ int i = intVal(key);
+ if (i == Integer.MIN_VALUE) super.put(key, val);
+ else {
+ if (i >= vec.size()) vec.setSize(i+1);
+ vec.setElementAt(val, i);
+ }
}
public Object[] keys() {
- Object[] sup = super.keys();
- Object[] ret = new Object[vec.size() + 1 + sup.length];
- System.arraycopy(sup, 0, ret, vec.size(), sup.length);
- for(int i=0; i<vec.size(); i++) ret[i] = new Integer(i);
- ret[vec.size()] = "length";
- return ret;
+ Object[] sup = super.keys();
+ Object[] ret = new Object[vec.size() + 1 + sup.length];
+ System.arraycopy(sup, 0, ret, vec.size(), sup.length);
+ for(int i=0; i<vec.size(); i++) ret[i] = new Integer(i);
+ ret[vec.size()] = "length";
+ return ret;
}
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 String typeName() { return "array"; }
+
+ private Object join(JS.Array args) {
+ return join(args.length() == 0 ? "," : JS.toString(args.elementAt(0)));
+ }
+
+ private Object join(String sep) {
+ int length = vec.size();
+ if(length == 0) return "";
+ StringBuffer sb = new StringBuffer(64);
+ int i=0;
+ while(true) {
+ Object o = elementAt(i);
+ if(o != null) sb.append(JS.toString(o));
+ if(++i == length) break;
+ sb.append(sep);
+ }
+ return sb.toString();
+ }
+
+ private Object reverse(JS.Array args) {
+ Vec oldVec = vec;
+ int size = oldVec.size();
+ if(size < 2) return this;
+ vec = new Vec(size);
+ for(int i=size-1;i>=0;i--)
+ vec.addElement(oldVec.elementAt(i));
+ return this;
+ }
+
+ private Object slice(JS.Array args) {
+ int length = length();
+ int start = JS.toInt(args.length() < 1 ? null : args.elementAt(0));
+ int end = args.length() < 2 ? length : JS.toInt(args.elementAt(1));
+ if(start < 0) start = length+start;
+ if(end < 0) end = length+end;
+ if(start < 0) start = 0;
+ if(end < 0) end = 0;
+ if(start > length) start = length;
+ if(end > length) end = length;
+ JS.Array a = new JS.Array(end-start);
+ for(int i=0;i<end-start;i++)
+ a.setElementAt(elementAt(start+i),i);
+ return a;
+ }
+
+ private static final Vec.CompareFunc defaultSort = new Vec.CompareFunc() {
+ public int compare(Object a, Object b) {
+ return JS.toString(a).compareTo(JS.toString(b));
+ }
+ };
+ private Object sort(JS.Array args) {
+ Object tmp = args.length() < 1 ? null : args.elementAt(0);
+ if(tmp instanceof JS.Callable) {
+ final JS.Array funcArgs = new JS.Array(2);
+ final JS.Callable jsFunc = (JS.Callable) 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(funcArgs));
+ }
+ });
+ } else {
+ vec.sort(defaultSort);
+ }
+ return this;
+ }
+
+ private Object splice(JS.Array args) {
+ int oldLength = length();
+ int start = JS.toInt(args.length() < 1 ? null : args.elementAt(0));
+ int deleteCount = JS.toInt(args.length() < 2 ? null : args.elementAt(1));
+ int newCount = args.length() - 2;
+ if(newCount < 0) newCount = 0;
+ if(start < 0) start = oldLength+start;
+ if(start < 0) start = 0;
+ if(start > oldLength) start = oldLength;
+ if(deleteCount < 0) deleteCount = 0;
+ if(deleteCount > oldLength-start) deleteCount = oldLength-start;
+ int newLength = oldLength - deleteCount + newCount;
+ int lengthChange = newLength - oldLength;
+ JS.Array ret = new JS.Array(deleteCount);
+ for(int i=0;i<deleteCount;i++)
+ ret.setElementAt(elementAt(start+i),i);
+ if(lengthChange > 0) {
+ setSize(newLength);
+ for(int i=newLength-1;i>=start+newCount;i--)
+ setElementAt(elementAt(i-lengthChange),i);
+ } else if(lengthChange < 0) {
+ for(int i=start+newCount;i<newLength;i++)
+ setElementAt(elementAt(i-lengthChange),i);
+ setSize(newLength);
+ }
+ for(int i=0;i<newCount;i++)
+ setElementAt(args.elementAt(i+2),start+i);
+ return ret;
+ }
+
+ public String coerceToString() { return JS.toString(join(",")); }
}
-