1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.bcel.internal.generic;
  23 
  24 import java.io.*;
  25 import com.sun.org.apache.bcel.internal.util.ByteSequence;
  26 
  27 /**
  28  * LDC - Push item from constant pool.
  29  *
  30  * <PRE>Stack: ... -&gt; ..., item</PRE>
  31  *
  32  * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  33  */
  34 public class LDC extends CPInstruction
  35   implements PushInstruction, ExceptionThrower, TypedInstruction {
  36   /**
  37    * Empty constructor needed for the Class.newInstance() statement in
  38    * Instruction.readInstruction(). Not to be used otherwise.
  39    */
  40   LDC() {}
  41 
  42   public LDC(int index) {
  43     super(com.sun.org.apache.bcel.internal.Constants.LDC_W, index);
  44     setSize();
  45   }
  46 
  47   // Adjust to proper size
  48   protected final void setSize() {
  49     if(index <= com.sun.org.apache.bcel.internal.Constants.MAX_BYTE) { // Fits in one byte?
  50       opcode = com.sun.org.apache.bcel.internal.Constants.LDC;
  51       length = 2;
  52     } else {
  53       opcode = com.sun.org.apache.bcel.internal.Constants.LDC_W;
  54       length = 3;
  55     }
  56   }
  57 
  58   /**
  59    * Dump instruction as byte code to stream out.
  60    * @param out Output stream
  61    */
  62   public void dump(DataOutputStream out) throws IOException {
  63     out.writeByte(opcode);
  64 
  65     if(length == 2)
  66       out.writeByte(index);
  67     else // Applies for LDC_W
  68       out.writeShort(index);
  69   }
  70 
  71   /**
  72    * Set the index to constant pool and adjust size.
  73    */
  74   public final void setIndex(int index) {
  75     super.setIndex(index);
  76     setSize();
  77   }
  78 
  79   /**
  80    * Read needed data (e.g. index) from file.
  81    */
  82   protected void initFromFile(ByteSequence bytes, boolean wide)
  83        throws IOException
  84   {
  85     length = 2;
  86     index  = bytes.readUnsignedByte();
  87   }
  88 
  89   public Object getValue(ConstantPoolGen cpg) {
  90     com.sun.org.apache.bcel.internal.classfile.Constant c = cpg.getConstantPool().getConstant(index);
  91 
  92     switch(c.getTag()) {
  93       case com.sun.org.apache.bcel.internal.Constants.CONSTANT_String:
  94         int i = ((com.sun.org.apache.bcel.internal.classfile.ConstantString)c).getStringIndex();
  95         c = cpg.getConstantPool().getConstant(i);
  96         return ((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8)c).getBytes();
  97 
  98     case com.sun.org.apache.bcel.internal.Constants.CONSTANT_Float:
  99         return new Float(((com.sun.org.apache.bcel.internal.classfile.ConstantFloat)c).getBytes());
 100 
 101     case com.sun.org.apache.bcel.internal.Constants.CONSTANT_Integer:
 102         return new Integer(((com.sun.org.apache.bcel.internal.classfile.ConstantInteger)c).getBytes());
 103 
 104     default: // Never reached
 105       throw new RuntimeException("Unknown or invalid constant type at " + index);
 106       }
 107   }
 108 
 109   public Type getType(ConstantPoolGen cpg) {
 110     switch(cpg.getConstantPool().getConstant(index).getTag()) {
 111     case com.sun.org.apache.bcel.internal.Constants.CONSTANT_String:  return Type.STRING;
 112     case com.sun.org.apache.bcel.internal.Constants.CONSTANT_Float:   return Type.FLOAT;
 113     case com.sun.org.apache.bcel.internal.Constants.CONSTANT_Integer: return Type.INT;
 114     default: // Never reached
 115       throw new RuntimeException("Unknown or invalid constant type at " + index);
 116     }
 117   }
 118 
 119   public Class[] getExceptions() {
 120     return com.sun.org.apache.bcel.internal.ExceptionConstants.EXCS_STRING_RESOLUTION;
 121   }
 122 
 123   /**
 124    * Call corresponding visitor method(s). The order is:
 125    * Call visitor methods of implemented interfaces first, then
 126    * call methods according to the class hierarchy in descending order,
 127    * i.e., the most specific visitXXX() call comes last.
 128    *
 129    * @param v Visitor object
 130    */
 131   public void accept(Visitor v) {
 132     v.visitStackProducer(this);
 133     v.visitPushInstruction(this);
 134     v.visitExceptionThrower(this);
 135     v.visitTypedInstruction(this);
 136     v.visitCPInstruction(this);
 137     v.visitLDC(this);
 138   }
 139 }