moved ProxyAutoConfig.java from org.ibex.net.HTTP to this package
[org.ibex.js.git] / src / org / ibex / js / JSArray.java
index 5d6738e..e8529c6 100644 (file)
@@ -5,25 +5,29 @@
 package org.ibex.js; 
 
 import java.io.InputStream;
-import java.util.*;
 import org.ibex.util.*; 
-import org.ibex.util.Collections;
 
 /** A JavaScript JSArray */
-class JSArray extends ArrayList implements JS, Comparator {
+public class JSArray extends Basket.Array implements JS, Basket.CompareFunc {
     private static final JS.Method METHOD = new JS.Method();
     private static final String[] empty = new String[0];
 
-    JSArray() { }
-    JSArray(int size) { super(size); }
-    JSArray(JS[] args) { super(args.length); addAll(args); }
-    JSArray(JS arg) { super(1); add(arg); }
+    public JSArray() { }
+    public JSArray(int size) { super(size); }
+    public JSArray(JS[] args) { super(args.length); addAll(args); }
+    public JSArray(JS arg) { super(1); add(arg); }
 
     public JS unclone() { return this; }
-    public JS.Enumeration keys() throws JSExn { return new Enumeration.RandomAccessList(null, this); }
+    public JS.Enumeration keys() throws JSExn {
+        return new Enumeration(null) {
+            private int n = 0;
+            public boolean _hasNext() { return n < size(); }
+            public JS _next() { return JSU.N(n++); }
+        };
+    }
     public JS get(JS key) throws JSExn {
         if (key == null || !(key instanceof JSNumber.I)) {
-            //#switch(Script.str(key))
+            //#switch(JSU.str(key))
             case "pop": return METHOD;
             case "reverse": return METHOD;
             case "toString": return METHOD;
@@ -34,56 +38,46 @@ class JSArray extends ArrayList implements JS, Comparator {
             case "push": return METHOD;
             case "unshift": return METHOD;
             case "splice": return METHOD;
-            case "length": return Script.N(size());
+            case "length": return JSU.N(size());
             //#end
-            throw new JSExn("arrays only support positive integer keys, can not use: "+Script.str(key));
+            throw new JSExn("arrays only support positive integer keys, can not use: "+JSU.str(key));
         }
         return (JS)get(((JSNumber.I)key).toInt());
     }
     public void put(JS key, JS val) throws JSExn {
-        if (Script.str(key).equals("length")) { setSize(Script.toInt(val)); }
+        if (JSU.str(key).equals("length")) { setSize(JSU.toInt(val)); }
 
         if (key == null || !(key instanceof JSNumber.I)) throw new JSExn(
-            "arrays only support positive integer keys, can not use: "+Script.str(key));
+            "arrays only support positive integer keys, can not use: "+JSU.str(key));
         int i = ((JSNumber.I)key).toInt();
         if (i < 0) throw new JSExn("arrays can not use negative integer keys "+i);
-        ensureCapacity(i + 1); while (size() < i) add(null);
+        if (size() < i+1) size(i + 1);
+       //while (size() < i) add(null);
         set(i, val);
     }
-    public InputStream getInputStream() { return null; }
 
     public String[] getFormalArgs() { return empty; }
-    public String coerceToString() { return "array"; } // FIXME
-
-    public boolean hasKey(JS key) {
-        if (key == null || !(key instanceof JSNumber.I)) return false;
-        int i = ((JSNumber.I)key).toInt();
-        return 0 <= i && i < size();
-    }
+    public String coerceToString() throws JSExn { throw new JSExn("cannot coerce a "+getClass().getName()+" to a string"); }
 
-    public Object run(Object o) throws JSExn { return call(null); }
-    public void pause() throws NotPausableException { throw new NotPausableException(); }
-    public JS call(JS[] args) throws JSExn { throw new JSExn("can not call an array as a function"); }
     public JS call(JS method, JS[] args) throws JSExn {
-        //#switch(Script.str(method))
+        //#switch(JSU.str(method))
         case "pop": return size() == 0 ? null : (JS)remove(size() - 1);
-        case "push": addAll(args); return Script.N(size());
-        case "reverse": Collections.reverse(this); return this;
+        case "push": addAll(args); return JSU.N(size());
+        case "reverse": reverse(); return this;
         case "toString": return join(",");
         case "shift": return size() == 0 ? null : (JS)remove(0);
-        case "join": return join(args.length == 0 ? "," : Script.str(args[0]));
+        case "join": return join(args.length == 0 ? "," : JSU.str(args[0]));
         case "sort": return sort(args.length == 0 ? null : args[0]);
         case "slice":
-            int start = Script.toInt(args.length < 1 ? null : args[0]);
-            int end = args.length < 2 ? size() : Script.toInt(args[1]);
+            int start = JSU.toInt(args.length < 1 ? null : args[0]);
+            int end = args.length < 2 ? size() : JSU.toInt(args[1]);
             return slice(start, end);
         case "unshift":
             for (int i=0; i < args.length; i++) add(i, args[i]);
-            return Script.N(size());
+            return JSU.N(size());
         case "splice": return splice(args);
         //#end
-
-        throw new JSExn("arrays have no function: "+Script.str(method));
+        throw new JSExn("arrays have no function: "+JSU.str(method));
     }
 
     public JS putAndTriggerTraps(JS key, JS val) throws JSExn { put(key, val); return val; }
@@ -92,13 +86,13 @@ class JSArray extends ArrayList implements JS, Comparator {
 
     public void addTrap(JS k, JS f) throws JSExn { throw new JSExn("arrays do not support traps"); }
     public void delTrap(JS k, JS f) throws JSExn { throw new JSExn("arrays do not support traps"); }
-    public JS.Trap getTrap(JS k) throws JSExn { throw new JSExn("arrays do not support traps"); }
+    public JS.Trap getTrap(JS k) throws JSExn { return null; }
 
-    /** FIXME: move to specialised ArrayStore superclass. */
+    /** FEATURE: move to specialised ArrayStore superclass. */
     public void addAll(JS[] entries) { for (int i=0; i < entries.length; i++) add(entries[i]); }
 
     public void setSize(int newSize) {
-        ensureCapacity(newSize);
+        size(newSize);
         for (int i=size(); i < newSize; i++) add(null);
         for (int i=size() - 1; i >= newSize; i--) remove(i);
     }
@@ -108,16 +102,16 @@ class JSArray extends ArrayList implements JS, Comparator {
 
     private JS join(String sep) throws JSExn {
         int length = size();
-        if(length == 0) return JS.S("");
+        if(length == 0) return JSU.S("");
         StringBuffer sb = new StringBuffer(64);
         int i=0;
         while(true) {
             JS o = (JS)get(i);
-            if(o != null) sb.append(Script.toString(o));
+            if(o != null) sb.append(JSU.toString(o));
             if(++i == length) break;
             sb.append(sep);
         }
-        return JS.S(sb.toString());
+        return JSU.S(sb.toString());
     }
  
     private JS slice(int start, int end) {
@@ -129,15 +123,15 @@ class JSArray extends ArrayList implements JS, Comparator {
         if(start > length) start = length;
         if(end > length) end = length;
         JSArray a = new JSArray(end-start);
-        for(int i=0;i<end-start;i++) // FIXME: with ArrayStore do System.arraycopy()
+        for(int i=0;i<end-start;i++) // FEATURE: with ArrayStore do System.arraycopy()
             a.set(i, get(start+i));
         return a;
     }
 
     private JS splice(JS[] args) throws JSExn {
         int oldLength = size();
-        int start = Script.toInt(args.length < 1 ? null : args[0]);
-        int deleteCount = Script.toInt(args.length < 2 ? null : args[1]);
+        int start = JSU.toInt(args.length < 1 ? null : args[0]);
+        int deleteCount = JSU.toInt(args.length < 2 ? null : args[1]);
         int newCount = args.length - 2;
         if(newCount < 0) newCount = 0;
         if(start < 0) start = oldLength+start;
@@ -148,7 +142,7 @@ class JSArray extends ArrayList implements JS, Comparator {
         int newLength = oldLength - deleteCount + newCount;
         int lengthChange = newLength - oldLength;
         JSArray ret = new JSArray(deleteCount);
-        for(int i=0;i<deleteCount;i++) // FIXME: ArrayStore System.arraycopy()
+        for(int i=0;i<deleteCount;i++) // FEATURE: ArrayStore System.arraycopy()
             ret.set(i, get(start+i));
         if(lengthChange > 0) {
             setSize(newLength);
@@ -164,20 +158,27 @@ class JSArray extends ArrayList implements JS, Comparator {
         return ret;
     }
 
+    private static final Basket.CompareFunc defaultSort = new Basket.CompareFunc() {
+        public int compare(Object a, Object b) {
+            try { return JSU.toString((JS)a).compareTo(JSU.toString((JS)b)); }
+            catch (JSExn e) { throw new JSExn.Wrapper(e); }
+        }
+    };
     private JS sort(JS comparator) throws JSExn {
         try {
-            if (comparator == null) Collections.sort(this);
-            else { sort = comparator; Collections.sort(this, this); }
+            if (comparator == null) sort(defaultSort);
+            else { sort = comparator; sort((CompareFunc)this); }
             return this;
-        } catch (JSExn.Wrapper w) { throw w.unwrap(); }
+        } catch (JSExn.Wrapper w) { throw w.unwrap();
+        } finally { sort = null; }
     }
 
     private JS sort = null;
     private final JS[] sortargs = new JS[2];
-    public int compare(java.lang.Object a, java.lang.Object b) throws JSExn.Wrapper {
+    public int compare(Object a, Object b) throws JSExn.Wrapper {
         try {
             sortargs[0] = (JS)a; sortargs[1] = (JS)b;
-            return Script.toInt(sort.call(sortargs));
+            return JSU.toInt(sort.call(null, sortargs));
         } catch (JSExn e) { throw new JSExn.Wrapper(e);
         } finally { sortargs[0] = null; sortargs[1] = null; }
     }