/* Soot - a J*va Optimization Framework * Copyright (C) 1997 Clark Verbrugge * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* * Modified by the Sable Research Group and others 1997-1999. * See the 'credits' file distributed with Soot for the complete list of * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot) */ package soot.coffi; import soot.*; import soot.jimple.StringConstant; import java.io.*; import javax.naming.OperationNotSupportedException; /** A constant pool entry of type CONSTANT_Utf8; note this is <b>not</b> * multithread safe. It is, however, immutable. * @see cp_info * @author Clark Verbrugge */ public class CONSTANT_Utf8_info extends cp_info { // Some local private objects to help with efficient comparisons. private int sHashCode; // for caching the conversion. private String s; /** Byte array of actual utf8 string. */ private final byte bytes[]; /** Constructor from a DataInputSream */ public CONSTANT_Utf8_info(DataInputStream d) throws IOException { int len; len = d.readUnsignedShort(); bytes = new byte[len+2]; bytes[0] = (byte)(len>>8); bytes[1] = (byte)(len & 0xff); if (len>0) { int j; for (j=0; j<len;j++) bytes[j+2] = (byte)d.readUnsignedByte(); } } /** For writing out the byte stream for this utf8 properly (incl size). */ public void writeBytes(DataOutputStream dd) throws IOException { int len; len = bytes.length; dd.writeShort(len-2); dd.write(bytes,2,len-2); } /** Length in bytes of byte array. */ public int length() { return (((((bytes[0]))&0xff)<<8) + (((bytes[1]))&0xff)); } /** Returns the size of this cp_info object. * @return number of bytes occupied by this object. * @see cp_info#size */ public int size() { return length()+3; } /** Converts internal representation into an actual String. * @return String version of this utf8 object. */ public String convert() { if (s==null) { try { ByteArrayInputStream bs = new ByteArrayInputStream(bytes); DataInputStream d = new DataInputStream(bs); String buf = d.readUTF(); sHashCode = buf.hashCode(); return buf; } catch(IOException e) { return "!!IOException!!"; } } return s; } /** Fixes the actual String used to represent the internal representation. * We must have rep == convert(); we verify hashCodes() to spot-check this. * No user-visible effects. */ public void fixConversion(String rep) { if (sHashCode != rep.hashCode()) throw new RuntimeException("bad use of fixConversion!"); if (s == null) { s = rep; } } /** Answers whether this utf8 string is the same as a given one. * @param cu utf8 object with which to compare. * @return <i>true</i> if they are equal, <i>false</i> if they are not. */ public boolean equals(CONSTANT_Utf8_info cu) { int i,j; j = bytes.length; if (j!=cu.bytes.length) return false; for (i=0; i<j; i++) { if (bytes[i]!=cu.bytes[i]) return false; } return true; } /** Compares this entry with another cp_info object (which may reside * in a different constant pool). * @param constant_pool constant pool of ClassFile for this. * @param cp constant pool entry to compare against. * @param cp_constant_pool constant pool of ClassFile for cp. * @return a value <0, 0, or >0 indicating whether this is smaller, * the same or larger than cp. * @see cp_info#compareTo * @see CONSTANT_Utf8_info#compareTo(cp_info) */ public int compareTo(cp_info constant_pool[],cp_info cp,cp_info cp_constant_pool[]) { return compareTo(cp); } /** Compares this entry with another cp_info object; note that for Utf8 * object it really doesn't matter whether they're in the same or a different * constant pool, since they really do carry all their data. * @param cp constant pool entry to compare against. * @return a value <0, 0, or >0 indicating whether this is smaller, * the same or larger than cp. * @see cp_info#compareTo * @see CONSTANT_Utf8_info#compareTo(cp_info[],cp_info,cp_info[]) */ public int compareTo(cp_info cp) { if (tag!=cp.tag) return tag-cp.tag; CONSTANT_Utf8_info cu = (CONSTANT_Utf8_info)cp; G.v().coffi_CONSTANT_Utf8_info_e1.reset(bytes); G.v().coffi_CONSTANT_Utf8_info_e2.reset(cu.bytes); for (;G.v().coffi_CONSTANT_Utf8_info_e1.hasMoreElements() && G.v().coffi_CONSTANT_Utf8_info_e2.hasMoreElements();) { G.v().coffi_CONSTANT_Utf8_info_e1.nextElement(); G.v().coffi_CONSTANT_Utf8_info_e2.nextElement(); if (G.v().coffi_CONSTANT_Utf8_info_e1.c<G.v().coffi_CONSTANT_Utf8_info_e2.c) return -1; if (G.v().coffi_CONSTANT_Utf8_info_e2.c<G.v().coffi_CONSTANT_Utf8_info_e1.c) return 1; } if (G.v().coffi_CONSTANT_Utf8_info_e1.hasMoreElements()) return -1; if (G.v().coffi_CONSTANT_Utf8_info_e2.hasMoreElements()) return 1; return 0; } /** Utility method; converts the given String into a utf8 encoded array * of bytes. * @param s String to encode. * @return array of bytes, utf8 encoded version of s. */ public static byte[] toUtf8(String s) { try { ByteArrayOutputStream bs = new ByteArrayOutputStream(s.length()); DataOutputStream d = new DataOutputStream(bs); d.writeUTF(s); return bs.toByteArray(); } catch(IOException e) { G.v().out.println("Some sort of IO exception in toUtf8 with " + s); } return null; } /** Returns a String representation of this entry. * @param constant_pool constant pool of ClassFile. * @return String representation of this entry. * @see cp_info#toString */ public String toString(cp_info constant_pool[]) { return convert(); } /** Returns a String description of what kind of entry this is. * @return the String "utf8". * @see cp_info#typeName */ public String typeName() { return "utf8"; } public Value createJimpleConstantValue(cp_info[] constant_pool) { return StringConstant.v(convert()); } }