Commit | Line | Data |
---|---|---|
a52fde77 | 1 | /******************************************************************************* |
60ae41e1 | 2 | * Copyright (c) 2012, 2014 Ericsson |
a52fde77 AM |
3 | * Copyright (c) 2010, 2011 École Polytechnique de Montréal |
4 | * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> | |
5df842b3 | 5 | * |
a52fde77 AM |
6 | * All rights reserved. This program and the accompanying materials are |
7 | * made available under the terms of the Eclipse Public License v1.0 which | |
8 | * accompanies this distribution, and is available at | |
9 | * http://www.eclipse.org/legal/epl-v10.html | |
5df842b3 | 10 | * |
a52fde77 AM |
11 | ******************************************************************************/ |
12 | ||
e894a508 | 13 | package org.eclipse.tracecompass.statesystem.core.statevalue; |
a52fde77 | 14 | |
77c2c2c9 | 15 | import org.eclipse.jdt.annotation.Nullable; |
e894a508 AM |
16 | import org.eclipse.tracecompass.internal.statesystem.core.Activator; |
17 | import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException; | |
6d08acca | 18 | |
a52fde77 AM |
19 | /** |
20 | * This is the wrapper class that exposes the different types of 'state values' | |
21 | * available to use in the State System. | |
5df842b3 | 22 | * |
a52fde77 AM |
23 | * This also defines how these values are to be stored in the History Tree. For |
24 | * example, we can save numerical values as integers instead of arrays of | |
25 | * 1-digit characters. | |
5df842b3 | 26 | * |
ec5fec10 | 27 | * The available types are Int, Long, Double and String. |
5df842b3 | 28 | * |
2cb26548 | 29 | * @author Alexandre Montplaisir |
a52fde77 AM |
30 | */ |
31 | public abstract class TmfStateValue implements ITmfStateValue { | |
44b69c99 EB |
32 | |
33 | // ------------------------------------------------------------------------ | |
34 | // State value caches (sizes must be powers of 2) | |
35 | // ------------------------------------------------------------------------ | |
36 | ||
37 | private static final int INT_CACHE_SIZE = 128; | |
38 | private static final int LONG_CACHE_SIZE = 128; | |
39 | private static final int DOUBLE_CACHE_SIZE = 128; | |
40 | ||
41 | private static final IntegerStateValue intCache[] = new IntegerStateValue[INT_CACHE_SIZE]; | |
42 | private static final LongStateValue longCache[] = new LongStateValue[LONG_CACHE_SIZE]; | |
43 | private static final DoubleStateValue doubleCache[] = new DoubleStateValue[DOUBLE_CACHE_SIZE]; | |
44 | ||
a9cdbafc AM |
45 | // ------------------------------------------------------------------------ |
46 | // Factory methods to instantiate new state values | |
47 | // ------------------------------------------------------------------------ | |
48 | ||
a52fde77 AM |
49 | /* |
50 | * Since all "null state values" are the same, we only need one copy in | |
51 | * memory. | |
52 | */ | |
53 | private static TmfStateValue nullValue = new NullStateValue(); | |
54 | ||
55 | /** | |
56 | * Return an instance of a "null" value. Only one copy exists in memory. | |
5df842b3 | 57 | * |
a52fde77 AM |
58 | * @return A null value |
59 | */ | |
cb42195c | 60 | public static final TmfStateValue nullValue() { |
a52fde77 AM |
61 | return nullValue; |
62 | } | |
63 | ||
64 | /** | |
65 | * Factory constructor for Integer state values | |
5df842b3 | 66 | * |
a9cdbafc AM |
67 | * @param intValue |
68 | * The integer value to contain | |
a52fde77 AM |
69 | * @return The newly-created TmfStateValue object |
70 | */ | |
71 | public static TmfStateValue newValueInt(int intValue) { | |
44b69c99 EB |
72 | /* Lookup in cache for the existence of the same value. */ |
73 | int offset = intValue & (INT_CACHE_SIZE - 1); | |
74 | IntegerStateValue cached = intCache[offset]; | |
75 | if (cached != null && cached.unboxInt() == intValue) { | |
76 | return cached; | |
77 | } | |
78 | ||
79 | /* Not in cache, create a new value and cache it. */ | |
80 | IntegerStateValue newValue = new IntegerStateValue(intValue); | |
81 | intCache[offset] = newValue; | |
82 | return newValue; | |
a52fde77 AM |
83 | } |
84 | ||
85 | /** | |
a9cdbafc | 86 | * Factory constructor for Long state values |
5df842b3 | 87 | * |
a9cdbafc AM |
88 | * @param longValue |
89 | * The long value to contain | |
90 | * @return The newly-created TmfStateValue object | |
a52fde77 | 91 | */ |
a9cdbafc | 92 | public static TmfStateValue newValueLong(long longValue) { |
44b69c99 EB |
93 | /* Lookup in cache for the existence of the same value. */ |
94 | int offset = (int) longValue & (LONG_CACHE_SIZE - 1); | |
95 | LongStateValue cached = longCache[offset]; | |
96 | if (cached != null && cached.unboxLong() == longValue) { | |
97 | return cached; | |
98 | } | |
99 | ||
100 | /* Not in cache, create a new value and cache it. */ | |
101 | LongStateValue newValue = new LongStateValue(longValue); | |
102 | longCache[offset] = newValue; | |
103 | return newValue; | |
a52fde77 AM |
104 | } |
105 | ||
a3c22e8e AM |
106 | /** |
107 | * Factory constructor for Double state values | |
108 | * | |
109 | * @param value | |
110 | * The double value to contain | |
111 | * @return The newly-created TmfStateValue object | |
112 | */ | |
113 | public static TmfStateValue newValueDouble(double value) { | |
44b69c99 EB |
114 | /* Lookup in cache for the existence of the same value. */ |
115 | int offset = (int) Double.doubleToLongBits(value) & (DOUBLE_CACHE_SIZE - 1); | |
116 | DoubleStateValue cached = doubleCache[offset]; | |
117 | ||
118 | /* | |
119 | * We're using Double.compare() instead of .equals(), because .compare() | |
120 | * works when both values are Double.NaN. | |
121 | */ | |
122 | if (cached != null && Double.compare(cached.unboxDouble(), value) == 0) { | |
123 | return cached; | |
124 | } | |
125 | ||
126 | /* Not in cache, create a new value and cache it. */ | |
127 | DoubleStateValue newValue = new DoubleStateValue(value); | |
128 | doubleCache[offset] = newValue; | |
129 | return newValue; | |
a3c22e8e AM |
130 | } |
131 | ||
1cbf1a19 | 132 | /** |
a9cdbafc | 133 | * Factory constructor for String state values |
1cbf1a19 | 134 | * |
a9cdbafc AM |
135 | * @param strValue |
136 | * The string value to contain | |
137 | * @return The newly-created TmfStateValue object | |
1cbf1a19 | 138 | */ |
77c2c2c9 | 139 | public static TmfStateValue newValueString(@Nullable String strValue) { |
a9cdbafc | 140 | if (strValue == null) { |
1cbf1a19 FR |
141 | return nullValue(); |
142 | } | |
3cf9b392 AM |
143 | /* |
144 | * Make sure the String does not contain "weird" things, like ISO | |
145 | * control characters. | |
146 | */ | |
147 | for (char c : strValue.toCharArray()) { | |
148 | if (Character.isISOControl(c)) { | |
149 | Activator.getDefault().logError("Trying to use invalid string: " + strValue); //$NON-NLS-1$ | |
150 | throw new IllegalArgumentException(); | |
151 | } | |
152 | } | |
a9cdbafc | 153 | return new StringStateValue(strValue); |
1cbf1a19 FR |
154 | } |
155 | ||
a9cdbafc AM |
156 | // ------------------------------------------------------------------------ |
157 | // Default unboxing methods. | |
158 | // Subclasses can override those for the types they support. | |
159 | // ------------------------------------------------------------------------ | |
a52fde77 | 160 | |
a9cdbafc AM |
161 | private String unboxErrMsg(String targetType) { |
162 | return "Type " + getClass().getSimpleName() + //$NON-NLS-1$ | |
ec5fec10 | 163 | " cannot be unboxed into a " + targetType + " value."; //$NON-NLS-1$ //$NON-NLS-2$ |
a52fde77 AM |
164 | } |
165 | ||
166 | @Override | |
6dd46830 | 167 | public int unboxInt() { |
a9cdbafc | 168 | throw new StateValueTypeException(unboxErrMsg("Int")); //$NON-NLS-1$ |
a52fde77 | 169 | } |
1cbf1a19 | 170 | |
1cbf1a19 | 171 | @Override |
6dd46830 | 172 | public long unboxLong() { |
a9cdbafc AM |
173 | throw new StateValueTypeException(unboxErrMsg("Long")); //$NON-NLS-1$ |
174 | } | |
1cbf1a19 | 175 | |
a3c22e8e | 176 | @Override |
6dd46830 | 177 | public double unboxDouble() { |
a3c22e8e AM |
178 | throw new StateValueTypeException(unboxErrMsg("Double")); //$NON-NLS-1$ |
179 | } | |
180 | ||
a9cdbafc | 181 | @Override |
6dd46830 | 182 | public String unboxStr() { |
a9cdbafc | 183 | throw new StateValueTypeException(unboxErrMsg("String")); //$NON-NLS-1$ |
1cbf1a19 | 184 | } |
a52fde77 | 185 | } |