Add Trace Compass 1.1 baseline, fix some API errors
[deliverable/tracecompass.git] / ctf / org.eclipse.tracecompass.ctf.core / src / org / eclipse / tracecompass / ctf / core / event / types / EnumDeclaration.java
CommitLineData
866e5b51 1/*******************************************************************************
60ae41e1 2 * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
866e5b51
FC
3 *
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors: Matthew Khouzam - Initial API and implementation
10 * Contributors: Simon Marchi - Initial API and implementation
11 *******************************************************************************/
12
f357bcd4 13package org.eclipse.tracecompass.ctf.core.event.types;
866e5b51 14
816fde81
MK
15import java.util.Collections;
16import java.util.HashSet;
866e5b51
FC
17import java.util.LinkedList;
18import java.util.List;
0c2409c1 19import java.util.Map;
816fde81 20import java.util.Set;
866e5b51 21
f78eb6a7 22import org.eclipse.jdt.annotation.Nullable;
680f9173 23import org.eclipse.tracecompass.ctf.core.CTFException;
f357bcd4
AM
24import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
25import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope;
a4fa4e36 26
0c2409c1
MK
27import com.google.common.collect.ImmutableMap;
28
866e5b51 29/**
d37aaa7f 30 * A CTF enum declaration.
0594c61c 31 *
816fde81
MK
32 * The definition of a enum point basic data type. It will take the data from a
33 * trace and store it (and make it fit) as an integer and a string.
d37aaa7f
FC
34 *
35 * @version 1.0
36 * @author Matthew Khouzam
37 * @author Simon Marchi
866e5b51 38 */
8fa270f6 39public final class EnumDeclaration extends Declaration implements ISimpleDatatypeDeclaration {
866e5b51 40
0c2409c1
MK
41 /**
42 * A pair of longs class
43 *
6b6f22ef 44 * @since 2.0
0c2409c1
MK
45 */
46 public static class Pair {
47 private final long fFirst;
48 private final long fSecond;
49
50 private Pair(long first, long second) {
51 fFirst = first;
52 fSecond = second;
53 }
54
55 /**
56 * @return the first element
57 */
58 public long getFirst() {
59 return fFirst;
60 }
61
62 /**
63 * @return the second element
64 */
65 public long getSecond() {
66 return fSecond;
67 }
68 }
69
866e5b51
FC
70 // ------------------------------------------------------------------------
71 // Attributes
72 // ------------------------------------------------------------------------
73
816fde81
MK
74 private final EnumTable fTable = new EnumTable();
75 private final IntegerDeclaration fContainerType;
3de23137 76 private final Set<String> fLabels = new HashSet<>();
866e5b51
FC
77
78 // ------------------------------------------------------------------------
79 // Constructors
80 // ------------------------------------------------------------------------
81
9ac2eb62
MK
82 /**
83 * constructor
84 *
85 * @param containerType
86 * the enum is an int, this is the type that the data is
87 * contained in. If you have 1000 possible values, you need at
88 * least a 10 bit enum. If you store 2 values in a 128 bit int,
89 * you are wasting space.
90 */
866e5b51 91 public EnumDeclaration(IntegerDeclaration containerType) {
816fde81 92 fContainerType = containerType;
866e5b51
FC
93 }
94
95 // ------------------------------------------------------------------------
96 // Getters/Setters/Predicates
97 // ------------------------------------------------------------------------
98
9ac2eb62
MK
99 /**
100 *
101 * @return The container type
102 */
866e5b51 103 public IntegerDeclaration getContainerType() {
816fde81 104 return fContainerType;
866e5b51
FC
105 }
106
fd74e6c1
MK
107 @Override
108 public long getAlignment() {
109 return this.getContainerType().getAlignment();
110 }
9ac2eb62 111
a4fa4e36
MK
112 @Override
113 public int getMaximumSize() {
114 return fContainerType.getMaximumSize();
115 }
116
866e5b51
FC
117 // ------------------------------------------------------------------------
118 // Operations
119 // ------------------------------------------------------------------------
120
121 @Override
680f9173 122 public EnumDefinition createDefinition(@Nullable IDefinitionScope definitionScope, String fieldName, BitBuffer input) throws CTFException {
a4fa4e36
MK
123 alignRead(input);
124 IntegerDefinition value = getContainerType().createDefinition(definitionScope, fieldName, input);
125 return new EnumDefinition(this, definitionScope, fieldName, value);
866e5b51
FC
126 }
127
9ac2eb62 128 /**
8fa270f6
MK
129 * Add a value. Do not overlap, this is <em><strong>not</strong></em> an
130 * interval tree.
816fde81
MK
131 *
132 * @param low
133 * lowest value that this int can be to have label as a return
134 * string
135 * @param high
136 * highest value that this int can be to have label as a return
137 * string
138 * @param label
139 * the name of the value.
9ac2eb62
MK
140 * @return was the value be added? true == success
141 */
f78eb6a7 142 public boolean add(long low, long high, @Nullable String label) {
816fde81
MK
143 fLabels.add(label);
144 return fTable.add(low, high, label);
866e5b51
FC
145 }
146
9ac2eb62 147 /**
816fde81
MK
148 * Check if the label for a value (enum a{day=0,night=1} would return "day"
149 * for query(0)
150 *
151 * @param value
152 * the value to lookup
9ac2eb62
MK
153 * @return the label of that value, can be null
154 */
f78eb6a7 155 public @Nullable String query(long value) {
816fde81
MK
156 return fTable.query(value);
157 }
158
0c2409c1
MK
159 /**
160 * Get the lookup table
161 *
162 * @return the lookup table
6b6f22ef 163 * @since 2.0
0c2409c1
MK
164 */
165 public Map<String, Pair> getEnumTable() {
166 ImmutableMap.Builder<String, Pair> builder = new ImmutableMap.Builder<>();
167 for (LabelAndRange range : fTable.ranges) {
168 builder.put(range.getLabel(), new Pair(range.low, range.high));
169 }
170 return builder.build();
171
172 }
173
816fde81
MK
174 /**
175 * Gets a set of labels of the enum
176 *
177 * @return A set of labels of the enum, can be empty but not null
178 */
179 public Set<String> getLabels() {
180 return Collections.unmodifiableSet(fLabels);
866e5b51
FC
181 }
182
866e5b51
FC
183 /*
184 * Maps integer range -> string. A simple list for now, but feel free to
185 * optimize it. Babeltrace suggests an interval tree.
186 */
816fde81 187 private class EnumTable {
866e5b51 188
3de23137 189 private final List<LabelAndRange> ranges = new LinkedList<>();
866e5b51
FC
190
191 public EnumTable() {
192 }
193
e00e6663 194 public synchronized boolean add(long low, long high, @Nullable String label) {
816fde81 195 LabelAndRange newRange = new LabelAndRange(low, high, label);
866e5b51 196
816fde81 197 for (LabelAndRange r : ranges) {
866e5b51
FC
198 if (r.intersects(newRange)) {
199 return false;
200 }
201 }
202
203 ranges.add(newRange);
204
205 return true;
206 }
207
9ac2eb62 208 /**
a511da0d 209 * Return the first label that matches a value
816fde81
MK
210 *
211 * @param value
212 * the value to query
9ac2eb62
MK
213 * @return the label corresponding to that value
214 */
e00e6663 215 public synchronized @Nullable String query(long value) {
816fde81 216 for (LabelAndRange r : ranges) {
866e5b51 217 if (r.intersects(value)) {
096bc534 218 return r.getLabel();
866e5b51
FC
219 }
220 }
866e5b51
FC
221 return null;
222 }
223
e00e6663
MK
224 @Override
225 public synchronized int hashCode() {
226 final int prime = 31;
227 int result = 1;
228 for (LabelAndRange range : ranges) {
229 result = prime * result + range.hashCode();
230 }
231 return result;
232 }
233
234 @Override
235 public synchronized boolean equals(@Nullable Object obj) {
236 if (this == obj) {
237 return true;
238 }
239 if (obj == null) {
240 return false;
241 }
242 if (getClass() != obj.getClass()) {
243 return false;
244 }
245 EnumTable other = (EnumTable) obj;
246 if (ranges.size() != other.ranges.size()) {
247 return false;
248 }
249 for (int i = 0; i < ranges.size(); i++) {
250 if (!ranges.get(i).equals(other.ranges.get(i))) {
251 return false;
252 }
253 }
254 return true;
255 }
256
816fde81 257 }
866e5b51 258
096bc534 259 private static class LabelAndRange {
866e5b51 260
816fde81 261 private final long low, high;
f78eb6a7 262 private final @Nullable String fLabel;
866e5b51 263
096bc534
MK
264 /**
265 * Get the label
266 *
267 * @return the label
268 */
e00e6663 269 public @Nullable String getLabel() {
096bc534
MK
270 return fLabel;
271 }
272
f78eb6a7 273 public LabelAndRange(long low, long high, @Nullable String str) {
816fde81
MK
274 this.low = low;
275 this.high = high;
276 this.fLabel = str;
277 }
866e5b51 278
816fde81
MK
279 public boolean intersects(long i) {
280 return (i >= this.low) && (i <= this.high);
281 }
282
283 public boolean intersects(LabelAndRange other) {
284 return this.intersects(other.low)
285 || this.intersects(other.high);
866e5b51 286 }
e00e6663
MK
287
288 @Override
289 public int hashCode() {
290 final int prime = 31;
291 int result = 1;
292 final String label = fLabel;
293 result = prime * result + ((label == null) ? 0 : label.hashCode());
294 result = prime * result + (int) (high ^ (high >>> 32));
295 result = prime * result + (int) (low ^ (low >>> 32));
296 return result;
297 }
298
299 @Override
300 public boolean equals(@Nullable Object obj) {
301 if (this == obj) {
302 return true;
303 }
304 if (obj == null) {
305 return false;
306 }
307 if (getClass() != obj.getClass()) {
308 return false;
309 }
310 LabelAndRange other = (LabelAndRange) obj;
311 final String label = fLabel;
312 if (label == null) {
313 if (other.fLabel != null) {
314 return false;
315 }
316 } else if (!label.equals(other.fLabel)) {
317 return false;
318 }
319 if (high != other.high) {
320 return false;
321 }
322 if (low != other.low) {
323 return false;
324 }
325 return true;
326 }
866e5b51
FC
327 }
328
329 @Override
330 public String toString() {
331 /* Only used for debugging */
66aa25f0
MK
332 StringBuilder sb = new StringBuilder();
333 sb.append("[declaration] enum["); //$NON-NLS-1$
334 for (String label : fLabels) {
335 sb.append("label:").append(label).append(' '); //$NON-NLS-1$
336 }
337 sb.append("type:").append(fContainerType.toString()); //$NON-NLS-1$
338 sb.append(']');
339 String string = sb.toString();
340 if (string == null) {
341 throw new IllegalStateException();
342 }
343 return string;
866e5b51
FC
344 }
345
e00e6663
MK
346 @Override
347 public int hashCode() {
348 final int prime = 31;
349 int result = prime + fContainerType.hashCode();
350 for (String label : fLabels) {
351 result = prime * result + label.hashCode();
352 }
353 result = prime * result + fTable.hashCode();
354 return result;
355 }
356
357 @Override
358 public boolean equals(@Nullable Object obj) {
359 if (this == obj) {
360 return true;
361 }
362 if (obj == null) {
363 return false;
364 }
365 if (getClass() != obj.getClass()) {
366 return false;
367 }
368 EnumDeclaration other = (EnumDeclaration) obj;
369 if (!fContainerType.equals(other.fContainerType)) {
370 return false;
371 }
372 if (fLabels.size() != other.fLabels.size()) {
373 return false;
374 }
375 if (!fLabels.containsAll(other.fLabels)) {
376 return false;
377 }
378 if (!fTable.equals(other.fTable)) {
379 return false;
380 }
381 return true;
382 }
383
66aa25f0
MK
384 @Override
385 public boolean isBinaryEquivalent(@Nullable IDeclaration obj) {
386 if (this == obj) {
387 return true;
388 }
389 if (obj == null) {
390 return false;
391 }
392 if (getClass() != obj.getClass()) {
393 return false;
394 }
395 EnumDeclaration other = (EnumDeclaration) obj;
396 if (!fContainerType.isBinaryEquivalent(other.fContainerType)) {
397 return false;
398 }
399 if (fLabels.size() != other.fLabels.size()) {
400 return false;
401 }
402 if (!fLabels.containsAll(other.fLabels)) {
403 return false;
404 }
405 if (!fTable.equals(other.fTable)) {
406 return false;
407 }
408 return true;
409 }
410
866e5b51 411}
This page took 0.079989 seconds and 5 git commands to generate.