FileDocCategorySizeDatePackage
SignatureIterator.javaAPI DocJ2ME CLDC 1.15433Wed Feb 05 15:56:04 GMT 2003util

SignatureIterator.java

/*
 *    SignatureIterator.java    1.2    99/04/06 SMI
 *
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package util;
import vm.Const;

public abstract class SignatureIterator {
    
    protected String sig;
    private int       sigStart;
    private int       cur;
    private int       end;
    private int       arrayDepth;

    public  boolean isSingleton;
    protected boolean isReturnType;

    public SignatureIterator( String sig, int start, int end ){
    this.sig = sig;
    this.sigStart = cur = start;
    this.end = end;
    isSingleton = sig.charAt( start ) != Const.SIGC_METHOD;
    }

    public SignatureIterator( String sig ){
    this( sig, 0, sig.length()-1);
    }

    /*
     * Override any of these to do something more intelligent
     */
    public void do_boolean(){
    do_scalar( Const.SIGC_BOOLEAN );
    }
    public void do_char  (){
    do_scalar( Const.SIGC_CHAR );
    }
    public void do_float (){
    do_scalar( Const.SIGC_FLOAT );
    }
    public void do_double(){
    do_scalar( Const.SIGC_DOUBLE );
    }
    public void do_byte  (){
    do_scalar( Const.SIGC_BYTE );
    }
    public void do_short (){
    do_scalar( Const.SIGC_SHORT );
    }
    public void do_int   (){
    do_scalar( Const.SIGC_INT );
    }
    public void do_long  (){
    do_scalar( Const.SIGC_LONG );
    }
    public void do_void  (){
    do_scalar( Const.SIGC_VOID );
    }

    public void do_scalar( char c ){
    return;
    }

    //
    // do_array and do_object are expected to parse the subtype
    // information themselves.
    // if its a simple type (do_array only),
    // then subTypeEnd == subTypeStart
    // else  sig.charAt(subTypeStart) == Const.SIGC_CLASS 
    // and   sig.charAt(subTypeEnd)   == Const.SIGC_ENDCLASS
    //
    public abstract void do_array( int arrayDepth, int subTypeStart, int subTypeEnd );
    public abstract void do_object( int subTypeStart, int subTypeEnd );

    public boolean isMethod(){ return !isSingleton; }

    public void iterate_parameters() throws DataFormatException {
    cur = sigStart;
    if ( isSingleton )
        throw new DataFormatException(sig.substring(cur-1, end)+" is not a method signature");
    cur += 1;
    isReturnType = false;
    char c;
    while ((c=sig.charAt(cur++) ) != Const.SIGC_ENDMETHOD ){
        if ( cur > end ){
        throw new DataFormatException( "unterminated parameter list");
        }
        next( c );
    }
    }

    public void iterate_returntype() throws DataFormatException {
    if ( isSingleton )
        throw new DataFormatException(sig.substring(sigStart, end)+" is not a method signature");
    int endpos = sig.indexOf( Const.SIGC_ENDMETHOD, sigStart );
    isReturnType = true;
    if ( (endpos < 0 ) || (endpos > end ) )
        throw new DataFormatException( "unterminated parameter list");
    cur = endpos+1;
    next( sig.charAt(cur++) );
    }

    public void iterate() throws DataFormatException {
    if ( isSingleton ){
        // trivial case.
        isReturnType = false;
        cur = sigStart;
        next( sig.charAt(cur++) );
    } else {
        iterate_parameters();
        iterate_returntype();
    }
    }

    private int
    delimitClassname( ) throws DataFormatException{
    int endpos = sig.indexOf( Const.SIGC_ENDCLASS, cur );
    if ( (endpos < 0 ) || (endpos > end ) )
        throw new DataFormatException( "unending class name");
    return endpos;
    }

    private void next( char c ) throws DataFormatException {
    switch (c){
    case Const.SIGC_BOOLEAN:
        do_boolean(); return;
    case Const.SIGC_BYTE:
        do_byte(); return;
    case Const.SIGC_CHAR:
        do_char(); return;
    case Const.SIGC_SHORT:
        do_short(); return;
    case Const.SIGC_INT:
        do_int(); return;
    case Const.SIGC_FLOAT:
        do_float(); return;
    case Const.SIGC_LONG:
        do_long(); return;
    case Const.SIGC_DOUBLE:
        do_double(); return;
    case Const.SIGC_VOID:
        do_void();
        return;

    case Const.SIGC_CLASS:
        int startClassName = cur-1;
        int endClassName = delimitClassname( );
        cur = endClassName+1;
        do_object( startClassName, endClassName );
        return;

    case Const.SIGC_ARRAY:
        arrayDepth = 0;
        cur -= 1;
        do {
        arrayDepth += 1;
        }while ((cur<=end) && ((c=sig.charAt(++cur)) == Const.SIGC_ARRAY));
        if ( cur > end )
        throw new DataFormatException( "array of nothing");
        int startBaseType = cur;
        int endBaseType;
        // now isolate at the base type.
        if ( c == Const.SIGC_CLASS ){
        endBaseType = delimitClassname( );
        } else {
        endBaseType = startBaseType;
        }
        cur = endBaseType+1;
        do_array( arrayDepth, startBaseType, endBaseType );
        return;

    case Const.SIGC_METHOD:
        // cannot happen here!
    default:
        throw new DataFormatException( "unparseable signature: " + sig);
    }
    }

    // when the baseType is a class, we have the name stashed away.
    public String className( int startpos, int endpos){
    return sig.substring( startpos+1, endpos );
    }

    public static boolean isPrimitiveType( String sig ){
    char c = sig.charAt(0);
    return ( (c!=Const.SIGC_METHOD) && (c!=Const.SIGC_ARRAY) && (c!=Const.SIGC_CLASS) );
    }
}