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
.Collection
;
16 import java
.util
.Collections
;
17 import java
.util
.HashMap
;
19 import java
.util
.Map
.Entry
;
21 import org
.eclipse
.tracecompass
.ctf
.core
.event
.io
.BitBuffer
;
22 import org
.eclipse
.tracecompass
.ctf
.core
.event
.scope
.IDefinitionScope
;
23 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFReaderException
;
26 * A CTFC variant declaration.
28 * A variant is similar to a C union, only taking the minimum size of the types,
29 * it is a compound data type that contains other datatypes in fields. they are
30 * stored in an hashmap and indexed by names which are strings.
33 * @author Matthew Khouzam
34 * @author Simon Marchi
36 public class VariantDeclaration
extends Declaration
{
38 // ------------------------------------------------------------------------
40 // ------------------------------------------------------------------------
42 private String fTag
= null;
43 private static final long ALIGNMENT
= 1;
44 private final Map
<String
, IDeclaration
> fFields
= Collections
.synchronizedMap(new HashMap
<String
, IDeclaration
>());
45 private EnumDefinition fTagDef
;
46 private IDeclaration fDeclarationToPopulate
;
47 private IDefinitionScope fPrevDefinitionScope
;
49 // ------------------------------------------------------------------------
51 // ------------------------------------------------------------------------
56 public VariantDeclaration() {
59 // ------------------------------------------------------------------------
60 // Getters/Setters/Predicates
61 // ------------------------------------------------------------------------
64 * @return Does the variant have a tag
66 public boolean isTagged() {
71 * Lookup if a field exists in the variant
75 * @return true = field tag exists
77 public boolean hasField(String fieldTag
) {
78 return fFields
.containsKey(fieldTag
);
82 * Sets the tag in a variant
87 public void setTag(String tag
) {
93 * Gets current variant tag
95 * @return the variant tag.
97 public String
getTag() {
102 * Gets the fields of the variant
104 * @return the fields of the variant
107 public Map
<String
, IDeclaration
> getFields() {
112 public long getAlignment() {
116 // ------------------------------------------------------------------------
118 // ------------------------------------------------------------------------
124 public VariantDefinition
createDefinition(IDefinitionScope definitionScope
,
125 String fieldName
, BitBuffer input
) throws CTFReaderException
{
127 if (fPrevDefinitionScope
!= definitionScope
) {
129 fPrevDefinitionScope
= definitionScope
;
131 EnumDefinition tagDef
= fTagDef
;
132 if (tagDef
== null) {
133 Definition def
= definitionScope
.lookupDefinition(fTag
);
134 tagDef
= (EnumDefinition
) ((def
instanceof EnumDefinition
) ? def
: null);
136 if (tagDef
== null) {
137 throw new CTFReaderException("Tag is not defined " + fTag
); //$NON-NLS-1$
139 String varFieldName
= tagDef
.getStringValue();
140 fDeclarationToPopulate
= fFields
.get(varFieldName
);
141 if (fDeclarationToPopulate
== null) {
142 throw new CTFReaderException("Unknown enum selector for variant " + //$NON-NLS-1$
143 definitionScope
.getScopePath().toString());
145 Definition fieldValue
= fDeclarationToPopulate
.createDefinition(definitionScope
, fieldName
, input
);
146 return new VariantDefinition(this, definitionScope
, varFieldName
, fieldName
, fieldValue
);
150 * Add a field to this CTF Variant
153 * The tag of the new field
155 * The Declaration of this new field
157 public void addField(String fieldTag
, IDeclaration declaration
) {
158 fFields
.put(fieldTag
, declaration
);
162 * gets the tag definition
164 * @return the fTagDef
167 public EnumDefinition
getTagDef() {
175 public int getMaximumSize() {
176 Collection
<IDeclaration
> values
= fFields
.values();
178 for (IDeclaration field
: values
) {
179 maxSize
= Math
.max(maxSize
, field
.getMaximumSize());
185 public String
toString() {
186 /* Only used for debugging */
187 StringBuilder sb
= new StringBuilder();
188 sb
.append("[declaration] variant["); //$NON-NLS-1$
189 for (Entry
<String
, IDeclaration
> field
: fFields
.entrySet()) {
190 sb
.append(field
.getKey()).append(':').append(field
.getValue());
193 return sb
.toString();
197 public int hashCode() {
198 final int prime
= 31;
200 result
= prime
* result
+ ((fDeclarationToPopulate
== null) ?
0 : fDeclarationToPopulate
.hashCode());
201 if (fFields
== null) {
202 result
= prime
* result
;
204 for (Entry
<String
, IDeclaration
> field
: fFields
.entrySet()) {
205 result
= prime
* result
+ field
.getValue().hashCode();
208 result
= prime
* result
+ ((fPrevDefinitionScope
== null) ?
0 : fPrevDefinitionScope
.hashCode());
209 result
= prime
* result
+ ((fTag
== null) ?
0 : fTag
.hashCode());
210 result
= prime
* result
+ ((fTagDef
== null) ?
0 : fTagDef
.hashCode());
215 public boolean equals(Object obj
) {
222 if (getClass() != obj
.getClass()) {
225 VariantDeclaration other
= (VariantDeclaration
) obj
;
226 if (fDeclarationToPopulate
== null) {
227 if (other
.fDeclarationToPopulate
!= null) {
230 } else if (!fDeclarationToPopulate
.equals(other
.fDeclarationToPopulate
)) {
233 // do not check the order of the fields
235 if (fFields
== null) {
236 if (other
.fFields
!= null) {
240 if( !fFields
.equals(other
.fFields
)) {
244 if (fPrevDefinitionScope
== null) {
245 if (other
.fPrevDefinitionScope
!= null) {
248 } else if (!fPrevDefinitionScope
.equals(other
.fPrevDefinitionScope
)) {
252 if (other
.fTag
!= null) {
255 } else if (!fTag
.equals(other
.fTag
)) {
258 if (fTagDef
== null) {
259 if (other
.fTagDef
!= null) {
262 } else if (!fTagDef
.equals(other
.fTagDef
)) {
269 public boolean isBinaryEquivalent(IDeclaration obj
) {
276 if (getClass() != obj
.getClass()) {
279 VariantDeclaration other
= (VariantDeclaration
) obj
;
280 if (fFields
== null) {
281 if (other
.fFields
!= null) {
285 if (fFields
.size() != other
.fFields
.size()) {
288 for (Entry
<String
, IDeclaration
> field
: fFields
.entrySet()) {
289 if (!other
.fFields
.containsKey(field
.getKey())) {
292 IDeclaration field2
= other
.fFields
.get(field
.getKey());
293 if (!field2
.isBinaryEquivalent(field
.getValue())) {