/*
 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot.runtime;

import sun.jvm.hotspot.oops.*;

SignatureIterators iterate over a Java signature (or parts of it). (Syntax according to: "The Java Virtual Machine Specification" by Tim Lindholm & Frank Yellin; section 4.3 Descriptors; p. 89ff.)

Example: Iterating over

([Lfoo;D)I
0123456789
using

iterateParameters() calls: do_array(2, 7); do_double();
iterateReturntype() calls:                              do_int();
iterate()           calls: do_array(2, 7); do_double(); do_int();
is_returnType()        is: false         ; false      ; true
/** <P> SignatureIterators iterate over a Java signature (or parts of it). (Syntax according to: "The Java Virtual Machine Specification" by Tim Lindholm & Frank Yellin; section 4.3 Descriptors; p. 89ff.) </P> <P> Example: Iterating over <PRE> ([Lfoo;D)I 0123456789 </PRE> using </P> <PRE> iterateParameters() calls: do_array(2, 7); do_double(); iterateReturntype() calls: do_int(); iterate() calls: do_array(2, 7); do_double(); do_int(); is_returnType() is: false ; false ; true </PRE> */
public abstract class SignatureIterator { protected Symbol _signature; // the signature to iterate over protected int _index; // the current character index (only valid during iteration) protected int _parameter_index; // the current parameter index (0 outside iteration phase) protected void expect(char c) { if (_signature.getByteAt(_index) != (byte) c) { throw new RuntimeException("expecting '" + c + "'"); } _index++; } protected void skipOptionalSize() { byte c = _signature.getByteAt(_index); while ('0' <= c && c <= '9') { c = _signature.getByteAt(++_index); } } // returns the parameter size in words (0 for void) protected int parseType() { switch(_signature.getByteAt(_index)) { case 'B': doByte (); _index++; return BasicTypeSize.getTByteSize(); case 'C': doChar (); _index++; return BasicTypeSize.getTCharSize(); case 'D': doDouble(); _index++; return BasicTypeSize.getTDoubleSize(); case 'F': doFloat (); _index++; return BasicTypeSize.getTFloatSize(); case 'I': doInt (); _index++; return BasicTypeSize.getTIntSize(); case 'J': doLong (); _index++; return BasicTypeSize.getTLongSize(); case 'S': doShort (); _index++; return BasicTypeSize.getTShortSize(); case 'Z': doBool (); _index++; return BasicTypeSize.getTBooleanSize(); case 'V': { if (!isReturnType()) { throw new RuntimeException("illegal parameter type V (void)"); } doVoid(); _index++; return BasicTypeSize.getTVoidSize(); } case 'L': { int begin = ++_index; while (_signature.getByteAt(_index++) != ';') ; doObject(begin, _index); return BasicTypeSize.getTObjectSize(); } case '[': { int begin = ++_index; skipOptionalSize(); while (_signature.getByteAt(_index) == '[') { _index++; skipOptionalSize(); } if (_signature.getByteAt(_index) == 'L') { while (_signature.getByteAt(_index++) != ';') ; } else { _index++; } doArray(begin, _index); return BasicTypeSize.getTArraySize(); } } throw new RuntimeException("Should not reach here: char " + (char)_signature.getByteAt(_index) + " @ " + _index + " in " + _signature.asString()); } protected void checkSignatureEnd() { if (_index < _signature.getLength()) { System.err.println("too many chars in signature"); _signature.printValueOn(System.err); System.err.println(" @ " + _index); } } public SignatureIterator(Symbol signature) { _signature = signature; _parameter_index = 0; } // // Iteration // // dispatches once for field signatures public void dispatchField() { // no '(', just one (field) type _index = 0; _parameter_index = 0; parseType(); checkSignatureEnd(); } // iterates over parameters only public void iterateParameters() { // Parse parameters _index = 0; _parameter_index = 0; expect('('); while (_signature.getByteAt(_index) != ')') { _parameter_index += parseType(); } expect(')'); _parameter_index = 0; // so isReturnType() is false outside iteration } // iterates over returntype only public void iterateReturntype() { // Ignore parameters _index = 0; expect('('); while (_signature.getByteAt(_index) != ')') { _index++; } expect(')'); // Parse return type _parameter_index = -1; parseType(); checkSignatureEnd(); _parameter_index = 0; // so isReturnType() is false outside iteration } // iterates over whole signature public void iterate() { // Parse parameters _index = 0; _parameter_index = 0; expect('('); while (_signature.getByteAt(_index) != ')') { _parameter_index += parseType(); } expect(')'); // Parse return type _parameter_index = -1; parseType(); checkSignatureEnd(); _parameter_index = 0; // so isReturnType() is false outside iteration } // Returns the word index of the current parameter; returns a negative value at the return type public int parameterIndex() { return _parameter_index; } public boolean isReturnType() { return (parameterIndex() < 0); } // Basic types public abstract void doBool (); public abstract void doChar (); public abstract void doFloat (); public abstract void doDouble(); public abstract void doByte (); public abstract void doShort (); public abstract void doInt (); public abstract void doLong (); public abstract void doVoid (); // Object types (begin indexes the first character of the entry, end // indexes the first character after the entry) public abstract void doObject(int begin, int end); public abstract void doArray (int begin, int end); }