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