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