1
2
3 package org.xwt.js;
4 import org.xwt.util.*;
5 import java.io.*;
6 import java.util.*;
7
8
9 class ArrayImpl extends JS.Obj {
10 private Vec vec = new Vec();
11 public ArrayImpl() { }
12 public ArrayImpl(int size) { vec.setSize(size); }
13 private static int intVal(Object o) {
14 if (o instanceof Number) {
15 int intVal = ((Number)o).intValue();
16 if (intVal == ((Number)o).doubleValue()) return intVal;
17 return Integer.MIN_VALUE;
18 }
19 if (!(o instanceof String)) return Integer.MIN_VALUE;
20 String s = (String)o;
21 for(int i=0; i<s.length(); i++) if (s.charAt(i) < '0' || s.charAt(i) > '9') return Integer.MIN_VALUE;
22 return Integer.parseInt(s);
23 }
24
25 public Object callMethod(Object method, JS.Array args,boolean justChecking) {
26 if(method.equals("push")) {
27 if(justChecking) return Boolean.TRUE;
28 for(int i=0;i<args.length();i++)
29 vec.push(args.elementAt(i));
30 return new Integer(vec.size());
31 }
32 if(method.equals("pop")) {
33 if(justChecking) return Boolean.TRUE;
34 return vec.pop();
35 }
36 if(method.equals("shift")) {
37 if(justChecking) return Boolean.TRUE;
38 if(length() > 0) {
39 Object o = vec.elementAt(0);
40 vec.removeElementAt(0);
41 return o;
42 } else {
43 return null;
44 }
45 }
46 if(method.equals("unshift")) {
47 if(justChecking) return Boolean.TRUE;
48
49 for(int i=0;i<args.length();i++)
50 vec.insertElementAt(args.elementAt(i),i);
51 return new Integer(vec.size());
52 }
53 if(method.equals("slice")) return justChecking ? Boolean.TRUE : slice(args);
54 if(method.equals("join")) return justChecking ? Boolean.TRUE : join(args);
55 if(method.equals("reverse")) return justChecking ? Boolean.TRUE : reverse(args);
56 if(method.equals("toString")) return justChecking ? Boolean.TRUE : join(",");
57 if(method.equals("sort")) return justChecking ? Boolean.TRUE : sort(args);
58 if(method.equals("splice")) return justChecking ? Boolean.TRUE : splice(args);
59 return super.callMethod(method,args,justChecking);
60 }
61
62
63
64 public Object _get(Object key) throws JS.Exn {
65 if (key.equals("length")) return new Long(vec.size());
66
67 int i = intVal(key);
68 if (i == Integer.MIN_VALUE) return super.get(key);
69 try {
70 return vec.elementAt(i);
71 } catch (ArrayIndexOutOfBoundsException e) {
72 return null;
73 }
74 }
75
76 public void _put(Object key, Object val) {
77 if (key.equals("length")) vec.setSize(toNumber(val).intValue());
78 int i = intVal(key);
79 if (i == Integer.MIN_VALUE) super.put(key, val);
80 else {
81 if (i >= vec.size()) vec.setSize(i+1);
82 vec.setElementAt(val, i);
83 }
84 }
85 public Object[] keys() {
86 Object[] sup = super.keys();
87 Object[] ret = new Object[vec.size() + 1 + sup.length];
88 System.arraycopy(sup, 0, ret, vec.size(), sup.length);
89 for(int i=0; i<vec.size(); i++) ret[i] = new Integer(i);
90 ret[vec.size()] = "length";
91 return ret;
92 }
93 public void setSize(int i) { vec.setSize(i); }
94 public int length() { return vec.size(); }
95 public Object elementAt(int i) { return vec.elementAt(i); }
96 public void addElement(Object o) { vec.addElement(o); }
97 public void setElementAt(Object o, int i) { vec.setElementAt(o, i); }
98
99 public String typeName() { return "array"; }
100
101 private Object join(JS.Array args) {
102 return join(args.length() == 0 ? "," : JS.toString(args.elementAt(0)));
103 }
104
105 private Object join(String sep) {
106 int length = vec.size();
107 if(length == 0) return "";
108 StringBuffer sb = new StringBuffer(64);
109 int i=0;
110 while(true) {
111 Object o = elementAt(i);
112 if(o != null) sb.append(JS.toString(o));
113 if(++i == length) break;
114 sb.append(sep);
115 }
116 return sb.toString();
117 }
118
119 private Object reverse(JS.Array args) {
120 Vec oldVec = vec;
121 int size = oldVec.size();
122 if(size < 2) return this;
123 vec = new Vec(size);
124 for(int i=size-1;i>=0;i--)
125 vec.addElement(oldVec.elementAt(i));
126 return this;
127 }
128
129 private Object slice(JS.Array args) {
130 int length = length();
131 int start = JS.toInt(args.length() < 1 ? null : args.elementAt(0));
132 int end = args.length() < 2 ? length : JS.toInt(args.elementAt(1));
133 if(start < 0) start = length+start;
134 if(end < 0) end = length+end;
135 if(start < 0) start = 0;
136 if(end < 0) end = 0;
137 if(start > length) start = length;
138 if(end > length) end = length;
139 JS.Array a = new JS.Array(end-start);
140 for(int i=0;i<end-start;i++)
141 a.setElementAt(elementAt(start+i),i);
142 return a;
143 }
144
145 private static final Vec.CompareFunc defaultSort = new Vec.CompareFunc() {
146 public int compare(Object a, Object b) {
147 return JS.toString(a).compareTo(JS.toString(b));
148 }
149 };
150 private Object sort(JS.Array args) {
151 Object tmp = args.length() < 1 ? null : args.elementAt(0);
152 if(tmp instanceof JS.Callable) {
153 final JS.Array funcArgs = new JS.Array(2);
154 final JS.Callable jsFunc = (JS.Callable) tmp;
155 vec.sort(new Vec.CompareFunc() {
156 public int compare(Object a, Object b) {
157 funcArgs.setElementAt(a,0);
158 funcArgs.setElementAt(b,1);
159 return JS.toInt(jsFunc.call(funcArgs));
160 }
161 });
162 } else {
163 vec.sort(defaultSort);
164 }
165 return this;
166 }
167
168 private Object splice(JS.Array args) {
169 int oldLength = length();
170 int start = JS.toInt(args.length() < 1 ? null : args.elementAt(0));
171 int deleteCount = JS.toInt(args.length() < 2 ? null : args.elementAt(1));
172 int newCount = args.length() - 2;
173 if(newCount < 0) newCount = 0;
174 if(start < 0) start = oldLength+start;
175 if(start < 0) start = 0;
176 if(start > oldLength) start = oldLength;
177 if(deleteCount < 0) deleteCount = 0;
178 if(deleteCount > oldLength-start) deleteCount = oldLength-start;
179 int newLength = oldLength - deleteCount + newCount;
180 int lengthChange = newLength - oldLength;
181 JS.Array ret = new JS.Array(deleteCount);
182 for(int i=0;i<deleteCount;i++)
183 ret.setElementAt(elementAt(start+i),i);
184 if(lengthChange > 0) {
185 setSize(newLength);
186 for(int i=newLength-1;i>=start+newCount;i--)
187 setElementAt(elementAt(i-lengthChange),i);
188 } else if(lengthChange < 0) {
189 for(int i=start+newCount;i<newLength;i++)
190 setElementAt(elementAt(i-lengthChange),i);
191 setSize(newLength);
192 }
193 for(int i=0;i<newCount;i++)
194 setElementAt(args.elementAt(i+2),start+i);
195 return ret;
196 }
197
198 public String coerceToString() { return JS.toString(join(",")); }
199 }
200