package cutils.classDumper;


import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;


/**

 * This class describes a Method as it is stored in the class file.

 * The attribute associated with method is the code that actually implements

 * the method. Since we don't need to manipulate the byte codes directly

 * we leave them as an opaque chunk in the attributes[] array. References

 * in the code are all references into the constant table so when we are

 * modifing a class to use a different object we needn't get into the code

 * level.

 *

 * @version     1.4, 16 Aug 1995

 * @author  Chuck McManis

 * @see     ClassFile

 */


public class MethodInfo {

  short accessFlags;

  ConstantPoolInfo name;

  ConstantPoolInfo signature;

  AttributeInfo attributes[];


  /**

   * Read a method_info from the data stream.

   */

  public boolean read(DataInputStream di, ConstantPoolInfo pool[])

      throws IOException {

    int count;


    accessFlags = di.readShort();

    name = pool[di.readShort()];

    signature = pool[di.readShort()];

    count = di.readShort();

    if (count != 0) {

      attributes = new AttributeInfo[count];

      for (int i = 0; i < count; i++) {

        attributes[i] = new AttributeInfo(); // "code"

        if (!attributes[i].read(di, pool)) {

          return (false);

        }

      }

    }

    return (true);

  }


  /**

   * Write out a method_info, do constant table fixups on the write.

   */

  public void write(DataOutputStream dos, ConstantPoolInfo pool[])

      throws IOException, Exception {

    dos.writeShort(accessFlags);

    dos.writeShort(ConstantPoolInfo.indexOf(name, pool));

    dos.writeShort(ConstantPoolInfo.indexOf(signature, pool));

    if (attributes == null) {

      dos.writeShort(0);

    } else {

      dos.writeShort(attributes.length);

      for (int i = 0; i < attributes.length; i++)

        attributes[i].write(dos, pool);

    }

  }


  /**

   * print out the method, much as you would see it in the source

   * file. The string ClassName is substituted for &LTinit&GT when

   * printing.

   */

  public String toString(String className) {

    StringBuffer x = new StringBuffer();

    boolean isArray = false;

    String paramSig;

    String returnSig;

    int ndx = 0;

    StringBuffer parameterList = new StringBuffer();

    char initialParameter = 'a';

    StringBuffer varName = new StringBuffer();


    String s = signature.strValue;

    paramSig = s.substring(s.indexOf('(') + 1, s.indexOf(')'));

    returnSig = s.substring(s.indexOf(')') + 1);


    x.append(ClassFile.accessString(accessFlags));

    /* catch constructors */

    if ((className != null) && (name.toString().startsWith("<init>")))

      parameterList.append(className);

    else

      parameterList.append(name.toString());

    parameterList.append("(");

    if ((paramSig.length() > 0) && paramSig.charAt(0) != 'V') {

      while (paramSig.length() > 0) {

        varName.setLength(0);

        varName.append(initialParameter);

        initialParameter++;

        parameterList.append(

            ClassFile.typeString(paramSig, varName.toString()));

        paramSig = ClassFile.nextSig(paramSig);

        if (paramSig.length() > 0)

          parameterList.append(", ");

      }


    }

    parameterList.append(")");

    x.append(ClassFile.typeString(returnSig, parameterList.toString()));

    x.append(";");

    return (x.toString());

  }


  /**

   * Generic toString method, init method is unchanged.

   */

  public String toString() {

    return (toString((String) null));

  }

}