c724410d21706952447b59424e33a6d8411b5bf1
[deliverable/tracecompass.git] / org.eclipse.tracecompass.statesystem.core / src / org / eclipse / tracecompass / statesystem / core / statevalue / TmfStateValue.java
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>
5 *
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
10 *
11 ******************************************************************************/
12
13 package org.eclipse.tracecompass.statesystem.core.statevalue;
14
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;
18
19 /**
20 * This is the wrapper class that exposes the different types of 'state values'
21 * available to use in the State System.
22 *
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.
26 *
27 * The available types are Int, Long, Double and String.
28 *
29 * @author Alexandre Montplaisir
30 */
31 public abstract class TmfStateValue implements ITmfStateValue {
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
45 // ------------------------------------------------------------------------
46 // Factory methods to instantiate new state values
47 // ------------------------------------------------------------------------
48
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.
57 *
58 * @return A null value
59 */
60 public static final TmfStateValue nullValue() {
61 return nullValue;
62 }
63
64 /**
65 * Factory constructor for Integer state values
66 *
67 * @param intValue
68 * The integer value to contain
69 * @return The newly-created TmfStateValue object
70 */
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) {
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;
83 }
84
85 /**
86 * Factory constructor for Long state values
87 *
88 * @param longValue
89 * The long value to contain
90 * @return The newly-created TmfStateValue object
91 */
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) {
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;
104 }
105
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) {
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;
130 }
131
132 /**
133 * Factory constructor for String state values
134 *
135 * @param strValue
136 * The string value to contain
137 * @return The newly-created TmfStateValue object
138 */
139 public static TmfStateValue newValueString(@Nullable String strValue) {
140 if (strValue == null) {
141 return nullValue();
142 }
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 }
153 return new StringStateValue(strValue);
154 }
155
156 // ------------------------------------------------------------------------
157 // Default unboxing methods.
158 // Subclasses can override those for the types they support.
159 // ------------------------------------------------------------------------
160
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$
164 }
165
166 @Override
167 public int unboxInt() {
168 throw new StateValueTypeException(unboxErrMsg("Int")); //$NON-NLS-1$
169 }
170
171 @Override
172 public long unboxLong() {
173 throw new StateValueTypeException(unboxErrMsg("Long")); //$NON-NLS-1$
174 }
175
176 @Override
177 public double unboxDouble() {
178 throw new StateValueTypeException(unboxErrMsg("Double")); //$NON-NLS-1$
179 }
180
181 @Override
182 public String unboxStr() {
183 throw new StateValueTypeException(unboxErrMsg("String")); //$NON-NLS-1$
184 }
185 }
This page took 0.037644 seconds and 4 git commands to generate.