1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21package proguard.evaluation.value;
22
23import proguard.classfile.*;
24import proguard.classfile.util.ClassUtil;
25
26/**
27 * This class provides methods to create and reuse Value objects.
28 *
29 * @author Eric Lafortune
30 */
31public class ValueFactory
32{
33    // Shared copies of Value objects, to avoid creating a lot of objects.
34    static final IntegerValue INTEGER_VALUE = new UnknownIntegerValue();
35    static final LongValue    LONG_VALUE    = new UnknownLongValue();
36    static final FloatValue   FLOAT_VALUE   = new UnknownFloatValue();
37    static final DoubleValue  DOUBLE_VALUE  = new UnknownDoubleValue();
38
39    static final ReferenceValue REFERENCE_VALUE_NULL                        = new ReferenceValue(null, null, true);
40    static final ReferenceValue REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL = new ReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT, null, true);
41    static final ReferenceValue REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL   = new ReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT, null, false);
42
43
44    /**
45     * Creates a new Value of the given type.
46     * The type must be a fully specified internal type for primitives, classes,
47     * or arrays.
48     */
49    public Value createValue(String type, Clazz referencedClass, boolean mayBeNull)
50    {
51        switch (type.charAt(0))
52        {
53            case ClassConstants.INTERNAL_TYPE_VOID:    return null;
54            case ClassConstants.INTERNAL_TYPE_BOOLEAN:
55            case ClassConstants.INTERNAL_TYPE_BYTE:
56            case ClassConstants.INTERNAL_TYPE_CHAR:
57            case ClassConstants.INTERNAL_TYPE_SHORT:
58            case ClassConstants.INTERNAL_TYPE_INT:     return createIntegerValue();
59            case ClassConstants.INTERNAL_TYPE_LONG:    return createLongValue();
60            case ClassConstants.INTERNAL_TYPE_FLOAT:   return createFloatValue();
61            case ClassConstants.INTERNAL_TYPE_DOUBLE:  return createDoubleValue();
62            default:                                   return createReferenceValue(ClassUtil.isInternalArrayType(type) ?
63                                                                                       type :
64                                                                                       ClassUtil.internalClassNameFromClassType(type),
65                                                                                   referencedClass,
66                                                                                   mayBeNull);
67        }
68    }
69
70    /**
71     * Creates a new IntegerValue with an undefined value.
72     */
73    public IntegerValue createIntegerValue()
74    {
75        return INTEGER_VALUE;
76    }
77
78    /**
79     * Creates a new IntegerValue with a given particular value.
80     */
81    public IntegerValue createIntegerValue(int value)
82    {
83        return createIntegerValue();
84    }
85
86
87    /**
88     * Creates a new LongValue with an undefined value.
89     */
90    public LongValue createLongValue()
91    {
92        return LONG_VALUE;
93    }
94
95    /**
96     * Creates a new LongValue with a given particular value.
97     */
98    public LongValue createLongValue(long value)
99    {
100        return createLongValue();
101    }
102
103
104    /**
105     * Creates a new FloatValue with an undefined value.
106     */
107    public FloatValue createFloatValue()
108    {
109        return FLOAT_VALUE;
110    }
111
112    /**
113     * Creates a new FloatValue with a given particular value.
114     */
115    public FloatValue createFloatValue(float value)
116    {
117        return createFloatValue();
118    }
119
120
121    /**
122     * Creates a new DoubleValue with an undefined value.
123     */
124    public DoubleValue createDoubleValue()
125    {
126        return DOUBLE_VALUE;
127    }
128
129    /**
130     * Creates a new DoubleValue with a given particular value.
131     */
132    public DoubleValue createDoubleValue(double value)
133    {
134        return createDoubleValue();
135    }
136
137
138    /**
139     * Creates a new ReferenceValue that represents <code>null</code>.
140     */
141    public ReferenceValue createReferenceValueNull()
142    {
143        return REFERENCE_VALUE_NULL;
144    }
145
146
147    /**
148     * Creates a new ReferenceValue of the given type. The type must be an
149     * internal class name or an array type. If the type is <code>null</code>,
150     * the ReferenceValue represents <code>null</code>.
151     */
152    public ReferenceValue createReferenceValue(String  type,
153                                               Clazz   referencedClass,
154                                               boolean mayBeNull)
155    {
156        return type == null                                                ? REFERENCE_VALUE_NULL                                 :
157               !type.equals(ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT) ? new ReferenceValue(type, referencedClass, mayBeNull) :
158               mayBeNull                                                   ? REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL          :
159                                                                             REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL;
160    }
161
162
163    /**
164     * Creates a new ReferenceValue for arrays of the given type and length.
165     * The type must be a fully specified internal type for primitives, classes,
166     * or arrays.
167     */
168    public ReferenceValue createArrayReferenceValue(String       type,
169                                                    Clazz        referencedClass,
170                                                    IntegerValue arrayLength)
171    {
172        return createArrayReferenceValue(type,
173                                         referencedClass,
174                                         arrayLength,
175                                         createValue(type, referencedClass, false));
176    }
177
178
179    /**
180     * Creates a new ReferenceValue for arrays of the given type and length,
181     * containing the given element. The type must be a fully specified internal
182     * type for primitives, classes, or arrays.
183     */
184    public ReferenceValue createArrayReferenceValue(String       type,
185                                                    Clazz        referencedClass,
186                                                    IntegerValue arrayLength,
187                                                    Value        elementValue)
188    {
189        return createReferenceValue(ClassConstants.INTERNAL_TYPE_ARRAY + type,
190                                    referencedClass,
191                                    false);
192    }
193}
194