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