1 /*
2  * Copyright 2014 - 2020 Rafael Winterhalter
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package net.bytebuddy.implementation.bytecode.constant;
17
18 import net.bytebuddy.build.HashCodeAndEqualsPlugin;
19 import net.bytebuddy.implementation.Implementation;
20 import net.bytebuddy.implementation.bytecode.StackManipulation;
21 import net.bytebuddy.implementation.bytecode.StackSize;
22 import net.bytebuddy.jar.asm.MethodVisitor;
23 import net.bytebuddy.jar.asm.Opcodes;
24
25 /**
26  * This class is responsible for loading any {@code float} constant onto the operand stack.
27  */

28 public enum FloatConstant implements StackManipulation {
29
30     /**
31      * A {@code float} constant of value {@code 0.0f}.
32      */

33     ZERO(Opcodes.FCONST_0),
34
35     /**
36      * A {@code float} constant of value {@code 1.0f}.
37      */

38     ONE(Opcodes.FCONST_1),
39
40     /**
41      * A {@code float} constant of value {@code 2.0f}.
42      */

43     TWO(Opcodes.FCONST_2);
44
45     /**
46      * The size impact of loading a {@code float} constant onto the operand stack.
47      */

48     private static final Size SIZE = StackSize.SINGLE.toIncreasingSize();
49
50     /**
51      * The shortcut opcode for loading a {@code float} constant.
52      */

53     private final int opcode;
54
55     /**
56      * Creates a new shortcut operation for loading a common {@code float} onto the operand stack.
57      *
58      * @param opcode The shortcut opcode for loading a {@code float} constant.
59      */

60     FloatConstant(int opcode) {
61         this.opcode = opcode;
62     }
63
64     /**
65      * Creates a stack manipulation for loading a {@code float} value onto the operand stack.
66      * <p>&nbsp;</p>
67      * This is achieved either by invoking a specific opcode, if any, or by creating a constant pool entry.
68      *
69      * @param value The {@code float} value to load onto the stack.
70      * @return A stack manipulation for loading the given {@code float} value.
71      */

72     public static StackManipulation forValue(float value) {
73         if (value == 0f) {
74             return ZERO;
75         } else if (value == 1f) {
76             return ONE;
77         } else if (value == 2f) {
78             return TWO;
79         } else {
80             return new ConstantPool(value);
81         }
82     }
83
84     /**
85      * {@inheritDoc}
86      */

87     public boolean isValid() {
88         return true;
89     }
90
91     /**
92      * {@inheritDoc}
93      */

94     public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
95         methodVisitor.visitInsn(opcode);
96         return SIZE;
97     }
98
99     /**
100      * A stack manipulation for loading a {@code float} value from a class's constant pool onto the operand stack.
101      */

102     @HashCodeAndEqualsPlugin.Enhance
103     protected static class ConstantPool implements StackManipulation {
104
105         /**
106          * The {@code float} value to be loaded onto the operand stack.
107          */

108         private final float value;
109
110         /**
111          * Creates a new constant pool load operation.
112          *
113          * @param value The {@code float} value to be loaded onto the operand stack.
114          */

115         protected ConstantPool(float value) {
116             this.value = value;
117         }
118
119         /**
120          * {@inheritDoc}
121          */

122         public boolean isValid() {
123             return true;
124         }
125
126         /**
127          * {@inheritDoc}
128          */

129         public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
130             methodVisitor.visitLdcInsn(value);
131             return SIZE;
132         }
133     }
134 }
135