1 /*******************************************************************************
2 * Copyright (c) 2012, 2014 Ericsson
3 * Copyright (c) 2010, 2011 École Polytechnique de Montréal
4 * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
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
11 ******************************************************************************/
13 package org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
;
15 import org
.eclipse
.jdt
.annotation
.Nullable
;
16 import org
.eclipse
.tracecompass
.internal
.statesystem
.core
.Activator
;
17 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
20 * This is the wrapper class that exposes the different types of 'state values'
21 * available to use in the State System.
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
27 * The available types are Int, Long, Double and String.
29 * @author Alexandre Montplaisir
31 public abstract class TmfStateValue
implements ITmfStateValue
{
33 // ------------------------------------------------------------------------
34 // State value caches (sizes must be powers of 2)
35 // ------------------------------------------------------------------------
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;
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
];
45 // ------------------------------------------------------------------------
46 // Factory methods to instantiate new state values
47 // ------------------------------------------------------------------------
50 * Since all "null state values" are the same, we only need one copy in
53 private static TmfStateValue nullValue
= new NullStateValue();
56 * Return an instance of a "null" value. Only one copy exists in memory.
58 * @return A null value
60 public static final TmfStateValue
nullValue() {
65 * Factory constructor for Integer state values
68 * The integer value to contain
69 * @return The newly-created TmfStateValue object
71 public static TmfStateValue
newValueInt(int intValue
) {
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
) {
79 /* Not in cache, create a new value and cache it. */
80 IntegerStateValue newValue
= new IntegerStateValue(intValue
);
81 intCache
[offset
] = newValue
;
86 * Factory constructor for Long state values
89 * The long value to contain
90 * @return The newly-created TmfStateValue object
92 public static TmfStateValue
newValueLong(long longValue
) {
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
) {
100 /* Not in cache, create a new value and cache it. */
101 LongStateValue newValue
= new LongStateValue(longValue
);
102 longCache
[offset
] = newValue
;
107 * Factory constructor for Double state values
110 * The double value to contain
111 * @return The newly-created TmfStateValue object
113 public static TmfStateValue
newValueDouble(double value
) {
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
];
119 * We're using Double.compare() instead of .equals(), because .compare()
120 * works when both values are Double.NaN.
122 if (cached
!= null && Double
.compare(cached
.unboxDouble(), value
) == 0) {
126 /* Not in cache, create a new value and cache it. */
127 DoubleStateValue newValue
= new DoubleStateValue(value
);
128 doubleCache
[offset
] = newValue
;
133 * Factory constructor for String state values
136 * The string value to contain
137 * @return The newly-created TmfStateValue object
139 public static TmfStateValue
newValueString(@Nullable String strValue
) {
140 if (strValue
== null) {
144 * Make sure the String does not contain "weird" things, like ISO
145 * control characters.
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();
153 return new StringStateValue(strValue
);
156 // ------------------------------------------------------------------------
157 // Default unboxing methods.
158 // Subclasses can override those for the types they support.
159 // ------------------------------------------------------------------------
161 private String
unboxErrMsg(String targetType
) {
162 return "Type " + getClass().getSimpleName() + //$NON-NLS-1$
163 " cannot be unboxed into a " + targetType
+ " value."; //$NON-NLS-1$ //$NON-NLS-2$
167 public int unboxInt() {
168 throw new StateValueTypeException(unboxErrMsg("Int")); //$NON-NLS-1$
172 public long unboxLong() {
173 throw new StateValueTypeException(unboxErrMsg("Long")); //$NON-NLS-1$
177 public double unboxDouble() {
178 throw new StateValueTypeException(unboxErrMsg("Double")); //$NON-NLS-1$
182 public String
unboxStr() {
183 throw new StateValueTypeException(unboxErrMsg("String")); //$NON-NLS-1$