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 21package com.sun.org.apache.bcel.internal.generic; 22 23import java.io.DataOutputStream; 24import java.io.IOException; 25 26import com.sun.org.apache.bcel.internal.ExceptionConst; 27import com.sun.org.apache.bcel.internal.util.ByteSequence; 28 29/** 30 * LDC - Push item from constant pool. 31 * 32 * <PRE>Stack: ... -> ..., item</PRE> 33 * 34 * @version $Id: LDC.java 1749603 2016-06-21 20:50:19Z ggregory $ 35 */ 36public class LDC extends CPInstruction implements PushInstruction, ExceptionThrower { 37 38 /** 39 * Empty constructor needed for the Class.newInstance() statement in 40 * Instruction.readInstruction(). Not to be used otherwise. 41 */ 42 LDC() { 43 } 44 45 46 public LDC(final int index) { 47 super(com.sun.org.apache.bcel.internal.Const.LDC_W, index); 48 setSize(); 49 } 50 51 52 // Adjust to proper size 53 protected final void setSize() { 54 if (super.getIndex() <= com.sun.org.apache.bcel.internal.Const.MAX_BYTE) { // Fits in one byte? 55 super.setOpcode(com.sun.org.apache.bcel.internal.Const.LDC); 56 super.setLength(2); 57 } else { 58 super.setOpcode(com.sun.org.apache.bcel.internal.Const.LDC_W); 59 super.setLength(3); 60 } 61 } 62 63 64 /** 65 * Dump instruction as byte code to stream out. 66 * @param out Output stream 67 */ 68 @Override 69 public void dump( final DataOutputStream out ) throws IOException { 70 out.writeByte(super.getOpcode()); 71 if (super.getLength() == 2) { // TODO useless check? 72 out.writeByte(super.getIndex()); 73 } else { 74 out.writeShort(super.getIndex()); 75 } 76 } 77 78 79 /** 80 * Set the index to constant pool and adjust size. 81 */ 82 @Override 83 public final void setIndex( final int index ) { 84 super.setIndex(index); 85 setSize(); 86 } 87 88 89 /** 90 * Read needed data (e.g. index) from file. 91 */ 92 @Override 93 protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { 94 super.setLength(2); 95 super.setIndex(bytes.readUnsignedByte()); 96 } 97 98 99 public Object getValue( final ConstantPoolGen cpg ) { 100 com.sun.org.apache.bcel.internal.classfile.Constant c = cpg.getConstantPool().getConstant(super.getIndex()); 101 switch (c.getTag()) { 102 case com.sun.org.apache.bcel.internal.Const.CONSTANT_String: 103 final int i = ((com.sun.org.apache.bcel.internal.classfile.ConstantString) c).getStringIndex(); 104 c = cpg.getConstantPool().getConstant(i); 105 return ((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes(); 106 case com.sun.org.apache.bcel.internal.Const.CONSTANT_Float: 107 return new Float(((com.sun.org.apache.bcel.internal.classfile.ConstantFloat) c).getBytes()); 108 case com.sun.org.apache.bcel.internal.Const.CONSTANT_Integer: 109 return Integer.valueOf(((com.sun.org.apache.bcel.internal.classfile.ConstantInteger) c).getBytes()); 110 case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class: 111 final int nameIndex = ((com.sun.org.apache.bcel.internal.classfile.ConstantClass) c).getNameIndex(); 112 c = cpg.getConstantPool().getConstant(nameIndex); 113 return new ObjectType(((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes()); 114 default: // Never reached 115 throw new RuntimeException("Unknown or invalid constant type at " + super.getIndex()); 116 } 117 } 118 119 120 @Override 121 public Type getType( final ConstantPoolGen cpg ) { 122 switch (cpg.getConstantPool().getConstant(super.getIndex()).getTag()) { 123 case com.sun.org.apache.bcel.internal.Const.CONSTANT_String: 124 return Type.STRING; 125 case com.sun.org.apache.bcel.internal.Const.CONSTANT_Float: 126 return Type.FLOAT; 127 case com.sun.org.apache.bcel.internal.Const.CONSTANT_Integer: 128 return Type.INT; 129 case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class: 130 return Type.CLASS; 131 default: // Never reached 132 throw new RuntimeException("Unknown or invalid constant type at " + super.getIndex()); 133 } 134 } 135 136 137 @Override 138 public Class<?>[] getExceptions() { 139 return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_STRING_RESOLUTION); 140 } 141 142 143 /** 144 * Call corresponding visitor method(s). The order is: 145 * Call visitor methods of implemented interfaces first, then 146 * call methods according to the class hierarchy in descending order, 147 * i.e., the most specific visitXXX() call comes last. 148 * 149 * @param v Visitor object 150 */ 151 @Override 152 public void accept( final Visitor v ) { 153 v.visitStackProducer(this); 154 v.visitPushInstruction(this); 155 v.visitExceptionThrower(this); 156 v.visitTypedInstruction(this); 157 v.visitCPInstruction(this); 158 v.visitLDC(this); 159 } 160} 161