/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1997-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * Igor Bukanov * * Alternatively, the contents of this file may be used under the * terms of the GNU Public License (the "GPL"), in which case the * provisions of the GPL are applicable instead of those above. * If you wish to allow use of your version of this file only * under the terms of the GPL and not to allow others to use your * version of this file under the NPL, indicate your decision by * deleting the provisions above and replace them with the notice * and other provisions required by the GPL. If you do not delete * the provisions above, a recipient may use your version of this * file under either the NPL or the GPL. */ // Modified by Google package com.google.gwt.dev.js.rhino; import java.io.Serializable; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** 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. */ public class ObjArray implements Serializable { public ObjArray() { } public ObjArray(int capacityHint) { if (capacityHint < 0) throw new IllegalArgumentException(); if (capacityHint > FIELDS_STORE_SIZE) { data = new Object[capacityHint - FIELDS_STORE_SIZE]; } } public final boolean isEmpty() { return size == 0; } public final int size() { return size; } public final void setSize(int newSize) { if (newSize < 0) throw new IllegalArgumentException(); int N = size; if (newSize < N) { for (int i = newSize; i != N; ++i) { setImpl(i, null); } }else if (newSize > N) { if (newSize > FIELDS_STORE_SIZE) { ensureCapacity(newSize); } } size = newSize; } public final Object get(int index) { if (!(0 <= index && index < size)) throw invalidIndex(index, size); return getImpl(index); } public final void set(int index, Object value) { if (!(0 <= index && index < size)) throw invalidIndex(index, size); setImpl(index, value); } private Object getImpl(int index) { switch (index) { case 0: return f0; case 1: return f1; case 2: return f2; case 3: return f3; case 4: return f4; case 5: return f5; } return data[index - FIELDS_STORE_SIZE]; } private void setImpl(int index, Object value) { switch (index) { case 0: f0 = value; break; case 1: f1 = value; break; case 2: f2 = value; break; case 3: f3 = value; break; case 4: f4 = value; break; case 5: f5 = value; break; default: data[index - FIELDS_STORE_SIZE] = value; } } public int indexOf(Object obj) { int N = size; for (int i = 0; i != N; ++i) { Object current = getImpl(i); if (current == obj || (current != null && current.equals(obj))) { return i; } } return -1; } public int lastIndexOf(Object obj) { for (int i = size; i != 0;) { --i; Object current = getImpl(i); if (current == obj || (current != null && current.equals(obj))) { return i; } } return -1; } public final Object peek() { int N = size; if (N == 0) throw invalidEmptyStackAccess(); return getImpl(N - 1); } public final Object pop() { int N = size; --N; Object top; switch (N) { case -1: throw invalidEmptyStackAccess(); case 0: top = f0; f0 = null; break; case 1: top = f1; f1 = null; break; case 2: top = f2; f2 = null; break; case 3: top = f3; f3 = null; break; case 4: top = f4; f4 = null; break; case 5: top = f5; f5 = null; break; default: top = data[N - FIELDS_STORE_SIZE]; data[N - FIELDS_STORE_SIZE] = null; } size = N; return top; } public final void push(Object value) { add(value); } public final void add(Object value) { int N = size; if (N >= FIELDS_STORE_SIZE) { ensureCapacity(N + 1); } size = N + 1; setImpl(N, value); } public final void add(int index, Object value) { Object tmp; int N = size; if (!(0 <= index && index <= N)) throw invalidIndex(index, N + 1); switch (index) { case 0: if (N == 0) { f0 = value; break; } tmp = f0; f0 = value; value = tmp; case 1: if (N == 1) { f1 = value; break; } tmp = f1; f1 = value; value = tmp; case 2: if (N == 2) { f2 = value; break; } tmp = f2; f2 = value; value = tmp; case 3: if (N == 3) { f3 = value; break; } tmp = f3; f3 = value; value = tmp; case 4: if (N == 4) { f4 = value; break; } tmp = f4; f4 = value; value = tmp; case 5: if (N == 5) { f5 = value; break; } tmp = f5; f5 = value; value = tmp; index = FIELDS_STORE_SIZE; default: ensureCapacity(N + 1); if (index != N) { System.arraycopy(data, index - FIELDS_STORE_SIZE, data, index - FIELDS_STORE_SIZE + 1, N - index); } data[index - FIELDS_STORE_SIZE] = value; } size = N + 1; } public final void remove(int index) { int N = size; if (!(0 <= index && index < N)) throw invalidIndex(index, N); --N; switch (index) { case 0: if (N == 0) { f0 = null; break; } f0 = f1; case 1: if (N == 1) { f1 = null; break; } f1 = f2; case 2: if (N == 2) { f2 = null; break; } f2 = f3; case 3: if (N == 3) { f3 = null; break; } f3 = f4; case 4: if (N == 4) { f4 = null; break; } f4 = f5; case 5: if (N == 5) { f5 = null; break; } f5 = data[0]; index = FIELDS_STORE_SIZE; default: if (index != N) { System.arraycopy(data, index - FIELDS_STORE_SIZE + 1, data, index - FIELDS_STORE_SIZE, N - index); } data[N - FIELDS_STORE_SIZE] = null; } size = N; } public final void clear() { int N = size; for (int i = 0; i != N; ++i) { setImpl(i, null); } size = 0; } public final Object[] toArray() { Object[] array = new Object[size]; toArray(array, 0); return array; } public final void toArray(Object[] array) { toArray(array, 0); } public final void toArray(Object[] array, int offset) { int N = size; switch (N) { default: System.arraycopy(data, 0, array, offset + FIELDS_STORE_SIZE, N - FIELDS_STORE_SIZE); case 6: array[offset + 5] = f5; case 5: array[offset + 4] = f4; case 4: array[offset + 3] = f3; case 3: array[offset + 2] = f2; case 2: array[offset + 1] = f1; case 1: array[offset + 0] = f0; case 0: break; } } private void ensureCapacity(int minimalCapacity) { int required = minimalCapacity - FIELDS_STORE_SIZE; if (required <= 0) throw new IllegalArgumentException(); if (data == null) { int alloc = FIELDS_STORE_SIZE * 2; if (alloc < required) { alloc = required; } data = new Object[alloc]; } else { int alloc = data.length; if (alloc < required) { if (alloc <= FIELDS_STORE_SIZE) { alloc = FIELDS_STORE_SIZE * 2; } else { alloc *= 2; } if (alloc < required) { alloc = required; } Object[] tmp = new Object[alloc]; if (size > FIELDS_STORE_SIZE) { System.arraycopy(data, 0, tmp, 0, size - FIELDS_STORE_SIZE); } data = tmp; } } } private static RuntimeException invalidIndex(int index, int upperBound) { // \u2209 is "NOT ELEMENT OF" String msg = index+" \u2209 [0, "+upperBound+')'; return new IndexOutOfBoundsException(msg); } private static RuntimeException invalidEmptyStackAccess() { throw new RuntimeException("Empty stack"); } private void writeObject(ObjectOutputStream os) throws IOException { os.defaultWriteObject(); int N = size; for (int i = 0; i != N; ++i) { Object obj = getImpl(i); os.writeObject(obj); } } private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException { is.defaultReadObject(); // It reads size int N = size; if (N > FIELDS_STORE_SIZE) { data = new Object[N - FIELDS_STORE_SIZE]; } for (int i = 0; i != N; ++i) { Object obj = is.readObject(); setImpl(i, obj); } } static final long serialVersionUID = 7448768847663119705L; // Number of data elements private int size; private static final int FIELDS_STORE_SIZE = 6; private transient Object f0, f1, f2, f3, f4, f5; private transient Object[] data; }