Package objot.bytecode

Source Code of objot.bytecode.Constants

//
// Copyright 2007-2010 Qianyan Cai
// Under the terms of the GNU Lesser General Public License version 2.1
//
package objot.bytecode;

import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import objot.util.Array2;
import objot.util.Bytes;
import objot.util.Class2;
import objot.util.InvalidValueException;


/**
* All UTFs in this class are no-null-character UTF-8. All names of class are internal
* form.
*/
public final class Constants
  extends Element
{
  public static final byte TAG_UTF = 1;
  public static final byte TAG_INT = 3;
  public static final byte TAG_FLOAT = 4;
  public static final byte TAG_LONG = 5;
  public static final byte TAG_DOUBLE = 6;
  public static final byte TAG_CLASS = 7;
  public static final byte TAG_STRING = 8;
  public static final byte TAG_FIELD = 9;
  /** class procedure */
  public static final byte TAG_CPROC = 10;
  /** interface procedure */
  public static final byte TAG_IPROC = 11;
  public static final byte TAG_NAMEDESC = 12;

  int byteN0;
  /** index [1, N) excluding 0. */
  int conN0;
  int conN;
  int[] bis;

  public Constants(byte[] bs, int beginBi_)
  {
    super(bs, beginBi_);
    conN0 = conN = readU2(bytes, beginBi);
    if (conN <= 0)
      throw new ClassFormatError("invalid constants amount");
    int bi = beginBi + 2;
    for (int ci = 1; ci < conN; ci++)
    {
      byte t = bytes[bi];
      if (t == TAG_LONG || t == TAG_DOUBLE)
        if (ci < conN)
          ci++; // stupid specification ass
        else
          throw new ClassFormatError("unexpect constant end");
      bi += readConByteN(bi);
    }
    end1Bi = bi;
    byteN0 = end1Bi - beginBi;
  }

  @Override
  public int byteN0()
  {
    return byteN0;
  }

  public int getConN()
  {
    return conN;
  }

  /** Including the tag byte. */
  int readConByteN(int bi)
  {
    switch (bytes[bi])
    {
    case TAG_UTF:
      int l = readU2(bytes, bi + 1);
      for (int i = bi + 3; i < bi + l; i++)
        if (bytes[i] == 0)
          throw new ClassFormatError("invalid utf constant");
      return 1 + 2 + l;
    case TAG_INT:
    case TAG_FLOAT:
      return 1 + 4;
    case TAG_LONG:
    case TAG_DOUBLE:
      return 1 + 8;
    case TAG_CLASS:
    case TAG_STRING:
      return 1 + 2;
    case TAG_FIELD:
    case TAG_CPROC:
    case TAG_IPROC:
    case TAG_NAMEDESC:
      return 1 + 2 + 2;
    }
    throw new ClassFormatError("invalid constant info tag");
  }

  void readBis()
  {
    if (bis != null)
      return;
    bis = new int[allocN(Math.max(conN, 100))];
    bis[0] = Integer.MIN_VALUE;
    bis[1] = beginBi + 2;
    for (int ci = 2; ci < conN; ci++)
    {
      bis[ci] = bis[ci - 1] + readConByteN(bis[ci - 1]);
      byte t = bytes[bis[ci - 1]];
      if (t == TAG_LONG || t == TAG_DOUBLE)
      {
        bis[ci + 1] = bis[ci];
        bis[ci] = bis[ci - 1];
        ci++;
      }
    }
  }

  /** @param ci [1, N) excluding 0. */
  void checkIndex(int ci)
  {
    if (ci <= 0 || ci >= conN)
      throw new InvalidValueException(ci);
  }

  public byte getTag(int ci)
  {
    checkIndex(ci);
    readBis();
    return bytes[bis[ci]];
  }

  public byte getTag(int ci, byte tag)
  {
    checkIndex(ci);
    readBis();
    if (tag != bytes[bis[ci]])
      throw new ClassCastException();
    return tag;
  }

  public Bytes getUtf(int ci)
  {
    getTag(ci, TAG_UTF);
    return new Bytes(bytes, getUtfBegin(ci), getUtfEnd1(ci));
  }

  public void getUtfTo(int ci, byte[] bs, int bi)
  {
    System.arraycopy(bytes, getUtfBegin(ci), bs, bi, getUtfByteN(ci));
  }

  public void getUtfTo(int ci, Bytes bs, int bi)
  {
    bs.copyFrom(bi, bytes, getUtfBegin(ci), getUtfByteN(ci));
  }

  public String getUcs(int ci)
  {
    return ucs(this, getUtfBegin(ci) - beginBi, getUtfEnd1(ci) - beginBi);
  }

  public int getUtfByteN(int ci)
  {
    getTag(ci, TAG_UTF);
    return readU2(bytes, bis[ci] + 1);
  }

  public int getUtfBegin(int ci)
  {
    getTag(ci, TAG_UTF);
    return bis[ci] + 3;
  }

  public int getUtfEnd1(int ci)
  {
    getTag(ci, TAG_UTF);
    return bis[ci] + 3 + readU2(bytes, bis[ci] + 1);
  }

  public int getInt(int ci)
  {
    getTag(ci, TAG_INT);
    return readS4(bytes, bis[ci] + 1);
  }

  public long getLong(int ci)
  {
    getTag(ci, TAG_LONG);
    return readS8(bytes, bis[ci] + 1);
  }

  public float getFloat(int ci)
  {
    getTag(ci, TAG_FLOAT);
    return Float.intBitsToFloat(readS4(bytes, bis[ci] + 1));
  }

  public double getDouble(int ci)
  {
    getTag(ci, TAG_DOUBLE);
    return Double.longBitsToDouble(readS8(bytes, bis[ci] + 1));
  }

  int getUtfRef(byte tag, int ci)
  {
    getTag(ci, tag);
    return readU2(bytes, bis[ci] + 1);
  }

  public int getClass(int ci)
  {
    return getUtfRef(TAG_CLASS, ci);
  }

  public int getString(int ci)
  {
    return getUtfRef(TAG_STRING, ci);
  }

  int getClassNameDescClass(byte tag, int ci)
  {
    getTag(ci, tag);
    return getClass(readU2(bytes, bis[ci] + 1));
  }

  int getClassNameDescName(byte tag, int ci)
  {
    getTag(ci, tag);
    return getNameDescName(readU2(bytes, bis[ci] + 3));
  }

  int getClassNameDescDesc(byte tag, int ci)
  {
    getTag(ci, tag);
    return getNameDescDesc(readU2(bytes, bis[ci] + 3));
  }

  public int getFieldClass(int ci)
  {
    return getClassNameDescClass(TAG_FIELD, ci);
  }

  public int getFieldName(int ci)
  {
    return getClassNameDescName(TAG_FIELD, ci);
  }

  public int getFieldDesc(int ci)
  {
    return getClassNameDescDesc(TAG_FIELD, ci);
  }

  public int getCprocClass(int ci)
  {
    return getClassNameDescClass(TAG_CPROC, ci);
  }

  public int getCprocName(int ci)
  {
    return getClassNameDescName(TAG_CPROC, ci);
  }

  public int getCprocDesc(int ci)
  {
    return getClassNameDescDesc(TAG_CPROC, ci);
  }

  public int getIprocClass(int ci)
  {
    return getClassNameDescClass(TAG_IPROC, ci);
  }

  public int getIprocName(int ci)
  {
    return getClassNameDescName(TAG_IPROC, ci);
  }

  public int getIprocDesc(int ci)
  {
    return getClassNameDescDesc(TAG_IPROC, ci);
  }

  public int getNameDescName(int ci)
  {
    return getUtfRef(TAG_NAMEDESC, ci);
  }

  public int getNameDescDesc(int ci)
  {
    getTag(ci, TAG_NAMEDESC);
    return readU2(bytes, bis[ci] + 3);
  }

  // ********************************************************************************

  public boolean equalsUtf(int ci, Bytes utf)
  {
    return getTag(ci) == TAG_UTF
      && utf.equals(bytes, bis[ci] + 3, bis[ci] + 3 + readU2(bytes, bis[ci] + 1));
  }

  public boolean startsWithUtf(int ci, Bytes utf)
  {
    return getTag(ci) == TAG_UTF && readU2(bytes, bis[ci] + 1) >= utf.byteN()
      && utf.equals(bytes, bis[ci] + 3, bis[ci] + 3 + utf.byteN());
  }

  public boolean equalsInt(int ci, int v)
  {
    return getTag(ci) == TAG_INT && readS4(bytes, bis[ci] + 1) == v;
  }

  public boolean equalsLong(int ci, long v)
  {
    return getTag(ci) == TAG_LONG && readS8(bytes, bis[ci] + 1) == v;
  }

  public boolean equalsFloat(int ci, float v)
  {
    return getTag(ci) == TAG_FLOAT
      && Float.intBitsToFloat(readS4(bytes, bis[ci] + 1)) == v;
  }

  public boolean equalsDouble(int ci, double v)
  {
    return getTag(ci) == TAG_LONG
      && Double.longBitsToDouble(readS8(bytes, bis[ci] + 1)) == v;
  }

  boolean equalsRef(byte tag, int ci, int refCi)
  {
    return getTag(ci) == tag && readU2(bytes, bis[ci] + 1) == refCi;
  }

  boolean equalsRefUtf(byte tag, int ci, Bytes utf)
  {
    return getTag(ci) == tag && equalsUtf(readU2(bytes, bis[ci] + 1), utf);
  }

  public boolean equalsClass(int ci, int nameCi)
  {
    return equalsRef(TAG_CLASS, ci, nameCi);
  }

  public boolean equalsClass(int ci, Bytes name)
  {
    return equalsRefUtf(TAG_CLASS, ci, name);
  }

  public boolean equalsString(int ci, int strCi)
  {
    return equalsRef(TAG_STRING, ci, strCi);
  }

  public boolean equalsString(int ci, Bytes str)
  {
    return equalsRefUtf(TAG_STRING, ci, str);
  }

  boolean equalsRef2(byte tag, int ci, int ref1Ci, int ref2Ci)
  {
    return getTag(ci) == tag && readU2(bytes, bis[ci] + 1) == ref1Ci
      && readU2(bytes, bis[ci] + 3) == ref2Ci;
  }

  boolean equalsClassNameDesc(byte tag, int ci, int classNameCi, int nameCi, int descCi)
  {
    return getTag(ci) == tag && equalsClass(readU2(bytes, bis[ci] + 1), classNameCi)
      && equalsNameDesc(readU2(bytes, bis[ci] + 3), nameCi, descCi);
  }

  boolean equalsClassNameDesc(byte tag, int ci, Bytes className, Bytes name, Bytes desc)
  {
    return getTag(ci) == tag && equalsClass(readU2(bytes, bis[ci] + 1), className)
      && equalsNameDesc(readU2(bytes, bis[ci] + 3), name, desc);
  }

  public boolean equalsField(int ci, int classNameCi, int nameDescCi)
  {
    return equalsRef2(TAG_FIELD, ci, classNameCi, nameDescCi);
  }

  public boolean equalsField(int ci, int classNameCi, int nameCi, int descCi)
  {
    return equalsClassNameDesc(TAG_FIELD, ci, classNameCi, nameCi, descCi);
  }

  public boolean equalsField(int ci, Bytes className, Bytes name, Bytes desc)
  {
    return equalsClassNameDesc(TAG_FIELD, ci, className, name, desc);
  }

  public boolean equalsCproc(int ci, int classNameCi, int nameDescCi)
  {
    return equalsRef2(TAG_CPROC, ci, classNameCi, nameDescCi);
  }

  public boolean equalsCproc(int ci, int classNameCi, int nameCi, int descCi)
  {
    return equalsClassNameDesc(TAG_CPROC, ci, classNameCi, nameCi, descCi);
  }

  public boolean equalsCproc(int ci, Bytes className, Bytes name, Bytes desc)
  {
    return equalsClassNameDesc(TAG_CPROC, ci, className, name, desc);
  }

  public boolean equalsIproc(int ci, int classNameCi, int nameDescCi)
  {
    return equalsRef2(TAG_IPROC, ci, classNameCi, nameDescCi);
  }

  public boolean equalsIproc(int ci, int classNameCi, int nameCi, int descCi)
  {
    return equalsClassNameDesc(TAG_IPROC, ci, classNameCi, nameCi, descCi);
  }

  public boolean equalsIproc(int ci, Bytes className, Bytes name, Bytes desc)
  {
    return equalsClassNameDesc(TAG_IPROC, ci, className, name, desc);
  }

  public boolean equalsNameDesc(int ci, int nameCi, int descCi)
  {
    return equalsRef2(TAG_NAMEDESC, ci, nameCi, descCi);
  }

  public boolean equalsNameDesc(int ci, Bytes name, Bytes desc)
  {
    return getTag(ci) == TAG_NAMEDESC && equalsUtf(readU2(bytes, bis[ci] + 1), name)
      && equalsUtf(readU2(bytes, bis[ci] + 3), desc);
  }

  /** @return the constant index, negative if nothing found. */
  public int searchUtf(Bytes utf)
  {
    for (int ci = 1; ci < conN; ci++)
      if (equalsUtf(ci, utf))
        return ci;
    return -1;
  }

  /** @return the constant index, negative if nothing found. */
  public int searchUtfLast(Bytes utf)
  {
    for (int ci = conN - 1; ci >= 1; ci--)
      if (equalsUtf(ci, utf))
        return ci;
    return -1;
  }

  /** @return the constant index, negative if nothing found. */
  public int searchInt(int v)
  {
    for (int ci = 1; ci < conN; ci++)
      if (equalsInt(ci, v))
        return ci;
    return -1;
  }

  /** @return the constant index, negative if nothing found. */
  public int searchLong(long v)
  {
    for (int ci = 1; ci < conN; ci++)
      // searching the index next to a long has no effect
      // stupid specification
      if (equalsLong(ci, v))
        return ci;
    return -1;
  }

  /** @return the constant index, negative if nothing found. */
  public int searchFloat(float v)
  {
    for (int ci = 1; ci < conN; ci++)
      if (equalsFloat(ci, v))
        return ci;
    return -1;
  }

  /** @return the constant index, negative if nothing found. */
  public int searchDouble(double v)
  {
    for (int ci = 1; ci < conN; ci++)
      // searching the index next to a double has no effect
      // stupid specification
      if (equalsDouble(ci, v))
        return ci;
    return -1;
  }

  /** @return the constant index, negative if nothing found. */
  int searchRef(byte tag, int refCi)
  {
    for (int ci = 1; ci < conN; ci++)
      if (equalsRef(tag, ci, refCi))
        return ci;
    return -1;
  }

  /** @return the constant index, negative if nothing found. */
  int searchRefUtf(byte tag, Bytes utf)
  {
    for (int ci = 1; ci < conN; ci++)
      if (equalsRefUtf(tag, ci, utf))
        return ci;
    return -1;
  }

  /** @return the constant index, negative if nothing found. */
  public int searchClass(int nameCi)
  {
    return searchRef(TAG_CLASS, nameCi);
  }

  /** @return the constant index, negative if nothing found. */
  public int searchClass(Bytes name)
  {
    return searchRefUtf(TAG_CLASS, name);
  }

  /** @return the constant index, negative if nothing found. */
  public int searchString(int strCi)
  {
    return searchRef(TAG_STRING, strCi);
  }

  /** @return the constant index, negative if nothing found. */
  public int searchString(Bytes str)
  {
    return searchRefUtf(TAG_STRING, str);
  }

  /** @return the constant index, negative if nothing found. */
  int searchRef2(byte tag, int ref1Ci, int ref2Ci)
  {
    for (int ci = 1; ci < conN; ci++)
      if (equalsRef2(tag, ci, ref1Ci, ref2Ci))
        return ci;
    return -1;
  }

  /** @return the constant index, negative if nothing found. */
  int searchClassNameDesc(byte tag, int classNameCi, int nameCi, int descCi)
  {
    for (int ci = 1; ci < conN; ci++)
      if (equalsClassNameDesc(tag, ci, classNameCi, nameCi, descCi))
        return ci;
    return -1;
  }

  /** @return the constant index, negative if nothing found. */
  int searchClassNameDesc(byte tag, Bytes className, Bytes name, Bytes desc)
  {
    for (int ci = 1; ci < conN; ci++)
      if (equalsClassNameDesc(tag, ci, className, name, desc))
        return ci;
    return -1;
  }

  /** @return the constant index, negative if nothing found. */
  public int searchField(int classNameCi, int nameDescCi)
  {
    return searchRef2(TAG_FIELD, classNameCi, nameDescCi);
  }

  /** @return the constant index, negative if nothing found. */
  public int searchField(int classNameCi, int nameCi, int descCi)
  {
    return searchClassNameDesc(TAG_FIELD, classNameCi, nameCi, descCi);
  }

  /** @return the constant index, negative if nothing found. */
  public int searchField(Bytes className, Bytes name, Bytes desc)
  {
    return searchClassNameDesc(TAG_FIELD, className, name, desc);
  }

  /** @return the constant index, negative if nothing found. */
  public int searchCproc(int classNameCi, int nameDescCi)
  {
    return searchRef2(TAG_CPROC, classNameCi, nameDescCi);
  }

  /** @return the constant index, negative if nothing found. */
  public int searchCproc(int classNameCi, int nameCi, int descCi)
  {
    return searchClassNameDesc(TAG_CPROC, classNameCi, nameCi, descCi);
  }

  /** @return the constant index, negative if nothing found. */
  public int searchCproc(Bytes className, Bytes name, Bytes desc)
  {
    return searchClassNameDesc(TAG_CPROC, className, name, desc);
  }

  /** @return the constant index, negative if nothing found. */
  public int searchIproc(int classNameCi, int nameDescCi)
  {
    return searchRef2(TAG_IPROC, classNameCi, nameDescCi);
  }

  /** @return the constant index, negative if nothing found. */
  public int searchIproc(int classNameCi, int nameCi, int descCi)
  {
    return searchClassNameDesc(TAG_IPROC, classNameCi, nameCi, descCi);
  }

  /** @return the constant index, negative if nothing found. */
  public int searchIproc(Bytes className, Bytes name, Bytes desc)
  {
    return searchClassNameDesc(TAG_IPROC, className, name, desc);
  }

  /** @return the constant index, negative if nothing found. */
  public int searchNameDesc(int nameI, int descI)
  {
    return searchRef2(TAG_NAMEDESC, nameI, descI);
  }

  /** @return the constant index, negative if nothing found. */
  public int searchNameDesc(Bytes name, Bytes desc)
  {
    for (int ci = 1; ci < conN; ci++)
      if (equalsNameDesc(ci, name, desc))
        return ci;
    return -1;
  }

  /** @see Class2#pathName(Class) */
  public Bytes classDesc2Name(int utfCi)
  {
    return classDesc2Name(this, getUtfBegin(utfCi) - beginBi, getUtfEnd1(utfCi) - beginBi);
  }

  /** @see Class2#pathName(Class) */
  public String classDesc2NameUcs(int utfCi)
  {
    return classDesc2NameUcs(this, getUtfBegin(utfCi) - beginBi, getUtfEnd1(utfCi)
      - beginBi);
  }

  @Override
  void printContents(PrintStream out, int indent1st, int indent, int verbose)
  {
    if (verbose > 0)
    {
      printIndent(out, indent1st);
      out.print(" conN ");
      out.print(conN);
      out.print("-1");
    }
    out.println();
    if (verbose > 1)
      for (int i = 1; i < conN; i++)
      {
        printIndent(out, indent);
        print(out, i, verbose).println();
      }
  }

  public PrintStream print(PrintStream out, int ci, int verbose)
  {
    out.print(ci);
    if (verbose < 0 || ci <= 0)
      out.print('~');
    else
      switch (getTag(ci))
      {
      case TAG_UTF:
        out.print("'");
        out.print(getUcs(ci));
        break;
      case TAG_INT:
        out.print("-int ");
        out.print(getInt(ci));
        break;
      case TAG_FLOAT:
        out.print("-float ");
        out.print(getFloat(ci));
        break;
      case TAG_LONG:
        out.print("-long ");
        out.print(getLong(ci));
        break;
      case TAG_DOUBLE:
        out.print("-double ");
        out.print(getDouble(ci));
        break;
      case TAG_CLASS:
        out.print("{");
        out.print(getUcs(getClass(ci)));
        break;
      case TAG_STRING:
        out.print("-str ");
        out.print(getUcs(getString(ci)));
        break;
      case TAG_FIELD:
        out.print("-field ");
        out.print(getUcs(getFieldClass(ci)));
        out.print('.');
        out.print(getUcs(getFieldName(ci)));
        out.print(' ');
        out.print(getUcs(getFieldDesc(ci)));
        break;
      case TAG_CPROC:
        out.print("-cproc ");
        out.print(getUcs(getCprocClass(ci)));
        out.print('.');
        out.print(getUcs(getCprocName(ci)));
        out.print(' ');
        out.print(getUcs(getCprocDesc(ci)));
        break;
      case TAG_IPROC:
        out.print("-iproc ");
        out.print(getUcs(getIprocClass(ci)));
        out.print('.');
        out.print(getUcs(getIprocName(ci)));
        out.print(getUcs(getIprocDesc(ci)));
        break;
      case TAG_NAMEDESC:
        out.print("-nameDesc ");
        out.print(getUcs(getNameDescName(ci)));
        out.print(' ');
        out.print(getUcs(getNameDescDesc(ci)));
        break;
      }
    return out;
  }

  public static PrintStream print(Constants cons, PrintStream out, int ci, int verbose)
  {
    if (cons != null)
      return cons.print(out, ci, verbose);
    out.print(ci);
    out.print('~');
    return out;
  }

  // ********************************************************************************

  /** bytes will be different with the original bytes */
  void ensureN(int cn, int bn)
  {
    readBis();
    bis = Array2.ensureN(bis, cn);
    if (conN > conN0)
      bytes = Array2.ensureN(bytes, bn);
    else
    { // new bytes always
      byte[] bs = new byte[Math.max((int)(end1Bi * 1.5f), bn)];
      System.arraycopy(bytes, 0, bs, 0, end1Bi);
      bytes = bs;
    }
  }

  /** @return second byte index of added constant */
  int add(byte tag, int bn)
  {
    readBis();
    ensureN(conN + 2, end1Bi + bn);
    if (tag == TAG_LONG || tag == TAG_DOUBLE)
      bis[conN++] = end1Bi; // stupid specification
    bis[conN++] = end1Bi;
    bytes[end1Bi] = tag;
    end1Bi += bn;
    return end1Bi - bn;
  }

  public void setUtf(int ci, Bytes utf)
  {
    getTag(ci, TAG_UTF);
    int d = utf.byteN() - getUtfByteN(ci);
    ensureN(conN, end1Bi + d); // new bytes
    if (d != 0 && ci < conN - 1)
    {
      int i = ci + 1;
      System.arraycopy(bytes, bis[i], bytes, bis[i] + d, end1Bi - bis[i]);
      while (i < conN)
        bis[i++] += d;
    }
    end1Bi += d;
    writeU2(bytes, bis[ci] + 1, utf.byteN());
    utf.copyTo(0, bytes, bis[ci] + 3, utf.byteN());
  }

  public int addUtf(Bytes utf)
  {
    int bi = add(TAG_UTF, 3 + utf.byteN());
    writeU2(bytes, bi + 1, utf.byteN());
    utf.copyTo(0, bytes, bi + 3, utf.byteN());
    return conN - 1;
  }

  public int putUtf(Bytes utf)
  {
    int i = searchUtf(utf);
    if (i < 0)
      i = addUtf(utf);
    return i;
  }

  public int putUtfLast(Bytes utf)
  {
    int i = searchUtfLast(utf);
    if (i < 0)
      i = addUtf(utf);
    return i;
  }

  public void setUcs(int ci, String s)
  {
    setUtf(ci, utf(s));
  }

  public int addUcs(String s)
  {
    return addUtf(utf(s));
  }

  public int putUcs(String s)
  {
    return putUtf(utf(s));
  }

  public int putUcsLast(String s)
  {
    return putUtfLast(utf(s));
  }

  public void setInt(int ci, int v)
  {
    getTag(ci, TAG_INT);
    ensureN(conN, end1Bi);
    writeS4(bytes, bis[ci] + 1, v);
  }

  public int addInt(int v)
  {
    int bi = add(TAG_INT, 5);
    writeS4(bytes, bi + 1, v);
    return conN - 1;
  }

  public int putInt(int v)
  {
    int i = searchInt(v);
    if (i < 0)
      i = addInt(v);
    return i;
  }

  public void setLong(int ci, long v)
  {
    getTag(ci, TAG_LONG);
    ensureN(conN, end1Bi);
    writeS8(bytes, bis[ci] + 1, v);
  }

  public int addLong(long v)
  {
    int bi = add(TAG_LONG, 9);
    writeS8(bytes, bi + 1, v);
    return conN - 2; // stupid specification
  }

  public int putLong(long v)
  {
    int i = searchLong(v);
    if (i < 0)
      i = addLong(v);
    return i;
  }

  public void setFloat(int ci, float v)
  {
    getTag(ci, TAG_FLOAT);
    ensureN(conN, end1Bi);
    writeS4(bytes, bis[ci] + 1, Float.floatToRawIntBits(v));
  }

  public int addFloat(float v)
  {
    int bi = add(TAG_FLOAT, 5);
    writeS4(bytes, bi + 1, Float.floatToRawIntBits(v));
    return conN - 1;
  }

  public int putFloat(float v)
  {
    int i = searchFloat(v);
    if (i < 0)
      i = addFloat(v);
    return i;
  }

  public void setDouble(int ci, double v)
  {
    getTag(ci, TAG_DOUBLE);
    ensureN(conN, end1Bi);
    writeS8(bytes, bis[ci] + 1, Double.doubleToRawLongBits(v));
  }

  public int addDouble(double v)
  {
    int bi = add(TAG_DOUBLE, 9);
    writeS8(bytes, bi + 1, Double.doubleToRawLongBits(v));
    return conN - 2; // stupid specification
  }

  public int putDouble(double v)
  {
    int i = searchDouble(v);
    if (i < 0)
      i = addDouble(v);
    return i;
  }

  public void setRef(int ci, byte tag, int refCi, byte refTag)
  {
    getTag(ci, tag);
    getTag(refCi, refTag);
    ensureN(conN, end1Bi);
    writeU2(bytes, bis[ci] + 1, refCi);
  }

  int addRef(byte tag, int refCi, byte refTag)
  {
    getTag(refCi, refTag);
    int bi = add(tag, 3);
    writeU2(bytes, bi + 1, refCi);
    return conN - 1;
  }

  int putRef(byte tag, int refCi, byte refTag)
  {
    getTag(refCi, refTag);
    int i = searchRef(tag, refCi);
    if (i < 0)
      i = addRef(tag, refCi, refTag);
    return i;
  }

  public void setClass(int ci, int nameCi)
  {
    setRef(ci, TAG_CLASS, nameCi, TAG_UTF);
  }

  public int addClass(int nameCi)
  {
    return addRef(TAG_CLASS, nameCi, TAG_UTF);
  }

  public int putClass(int nameCi)
  {
    return putRef(TAG_CLASS, nameCi, TAG_UTF);
  }

  public int addClass(String name)
  {
    return addRef(TAG_CLASS, addUcs(Class2.pathName(name)), TAG_UTF);
  }

  public int putClass(String name)
  {
    return putRef(TAG_CLASS, putUcs(Class2.pathName(name)), TAG_UTF);
  }

  public int addClass(Class<?> cla)
  {
    return addRef(TAG_CLASS, addUtf(utf(Class2.pathName(cla))), TAG_UTF);
  }

  public int putClass(Class<?> cla)
  {
    return putRef(TAG_CLASS, putUtf(utf(Class2.pathName(cla))), TAG_UTF);
  }

  public void setString(int ci, int strCi)
  {
    setRef(ci, TAG_STRING, strCi, TAG_UTF);
  }

  public int addString(int strCi)
  {
    return addRef(TAG_STRING, strCi, TAG_UTF);
  }

  public int putString(int strCi)
  {
    return putRef(TAG_STRING, strCi, TAG_UTF);
  }

  public int addString(String str)
  {
    return addRef(TAG_STRING, addUcs(str), TAG_UTF);
  }

  public int putString(String str)
  {
    return putRef(TAG_STRING, putUcs(str), TAG_UTF);
  }

  public void setRef2(int ci, byte tag, int ref1Ci, byte ref1Tag, int ref2Ci, byte ref2Tag)
  {
    getTag(ci, tag);
    getTag(ref1Ci, ref1Tag);
    getTag(ref2Ci, ref2Tag);
    ensureN(conN, end1Bi);
    writeU2(bytes, bis[ci] + 1, ref1Ci);
    writeU2(bytes, bis[ci] + 3, ref2Ci);
  }

  int addRef2(byte tag, int ref1Ci, byte ref1Tag, int ref2Ci, byte ref2Tag)
  {
    getTag(ref1Ci, ref1Tag);
    getTag(ref2Ci, ref2Tag);
    int bi = add(tag, 5);
    writeU2(bytes, bi + 1, ref1Ci);
    writeU2(bytes, bi + 3, ref2Ci);
    return conN - 1;
  }

  int putRef2(byte tag, int ref1Ci, byte ref1Tag, int ref2Ci, byte ref2Tag)
  {
    getTag(ref1Ci, ref1Tag);
    getTag(ref2Ci, ref2Tag);
    int i = searchRef2(tag, ref1Ci, ref2Ci);
    if (i < 0)
      i = addRef2(tag, ref1Ci, ref1Tag, ref2Ci, ref2Tag);
    return i;
  }

  public void setField(int ci, int classCi, int nameDescCi)
  {
    setRef2(ci, TAG_FIELD, classCi, TAG_CLASS, nameDescCi, TAG_NAMEDESC);
  }

  public int addField(int classCi, int nameDescCi)
  {
    return addRef2(TAG_FIELD, classCi, TAG_CLASS, nameDescCi, TAG_NAMEDESC);
  }

  public int putField(int classCi, int nameDescCi)
  {
    return putRef2(TAG_FIELD, classCi, TAG_CLASS, nameDescCi, TAG_NAMEDESC);
  }

  public int addField(java.lang.reflect.Field f)
  {
    return addField(addClass(f.getDeclaringClass()), addNameDesc(f));
  }

  public int putField(java.lang.reflect.Field f)
  {
    return putField(putClass(f.getDeclaringClass()), putNameDesc(f));
  }

  public void setCproc(int ci, int classCi, int nameDescCi)
  {
    setRef2(ci, TAG_CPROC, classCi, TAG_CLASS, nameDescCi, TAG_NAMEDESC);
  }

  public int addCproc(int classCi, int nameDescCi)
  {
    return addRef2(TAG_CPROC, classCi, TAG_CLASS, nameDescCi, TAG_NAMEDESC);
  }

  public int putCproc(int classCi, int nameDescCi)
  {
    return putRef2(TAG_CPROC, classCi, TAG_CLASS, nameDescCi, TAG_NAMEDESC);
  }

  public void setIproc(int ci, int classCi, int nameDescCi)
  {
    setRef2(ci, TAG_IPROC, classCi, TAG_CLASS, nameDescCi, TAG_NAMEDESC);
  }

  public int addIproc(int classCi, int nameDescCi)
  {
    return addRef2(TAG_IPROC, classCi, TAG_CLASS, nameDescCi, TAG_NAMEDESC);
  }

  public int putIproc(int classCi, int nameDescCi)
  {
    return putRef2(TAG_IPROC, classCi, TAG_CLASS, nameDescCi, TAG_NAMEDESC);
  }

  public int addProc(Constructor<?> c)
  {
    return addRef2(TAG_CPROC, addClass(c.getDeclaringClass()), TAG_CLASS, addNameDesc(c),
      TAG_NAMEDESC);
  }

  public int putProc(Constructor<?> c)
  {
    return putRef2(TAG_CPROC, putClass(c.getDeclaringClass()), TAG_CLASS, putNameDesc(c),
      TAG_NAMEDESC);
  }

  public int addProc(Method m)
  {
    return addRef2(m.getDeclaringClass().isInterface() ? TAG_IPROC : TAG_CPROC,
      addClass(m.getDeclaringClass()), TAG_CLASS, addNameDesc(m), TAG_NAMEDESC);
  }

  public int putProc(Method m)
  {
    return putRef2(m.getDeclaringClass().isInterface() ? TAG_IPROC : TAG_CPROC,
      putClass(m.getDeclaringClass()), TAG_CLASS, putNameDesc(m), TAG_NAMEDESC);
  }

  public int addCtor0(int classCi)
  {
    return addRef2(TAG_CPROC, classCi, TAG_CLASS, //
      addNameDesc(Procedure.CTOR_NAME_, Procedure.VOID_DESC_), TAG_NAMEDESC);
  }

  public int putCtor0(int classCi)
  {
    return putRef2(TAG_CPROC, classCi, TAG_CLASS, //
      putNameDesc(Procedure.CTOR_NAME_, Procedure.VOID_DESC_), TAG_NAMEDESC);
  }

  public void setNameDesc(int ci, int nameCi, int descCi)
  {
    setRef2(ci, TAG_NAMEDESC, nameCi, TAG_UTF, descCi, TAG_UTF);
  }

  public int addNameDesc(int nameCi, int descCi)
  {
    return addRef2(TAG_NAMEDESC, nameCi, TAG_UTF, descCi, TAG_UTF);
  }

  public int putNameDesc(int nameCi, int descCi)
  {
    return putRef2(TAG_NAMEDESC, nameCi, TAG_UTF, descCi, TAG_UTF);
  }

  public int addNameDesc(Bytes name, Bytes desc)
  {
    return addRef2(TAG_NAMEDESC, addUtf(name), TAG_UTF, addUtf(desc), TAG_UTF);
  }

  public int putNameDesc(Bytes name, Bytes desc)
  {
    return putRef2(TAG_NAMEDESC, putUtf(name), TAG_UTF, putUtf(desc), TAG_UTF);
  }

  public int addNameDesc(java.lang.reflect.Field f)
  {
    return addNameDesc(utf(f.getName()), utf(Class2.descript(f)));
  }

  public int putNameDesc(java.lang.reflect.Field f)
  {
    return putNameDesc(utf(f.getName()), utf(Class2.descript(f)));
  }

  public int addNameDesc(Constructor<?> c)
  {
    return addNameDesc(Procedure.CTOR_NAME_, utf(Class2.descript(c)));
  }

  public int putNameDesc(Constructor<?> c)
  {
    return putNameDesc(Procedure.CTOR_NAME_, utf(Class2.descript(c)));
  }

  public int addNameDesc(Method m)
  {
    return addNameDesc(utf(m.getName()), utf(Class2.descript(m)));
  }

  public int putNameDesc(Method m)
  {
    return putNameDesc(utf(m.getName()), utf(Class2.descript(m)));
  }

  // ********************************************************************************

  public int addUtf(Constants cons, int ci)
  {
    return addUtf(new Bytes(cons.bytes, cons.getUtfBegin(ci), cons.getUtfEnd1(ci)));
  }

  public int putUtf(Constants cons, int ci)
  {
    return putUtf(new Bytes(cons.bytes, cons.getUtfBegin(ci), cons.getUtfEnd1(ci)));
  }

  public int addClass(Constants cons, int ci)
  {
    return addClass(addUtf(cons, cons.getClass(ci)));
  }

  public int putClass(Constants cons, int ci)
  {
    return putClass(putUtf(cons, cons.getClass(ci)));
  }

  public int addString(Constants cons, int ci)
  {
    return addString(addUtf(cons, cons.getString(ci)));
  }

  public int putString(Constants cons, int ci)
  {
    return putString(putUtf(cons, cons.getString(ci)));
  }

  public int addField(Constants cons, int ci)
  {
    return addField(addClass(addUtf(cons, cons.getFieldClass(ci))), addNameDesc(addUtf(
      cons, cons.getFieldName(ci)), //
      addUtf(cons, cons.getFieldDesc(ci))));
  }

  public int putField(Constants cons, int ci)
  {
    return putField(putClass(putUtf(cons, cons.getFieldClass(ci))), //
      putNameDesc(putUtf(cons, cons.getFieldName(ci)), //
        putUtf(cons, cons.getFieldDesc(ci))));
  }

  public int addCproc(Constants cons, int ci)
  {
    return addCproc(addClass(addUtf(cons, cons.getCprocClass(ci))), addNameDesc(addUtf(
      cons, cons.getCprocName(ci)), //
      addUtf(cons, cons.getCprocDesc(ci))));
  }

  public int putCproc(Constants cons, int ci)
  {
    return putCproc(putClass(putUtf(cons, cons.getCprocClass(ci))), //
      putNameDesc(putUtf(cons, cons.getCprocName(ci)), //
        putUtf(cons, cons.getCprocDesc(ci))));
  }

  public int addIproc(Constants cons, int ci)
  {
    return addIproc(addClass(addUtf(cons, cons.getIprocClass(ci))), addNameDesc(addUtf(
      cons, cons.getIprocName(ci)), //
      addUtf(cons, cons.getIprocDesc(ci))));
  }

  public int putIproc(Constants cons, int ci)
  {
    return putIproc(putClass(putUtf(cons, cons.getIprocClass(ci))), //
      putNameDesc(putUtf(cons, cons.getIprocName(ci)), //
        putUtf(cons, cons.getIprocDesc(ci))));
  }

  public int addNameDesc(Constants cons, int ci)
  {
    return addNameDesc(addUtf(cons, cons.getNameDescName(ci)), //
      addUtf(cons, cons.getNameDescDesc(ci)));
  }

  public int putNameDesc(Constants cons, int ci)
  {
    return putNameDesc(putUtf(cons, cons.getNameDescName(ci)), //
      putUtf(cons, cons.getNameDescDesc(ci)));
  }

  public int addConstant(Constants cons, int ci)
  {
    switch (cons.getTag(ci))
    {
    case TAG_UTF:
      return addUtf(cons, ci);
    case TAG_INT:
      return addInt(cons.getInt(ci));
    case TAG_FLOAT:
      return addFloat(cons.getFloat(ci));
    case TAG_LONG:
      return addLong(cons.getLong(ci));
    case TAG_DOUBLE:
      return addDouble(cons.getDouble(ci));
    case TAG_CLASS:
      return addClass(cons, ci);
    case TAG_STRING:
      return addString(cons, ci);
    case TAG_FIELD:
      return addField(cons, ci);
    case TAG_CPROC:
      return addCproc(cons, ci);
    case TAG_IPROC:
      return addIproc(cons, ci);
    case TAG_NAMEDESC:
      return addNameDesc(cons, ci);
    }
    throw new ClassFormatError("invalid constant info tag " + cons.getTag(ci));
  }

  public int putConstant(Constants cons, int ci)
  {
    switch (cons.getTag(ci))
    {
    case TAG_UTF:
      return putUtf(cons, ci);
    case TAG_INT:
      return putInt(cons.getInt(ci));
    case TAG_FLOAT:
      return putFloat(cons.getFloat(ci));
    case TAG_LONG:
      return putLong(cons.getLong(ci));
    case TAG_DOUBLE:
      return putDouble(cons.getDouble(ci));
    case TAG_CLASS:
      return putClass(cons, ci);
    case TAG_STRING:
      return putString(cons, ci);
    case TAG_FIELD:
      return putField(cons, ci);
    case TAG_CPROC:
      return putCproc(cons, ci);
    case TAG_IPROC:
      return putIproc(cons, ci);
    case TAG_NAMEDESC:
      return putNameDesc(cons, ci);
    }
    throw new ClassFormatError("invalid constant info tag " + cons.getTag(ci));
  }

  @Override
  public int normalizeByteN()
  {
    return byteN();
  }

  @Override
  public int normalizeTo(byte[] bs, int begin)
  {
    System.arraycopy(bytes, beginBi, bs, begin, byteN());
    writeU2(bs, begin, conN);
    return begin + byteN();
  }
}
TOP

Related Classes of objot.bytecode.Constants

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.