001: /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
002: *
003: * The contents of this file are subject to the Netscape Public
004: * License Version 1.1 (the "License"); you may not use this file
005: * except in compliance with the License. You may obtain a copy of
006: * the License at http://www.mozilla.org/NPL/
007: *
008: * Software distributed under the License is distributed on an "AS
009: * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
010: * implied. See the License for the specific language governing
011: * rights and limitations under the License.
012: *
013: * The Original Code is Rhino code, released
014: * May 6, 1999.
015: *
016: * The Initial Developer of the Original Code is Netscape
017: * Communications Corporation. Portions created by Netscape are
018: * Copyright (C) 1997-2000 Netscape Communications Corporation. All
019: * Rights Reserved.
020: *
021: * Contributor(s):
022: * Igor Bukanov
023: *
024: * Alternatively, the contents of this file may be used under the
025: * terms of the GNU Public License (the "GPL"), in which case the
026: * provisions of the GPL are applicable instead of those above.
027: * If you wish to allow use of your version of this file only
028: * under the terms of the GPL and not to allow others to use your
029: * version of this file under the NPL, indicate your decision by
030: * deleting the provisions above and replace them with the notice
031: * and other provisions required by the GPL. If you do not delete
032: * the provisions above, a recipient may use your version of this
033: * file under either the NPL or the GPL.
034: */
035: // Modified by Google
036: package com.google.gwt.dev.js.rhino;
037:
038: import java.io.Serializable;
039: import java.io.IOException;
040: import java.io.ObjectInputStream;
041: import java.io.ObjectOutputStream;
042:
043: /**
044: Implementation of resizable array with focus on minimizing memory usage by storing few initial array elements in object fields. Can also be used as a stack.
045: */
046:
047: public class ObjArray implements Serializable {
048:
049: public ObjArray() {
050: }
051:
052: public ObjArray(int capacityHint) {
053: if (capacityHint < 0)
054: throw new IllegalArgumentException();
055: if (capacityHint > FIELDS_STORE_SIZE) {
056: data = new Object[capacityHint - FIELDS_STORE_SIZE];
057: }
058: }
059:
060: public final boolean isEmpty() {
061: return size == 0;
062: }
063:
064: public final int size() {
065: return size;
066: }
067:
068: public final void setSize(int newSize) {
069: if (newSize < 0)
070: throw new IllegalArgumentException();
071: int N = size;
072: if (newSize < N) {
073: for (int i = newSize; i != N; ++i) {
074: setImpl(i, null);
075: }
076: } else if (newSize > N) {
077: if (newSize > FIELDS_STORE_SIZE) {
078: ensureCapacity(newSize);
079: }
080: }
081: size = newSize;
082: }
083:
084: public final Object get(int index) {
085: if (!(0 <= index && index < size))
086: throw invalidIndex(index, size);
087: return getImpl(index);
088: }
089:
090: public final void set(int index, Object value) {
091: if (!(0 <= index && index < size))
092: throw invalidIndex(index, size);
093: setImpl(index, value);
094: }
095:
096: private Object getImpl(int index) {
097: switch (index) {
098: case 0:
099: return f0;
100: case 1:
101: return f1;
102: case 2:
103: return f2;
104: case 3:
105: return f3;
106: case 4:
107: return f4;
108: case 5:
109: return f5;
110: }
111: return data[index - FIELDS_STORE_SIZE];
112: }
113:
114: private void setImpl(int index, Object value) {
115: switch (index) {
116: case 0:
117: f0 = value;
118: break;
119: case 1:
120: f1 = value;
121: break;
122: case 2:
123: f2 = value;
124: break;
125: case 3:
126: f3 = value;
127: break;
128: case 4:
129: f4 = value;
130: break;
131: case 5:
132: f5 = value;
133: break;
134: default:
135: data[index - FIELDS_STORE_SIZE] = value;
136: }
137:
138: }
139:
140: public int indexOf(Object obj) {
141: int N = size;
142: for (int i = 0; i != N; ++i) {
143: Object current = getImpl(i);
144: if (current == obj
145: || (current != null && current.equals(obj))) {
146: return i;
147: }
148: }
149: return -1;
150: }
151:
152: public int lastIndexOf(Object obj) {
153: for (int i = size; i != 0;) {
154: --i;
155: Object current = getImpl(i);
156: if (current == obj
157: || (current != null && current.equals(obj))) {
158: return i;
159: }
160: }
161: return -1;
162: }
163:
164: public final Object peek() {
165: int N = size;
166: if (N == 0)
167: throw invalidEmptyStackAccess();
168: return getImpl(N - 1);
169: }
170:
171: public final Object pop() {
172: int N = size;
173: --N;
174: Object top;
175: switch (N) {
176: case -1:
177: throw invalidEmptyStackAccess();
178: case 0:
179: top = f0;
180: f0 = null;
181: break;
182: case 1:
183: top = f1;
184: f1 = null;
185: break;
186: case 2:
187: top = f2;
188: f2 = null;
189: break;
190: case 3:
191: top = f3;
192: f3 = null;
193: break;
194: case 4:
195: top = f4;
196: f4 = null;
197: break;
198: case 5:
199: top = f5;
200: f5 = null;
201: break;
202: default:
203: top = data[N - FIELDS_STORE_SIZE];
204: data[N - FIELDS_STORE_SIZE] = null;
205: }
206: size = N;
207: return top;
208: }
209:
210: public final void push(Object value) {
211: add(value);
212: }
213:
214: public final void add(Object value) {
215: int N = size;
216: if (N >= FIELDS_STORE_SIZE) {
217: ensureCapacity(N + 1);
218: }
219: size = N + 1;
220: setImpl(N, value);
221: }
222:
223: public final void add(int index, Object value) {
224: Object tmp;
225: int N = size;
226: if (!(0 <= index && index <= N))
227: throw invalidIndex(index, N + 1);
228: switch (index) {
229: case 0:
230: if (N == 0) {
231: f0 = value;
232: break;
233: }
234: tmp = f0;
235: f0 = value;
236: value = tmp;
237: case 1:
238: if (N == 1) {
239: f1 = value;
240: break;
241: }
242: tmp = f1;
243: f1 = value;
244: value = tmp;
245: case 2:
246: if (N == 2) {
247: f2 = value;
248: break;
249: }
250: tmp = f2;
251: f2 = value;
252: value = tmp;
253: case 3:
254: if (N == 3) {
255: f3 = value;
256: break;
257: }
258: tmp = f3;
259: f3 = value;
260: value = tmp;
261: case 4:
262: if (N == 4) {
263: f4 = value;
264: break;
265: }
266: tmp = f4;
267: f4 = value;
268: value = tmp;
269: case 5:
270: if (N == 5) {
271: f5 = value;
272: break;
273: }
274: tmp = f5;
275: f5 = value;
276: value = tmp;
277:
278: index = FIELDS_STORE_SIZE;
279: default:
280: ensureCapacity(N + 1);
281: if (index != N) {
282: System.arraycopy(data, index - FIELDS_STORE_SIZE, data,
283: index - FIELDS_STORE_SIZE + 1, N - index);
284: }
285: data[index - FIELDS_STORE_SIZE] = value;
286: }
287: size = N + 1;
288: }
289:
290: public final void remove(int index) {
291: int N = size;
292: if (!(0 <= index && index < N))
293: throw invalidIndex(index, N);
294: --N;
295: switch (index) {
296: case 0:
297: if (N == 0) {
298: f0 = null;
299: break;
300: }
301: f0 = f1;
302: case 1:
303: if (N == 1) {
304: f1 = null;
305: break;
306: }
307: f1 = f2;
308: case 2:
309: if (N == 2) {
310: f2 = null;
311: break;
312: }
313: f2 = f3;
314: case 3:
315: if (N == 3) {
316: f3 = null;
317: break;
318: }
319: f3 = f4;
320: case 4:
321: if (N == 4) {
322: f4 = null;
323: break;
324: }
325: f4 = f5;
326: case 5:
327: if (N == 5) {
328: f5 = null;
329: break;
330: }
331: f5 = data[0];
332:
333: index = FIELDS_STORE_SIZE;
334: default:
335: if (index != N) {
336: System.arraycopy(data, index - FIELDS_STORE_SIZE + 1,
337: data, index - FIELDS_STORE_SIZE, N - index);
338: }
339: data[N - FIELDS_STORE_SIZE] = null;
340: }
341: size = N;
342: }
343:
344: public final void clear() {
345: int N = size;
346: for (int i = 0; i != N; ++i) {
347: setImpl(i, null);
348: }
349: size = 0;
350: }
351:
352: public final Object[] toArray() {
353: Object[] array = new Object[size];
354: toArray(array, 0);
355: return array;
356: }
357:
358: public final void toArray(Object[] array) {
359: toArray(array, 0);
360: }
361:
362: public final void toArray(Object[] array, int offset) {
363: int N = size;
364: switch (N) {
365: default:
366: System.arraycopy(data, 0, array,
367: offset + FIELDS_STORE_SIZE, N - FIELDS_STORE_SIZE);
368: case 6:
369: array[offset + 5] = f5;
370: case 5:
371: array[offset + 4] = f4;
372: case 4:
373: array[offset + 3] = f3;
374: case 3:
375: array[offset + 2] = f2;
376: case 2:
377: array[offset + 1] = f1;
378: case 1:
379: array[offset + 0] = f0;
380: case 0:
381: break;
382: }
383: }
384:
385: private void ensureCapacity(int minimalCapacity) {
386: int required = minimalCapacity - FIELDS_STORE_SIZE;
387: if (required <= 0)
388: throw new IllegalArgumentException();
389: if (data == null) {
390: int alloc = FIELDS_STORE_SIZE * 2;
391: if (alloc < required) {
392: alloc = required;
393: }
394: data = new Object[alloc];
395: } else {
396: int alloc = data.length;
397: if (alloc < required) {
398: if (alloc <= FIELDS_STORE_SIZE) {
399: alloc = FIELDS_STORE_SIZE * 2;
400: } else {
401: alloc *= 2;
402: }
403: if (alloc < required) {
404: alloc = required;
405: }
406: Object[] tmp = new Object[alloc];
407: if (size > FIELDS_STORE_SIZE) {
408: System.arraycopy(data, 0, tmp, 0, size
409: - FIELDS_STORE_SIZE);
410: }
411: data = tmp;
412: }
413: }
414: }
415:
416: private static RuntimeException invalidIndex(int index,
417: int upperBound) {
418: // \u2209 is "NOT ELEMENT OF"
419: String msg = index + " \u2209 [0, " + upperBound + ')';
420: return new IndexOutOfBoundsException(msg);
421: }
422:
423: private static RuntimeException invalidEmptyStackAccess() {
424: throw new RuntimeException("Empty stack");
425: }
426:
427: private void writeObject(ObjectOutputStream os) throws IOException {
428: os.defaultWriteObject();
429: int N = size;
430: for (int i = 0; i != N; ++i) {
431: Object obj = getImpl(i);
432: os.writeObject(obj);
433: }
434: }
435:
436: private void readObject(ObjectInputStream is) throws IOException,
437: ClassNotFoundException {
438: is.defaultReadObject(); // It reads size
439: int N = size;
440: if (N > FIELDS_STORE_SIZE) {
441: data = new Object[N - FIELDS_STORE_SIZE];
442: }
443: for (int i = 0; i != N; ++i) {
444: Object obj = is.readObject();
445: setImpl(i, obj);
446: }
447: }
448:
449: static final long serialVersionUID = 7448768847663119705L;
450:
451: // Number of data elements
452: private int size;
453:
454: private static final int FIELDS_STORE_SIZE = 6;
455: private transient Object f0, f1, f2, f3, f4, f5;
456: private transient Object[] data;
457: }
|