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