1 /*******************************************************************************
2 * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
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
9 * Contributors: Matthew Khouzam - Initial API and implementation
10 * Contributors: Simon Marchi - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.ctf
.core
.event
.types
;
15 import java
.util
.Collections
;
16 import java
.util
.HashSet
;
17 import java
.util
.LinkedList
;
18 import java
.util
.List
;
21 import org
.eclipse
.jdt
.annotation
.Nullable
;
22 import org
.eclipse
.tracecompass
.ctf
.core
.event
.io
.BitBuffer
;
23 import org
.eclipse
.tracecompass
.ctf
.core
.event
.scope
.IDefinitionScope
;
24 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFReaderException
;
27 * A CTF enum declaration.
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.
33 * @author Matthew Khouzam
34 * @author Simon Marchi
36 public final class EnumDeclaration
extends Declaration
implements ISimpleDatatypeDeclaration
{
38 // ------------------------------------------------------------------------
40 // ------------------------------------------------------------------------
42 private final EnumTable fTable
= new EnumTable();
43 private final IntegerDeclaration fContainerType
;
44 private final Set
<String
> fLabels
= new HashSet
<>();
46 // ------------------------------------------------------------------------
48 // ------------------------------------------------------------------------
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.
59 public EnumDeclaration(IntegerDeclaration containerType
) {
60 fContainerType
= containerType
;
63 // ------------------------------------------------------------------------
64 // Getters/Setters/Predicates
65 // ------------------------------------------------------------------------
69 * @return The container type
71 public IntegerDeclaration
getContainerType() {
72 return fContainerType
;
76 public long getAlignment() {
77 return this.getContainerType().getAlignment();
84 public int getMaximumSize() {
85 return fContainerType
.getMaximumSize();
88 // ------------------------------------------------------------------------
90 // ------------------------------------------------------------------------
96 public EnumDefinition
createDefinition(@Nullable IDefinitionScope definitionScope
, String fieldName
, BitBuffer input
) throws CTFReaderException
{
98 IntegerDefinition value
= getContainerType().createDefinition(definitionScope
, fieldName
, input
);
99 return new EnumDefinition(this, definitionScope
, fieldName
, value
);
103 * Add a value. Do not overlap, this is <em><strong>not</strong></em> an
107 * lowest value that this int can be to have label as a return
110 * highest value that this int can be to have label as a return
113 * the name of the value.
114 * @return was the value be added? true == success
116 public boolean add(long low
, long high
, @Nullable String label
) {
118 return fTable
.add(low
, high
, label
);
122 * Check if the label for a value (enum a{day=0,night=1} would return "day"
126 * the value to lookup
127 * @return the label of that value, can be null
129 public @Nullable String
query(long value
) {
130 return fTable
.query(value
);
134 * Gets a set of labels of the enum
136 * @return A set of labels of the enum, can be empty but not null
139 public Set
<String
> getLabels() {
140 return Collections
.unmodifiableSet(fLabels
);
144 * Maps integer range -> string. A simple list for now, but feel free to
145 * optimize it. Babeltrace suggests an interval tree.
147 private class EnumTable
{
149 private final List
<LabelAndRange
> ranges
= new LinkedList
<>();
154 public synchronized boolean add(long low
, long high
, @Nullable String label
) {
155 LabelAndRange newRange
= new LabelAndRange(low
, high
, label
);
157 for (LabelAndRange r
: ranges
) {
158 if (r
.intersects(newRange
)) {
163 ranges
.add(newRange
);
169 * Return the first label that matches a value
173 * @return the label corresponding to that value
175 public synchronized @Nullable String
query(long value
) {
176 for (LabelAndRange r
: ranges
) {
177 if (r
.intersects(value
)) {
185 public synchronized int hashCode() {
186 final int prime
= 31;
188 for (LabelAndRange range
: ranges
) {
189 result
= prime
* result
+ range
.hashCode();
195 public synchronized boolean equals(@Nullable Object obj
) {
202 if (getClass() != obj
.getClass()) {
205 EnumTable other
= (EnumTable
) obj
;
206 if (ranges
.size() != other
.ranges
.size()) {
209 for (int i
= 0; i
< ranges
.size(); i
++) {
210 if (!ranges
.get(i
).equals(other
.ranges
.get(i
))) {
219 private static class LabelAndRange
{
221 private final long low
, high
;
222 private final @Nullable String fLabel
;
229 public @Nullable String
getLabel() {
233 public LabelAndRange(long low
, long high
, @Nullable String str
) {
239 public boolean intersects(long i
) {
240 return (i
>= this.low
) && (i
<= this.high
);
243 public boolean intersects(LabelAndRange other
) {
244 return this.intersects(other
.low
)
245 || this.intersects(other
.high
);
249 public int hashCode() {
250 final int prime
= 31;
252 final String label
= fLabel
;
253 result
= prime
* result
+ ((label
== null) ?
0 : label
.hashCode());
254 result
= prime
* result
+ (int) (high ^
(high
>>> 32));
255 result
= prime
* result
+ (int) (low ^
(low
>>> 32));
260 public boolean equals(@Nullable Object obj
) {
267 if (getClass() != obj
.getClass()) {
270 LabelAndRange other
= (LabelAndRange
) obj
;
271 final String label
= fLabel
;
273 if (other
.fLabel
!= null) {
276 } else if (!label
.equals(other
.fLabel
)) {
279 if (high
!= other
.high
) {
282 if (low
!= other
.low
) {
290 public String
toString() {
291 /* Only used for debugging */
292 return "[declaration] enum[" + Integer
.toHexString(hashCode()) + ']'; //$NON-NLS-1$
296 public int hashCode() {
297 final int prime
= 31;
298 int result
= prime
+ fContainerType
.hashCode();
299 for (String label
: fLabels
) {
300 result
= prime
* result
+ label
.hashCode();
302 result
= prime
* result
+ fTable
.hashCode();
307 public boolean equals(@Nullable Object obj
) {
314 if (getClass() != obj
.getClass()) {
317 EnumDeclaration other
= (EnumDeclaration
) obj
;
318 if (!fContainerType
.equals(other
.fContainerType
)) {
321 if (fLabels
.size() != other
.fLabels
.size()) {
324 if (!fLabels
.containsAll(other
.fLabels
)) {
327 if (!fTable
.equals(other
.fTable
)) {