/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.vm.bytecode; /** * A TypeStack is a stack of internal type numbers represented as {@link org.jnode.vm.JvmType} * values; i.e. integers. * * @author Ewout Prangsma (epr@users.sourceforge.net) */ public final class TypeStack { private byte[] stack; private int tos; /** * Create a new empty TypeStack instance. */ public TypeStack() { stack = new byte[8]; tos = 0; } /** * Create a new empty TypeStack instance as copy of an existing one. * @param src the stack whose contents is to be copied. */ public TypeStack(TypeStack src) { copyFrom(src); } /** * Set this stack's contents to be same as another stack. The * current state of the stack (if any) is discarded. * * @param src the stack whose contents is to be copied. */ public void copyFrom(TypeStack src) { if (src != null) { stack = new byte[src.stack.length]; System.arraycopy(src.stack, 0, stack, 0, stack.length); tos = src.tos; } else { stack = new byte[8]; tos = 0; } } /** * Empty the TypeStack. */ public void clear() { tos = 0; } /** * Is this TypeStack empty. * * @return {@code true} if the stack is empty, otherwise {@code false}. */ public final boolean isEmpty() { return (tos == 0); } /** * Is this TypeStack equal to the given TypeStack. Note that this is an * overload for {@link java.lang.Object#equals(java.lang.Object)} not * an override. */ public boolean equals(TypeStack tso) { if ((this.tos == 0) && (tso == null)) { return true; } if (this.tos != tso.tos) { return false; } for (int i = 0; i < tos; i++) { if (this.stack[i] != tso.stack[i]) { return false; } } return true; } public boolean equals(Object o) { if (o instanceof TypeStack) { return equals((TypeStack) o); } else { return false; } } /** * Push a type onto the TypeStack. * * @param type a {@link org.jnode.vm.JvmType} value */ public final void push(int type) { if (tos == stack.length) grow(); stack[tos++] = (byte) type; } /** * Pop a type from the TypeStack and return it. * * @return a {@link org.jnode.vm.JvmType} value * @throws Error if the stack is empty */ public final int pop() { if (tos <= 0) { throw new Error("Stack is empty"); } return stack[--tos]; } /** * Pop a type from the stack and check that it is the expected type. * * @param type the expected {@link org.jnode.vm.JvmType} value. * @throws Error if there is a type mismatch */ public final void pop(int type) throws Error { if (tos <= 0) { throw new Error("Stack is empty"); } if (stack[--tos] != type) { throw new Error("TypeStack[" + tos + "] is not the expected element " + type + " but " + stack[tos]); } } /** * Gets the number of elements in this stack. * * @return the number of elements. */ public final int size() { return tos; } /** * Get the element at a particular stack index. * * @param stackIndex the stack index. This should be a number in the range * {@code 0 .. size() - 1} inclusive where {@code size() - 1} is the top element * on the stack. * @return the {@link org.jnode.vm.JvmType} value at the given offset. */ public final int getType(int stackIndex) { return stack[stackIndex]; } /** * Convert to a string representation * * @see java.lang.Object#toString() */ public String toString() { final StringBuilder buf = new StringBuilder(); buf.append('{'); for (int i = 0; i < tos; i++) { if (i > 0) { buf.append(','); } buf.append(stack[i]); } buf.append('}'); return buf.toString(); } /** * Grow the stack space. */ private final void grow() { final byte[] tmp = new byte[stack.length * 2]; System.arraycopy(stack, 0, tmp, 0, stack.length); stack = tmp; } }