/*
 * Copyright 1994-2003 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.tools.java;

import java.io.IOException;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.util.Vector;
import java.util.Hashtable;

/**
 * This class is used to represent a constant table once
 * it is read from a class file.
 *
 * WARNING: The contents of this source file are not part of any
 * supported API.  Code that depends on them does so at its own risk:
 * they are subject to change or removal without notice.
 */
public final
class BinaryConstantPool implements Constants {
    private byte types[];
    private Object cpool[];

    /**
     * Constructor
     */
    BinaryConstantPool(DataInputStream in) throws IOException {
        // JVM 4.1 ClassFile.constant_pool_count
        types = new byte[in.readUnsignedShort()];
        cpool = new Object[types.length];
        for (int i = 1 ; i < cpool.length ; i++) {
            int j = i;
            // JVM 4.4 cp_info.tag
            switch(types[i] = in.readByte()) {
              case CONSTANT_UTF8:
                cpool[i] = in.readUTF();
                break;

              case CONSTANT_INTEGER:
                cpool[i] = new Integer(in.readInt());
                break;
              case CONSTANT_FLOAT:
                cpool[i] = new Float(in.readFloat());
                break;
              case CONSTANT_LONG:
                cpool[i++] = new Long(in.readLong());
                break;
              case CONSTANT_DOUBLE:
                cpool[i++] = new Double(in.readDouble());
                break;

              case CONSTANT_CLASS:
              case CONSTANT_STRING:
                // JVM 4.4.3 CONSTANT_String_info.string_index
                // or JVM 4.4.1 CONSTANT_Class_info.name_index
                cpool[i] = new Integer(in.readUnsignedShort());
                break;

              case CONSTANT_FIELD:
              case CONSTANT_METHOD:
              case CONSTANT_INTERFACEMETHOD:
              case CONSTANT_NAMEANDTYPE:
                // JVM 4.4.2 CONSTANT_*ref_info.class_index & name_and_type_index
                cpool[i] = new Integer((in.readUnsignedShort() << 16) | in.readUnsignedShort());
                break;

              case 0:
              default:
                throw new ClassFormatError("invalid constant type: " + (int)types[i]);
            }
        }
    }

    /**
     * get a integer
     */
    public int getInteger(int n) {
        return (n == 0) ? 0 : ((Number)cpool[n]).intValue();
    }

    /**
     * get a value
     */
    public Object getValue(int n) {
        return (n == 0) ? null : cpool[n];
    }

    /**
     * get a string
     */
    public String getString(int n) {
        return (n == 0) ? null : (String)cpool[n];
    }

    /**
     * get an identifier
     */
    public Identifier getIdentifier(int n) {
        return (n == 0) ? null : Identifier.lookup(getString(n));
    }

    /**
     * get class declaration
     */
    public ClassDeclaration getDeclarationFromName(Environment env, int n) {
        return (n == 0) ? null : env.getClassDeclaration(Identifier.lookup(getString(n).replace('/','.')));
    }

    /**
     * get class declaration
     */
    public ClassDeclaration getDeclaration(Environment env, int n) {
        return (n == 0) ? null : getDeclarationFromName(env, getInteger(n));
    }

    /**
     * get a type from a type signature
     */
    public Type getType(int n) {
        return Type.tType(getString(n));
    }

    /**
     * get the type of constant given an index
     */
    public int getConstantType(int n) {
        return types[n];
    }

    /**
     * get the n-th constant from the constant pool
     */
    public Object getConstant(int n, Environment env) {
        int constant_type = getConstantType(n);
        switch (constant_type) {
            case CONSTANT_INTEGER:
            case CONSTANT_FLOAT:
            case CONSTANT_LONG:
            case CONSTANT_DOUBLE:
                return getValue(n);

            case CONSTANT_CLASS:
                return getDeclaration(env, n);

            case CONSTANT_STRING:
                return getString(getInteger(n));

            case CONSTANT_FIELD:
            case CONSTANT_METHOD:
            case CONSTANT_INTERFACEMETHOD:
                try {
                    int key = getInteger(n);
                    ClassDefinition clazz =
                        getDeclaration(env, key >> 16).getClassDefinition(env);
                    int name_and_type = getInteger(key & 0xFFFF);
                    Identifier id = getIdentifier(name_and_type >> 16);
                    Type type = getType(name_and_type & 0xFFFF);

                    for (MemberDefinition field = clazz.getFirstMatch(id);
                         field != null;
                         field = field.getNextMatch()) {
                        Type field_type = field.getType();
                        if ((constant_type == CONSTANT_FIELD)
                            ? (field_type == type)
                            : (field_type.equalArguments(type)))
                            return field;
                    }
                } catch (ClassNotFound e) {
                }
                return null;

            default:
                throw new ClassFormatError("invalid constant type: " +
                                              constant_type);
        }
    }


    /**
     * Get a list of dependencies, ie: all the classes referenced in this
     * constant pool.
     */
    public Vector getDependencies(Environment env) {
        Vector v = new Vector();
        for (int i = 1 ; i < cpool.length ; i++) {
            switch(types[i]) {
              case CONSTANT_CLASS:
                v.addElement(getDeclarationFromName(env, getInteger(i)));
                break;
            }
        }
        return v;
    }

    Hashtable indexHashObject, indexHashAscii;
    Vector MoreStuff;

    /**
     * Find the index of an Object in the constant pool
     */
    public int indexObject(Object obj, Environment env) {
        if (indexHashObject == null)
            createIndexHash(env);
        Integer result = (Integer)indexHashObject.get(obj);
        if (result == null)
            throw new IndexOutOfBoundsException("Cannot find object " + obj + " of type " +
                                obj.getClass() + " in constant pool");
        return result.intValue();
    }

    /**
     * Find the index of an ascii string in the constant pool.  If it's not in
     * the constant pool, then add it at the end.
     */
    public int indexString(String string, Environment env) {
        if (indexHashObject == null)
            createIndexHash(env);
        Integer result = (Integer)indexHashAscii.get(string);
        if (result == null) {
            if (MoreStuff == null) MoreStuff = new Vector();
            result = new Integer(cpool.length + MoreStuff.size());
            MoreStuff.addElement(string);
            indexHashAscii.put(string, result);
        }
        return result.intValue();
    }

    /**
     * Create a hash table of all the items in the constant pool that could
     * possibly be referenced from the outside.
     */

    public void createIndexHash(Environment env) {
        indexHashObject = new Hashtable();
        indexHashAscii = new Hashtable();
        for (int i = 1; i < cpool.length; i++) {
            if (types[i] == CONSTANT_UTF8) {
                indexHashAscii.put(cpool[i], new Integer(i));
            } else {
                try {
                    indexHashObject.put(getConstant(i, env), new Integer(i));
                } catch (ClassFormatError e) { }
            }
        }
    }


    /**
     * Write out the contents of the constant pool, including any additions
     * that have been added.
     */
    public void write(DataOutputStream out, Environment env) throws IOException {
        int length = cpool.length;
        if (MoreStuff != null)
            length += MoreStuff.size();
        out.writeShort(length);
        for (int i = 1 ; i < cpool.length; i++) {
            int type = types[i];
            Object x = cpool[i];
            out.writeByte(type);
            switch (type) {
                case CONSTANT_UTF8:
                    out.writeUTF((String) x);
                    break;
                case CONSTANT_INTEGER:
                    out.writeInt(((Number)x).intValue());
                    break;
                case CONSTANT_FLOAT:
                    out.writeFloat(((Number)x).floatValue());
                    break;
                case CONSTANT_LONG:
                    out.writeLong(((Number)x).longValue());
                    i++;
                    break;
                case CONSTANT_DOUBLE:
                    out.writeDouble(((Number)x).doubleValue());
                    i++;
                    break;
                case CONSTANT_CLASS:
                case CONSTANT_STRING:
                    out.writeShort(((Number)x).intValue());
                    break;
                case CONSTANT_FIELD:
                case CONSTANT_METHOD:
                case CONSTANT_INTERFACEMETHOD:
                case CONSTANT_NAMEANDTYPE: {
                    int value = ((Number)x).intValue();
                    out.writeShort(value >> 16);
                    out.writeShort(value & 0xFFFF);
                    break;
                }
                default:
                     throw new ClassFormatError("invalid constant type: "
                                                   + (int)types[i]);
            }
        }
        for (int i = cpool.length; i < length; i++) {
            String string = (String)(MoreStuff.elementAt(i - cpool.length));
            out.writeByte(CONSTANT_UTF8);
            out.writeUTF(string);
        }
    }

}
