Commit | Line | Data |
---|---|---|
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 | ||
13 | package org.eclipse.linuxtools.ctf.core.event.types; | |
14 | ||
a4fa4e36 MK |
15 | import java.util.Collection; |
16 | import java.util.Collections; | |
866e5b51 | 17 | import java.util.HashMap; |
0594c61c | 18 | import java.util.Map; |
866e5b51 | 19 | |
a4fa4e36 MK |
20 | import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer; |
21 | import org.eclipse.linuxtools.ctf.core.event.scope.IDefinitionScope; | |
22 | import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException; | |
23 | ||
866e5b51 | 24 | /** |
d37aaa7f | 25 | * A CTFC variant declaration. |
0594c61c | 26 | * |
d37aaa7f FC |
27 | * A variant is similar to a C union, only taking the minimum size of the types, |
28 | * it is a compound data type that contains other datatypes in fields. they are | |
29 | * stored in an hashmap and indexed by names which are strings. | |
30 | * | |
31 | * @version 1.0 | |
32 | * @author Matthew Khouzam | |
33 | * @author Simon Marchi | |
866e5b51 | 34 | */ |
a4fa4e36 | 35 | public class VariantDeclaration extends Declaration { |
866e5b51 FC |
36 | |
37 | // ------------------------------------------------------------------------ | |
38 | // Attributes | |
39 | // ------------------------------------------------------------------------ | |
40 | ||
a4fa4e36 MK |
41 | private String fTag = null; |
42 | private static final long ALIGNMENT = 1; | |
43 | private final Map<String, IDeclaration> fFields = Collections.synchronizedMap(new HashMap<String, IDeclaration>()); | |
44 | private EnumDefinition fTagDef; | |
45 | private IDeclaration fDeclarationToPopulate; | |
46 | private IDefinitionScope fPrevDefinitionScope; | |
866e5b51 FC |
47 | |
48 | // ------------------------------------------------------------------------ | |
49 | // Constructors | |
50 | // ------------------------------------------------------------------------ | |
51 | ||
9ac2eb62 | 52 | /** |
a511da0d | 53 | * Constructor |
9ac2eb62 | 54 | */ |
866e5b51 FC |
55 | public VariantDeclaration() { |
56 | } | |
57 | ||
58 | // ------------------------------------------------------------------------ | |
59 | // Getters/Setters/Predicates | |
60 | // ------------------------------------------------------------------------ | |
61 | ||
9ac2eb62 MK |
62 | /** |
63 | * @return Does the variant have a tag | |
64 | */ | |
866e5b51 | 65 | public boolean isTagged() { |
a4fa4e36 | 66 | return fTag != null; |
866e5b51 FC |
67 | } |
68 | ||
9ac2eb62 MK |
69 | /** |
70 | * Lookup if a field exists in the variant | |
a4fa4e36 MK |
71 | * |
72 | * @param fieldTag | |
73 | * the field tag name | |
9ac2eb62 MK |
74 | * @return true = field tag exists |
75 | */ | |
866e5b51 | 76 | public boolean hasField(String fieldTag) { |
a4fa4e36 | 77 | return fFields.containsKey(fieldTag); |
866e5b51 FC |
78 | } |
79 | ||
9ac2eb62 MK |
80 | /** |
81 | * Sets the tag in a variant | |
a4fa4e36 MK |
82 | * |
83 | * @param tag | |
84 | * the tag | |
9ac2eb62 | 85 | */ |
866e5b51 | 86 | public void setTag(String tag) { |
a4fa4e36 MK |
87 | fTag = tag; |
88 | fTagDef = null; | |
866e5b51 FC |
89 | } |
90 | ||
9ac2eb62 | 91 | /** |
a511da0d | 92 | * Gets current variant tag |
a4fa4e36 | 93 | * |
9ac2eb62 MK |
94 | * @return the variant tag. |
95 | */ | |
866e5b51 | 96 | public String getTag() { |
a4fa4e36 | 97 | return fTag; |
866e5b51 FC |
98 | } |
99 | ||
9ac2eb62 MK |
100 | /** |
101 | * Gets the fields of the variant | |
a4fa4e36 | 102 | * |
9ac2eb62 | 103 | * @return the fields of the variant |
0594c61c | 104 | * @since 2.0 |
9ac2eb62 | 105 | */ |
0594c61c | 106 | public Map<String, IDeclaration> getFields() { |
a4fa4e36 | 107 | return this.fFields; |
866e5b51 FC |
108 | } |
109 | ||
fd74e6c1 MK |
110 | @Override |
111 | public long getAlignment() { | |
a4fa4e36 | 112 | return ALIGNMENT; |
fd74e6c1 | 113 | } |
a4fa4e36 | 114 | |
866e5b51 FC |
115 | // ------------------------------------------------------------------------ |
116 | // Operations | |
117 | // ------------------------------------------------------------------------ | |
118 | ||
a4fa4e36 MK |
119 | /** |
120 | * @since 3.0 | |
121 | */ | |
866e5b51 FC |
122 | @Override |
123 | public VariantDefinition createDefinition(IDefinitionScope definitionScope, | |
a4fa4e36 MK |
124 | String fieldName, BitBuffer input) throws CTFReaderException { |
125 | alignRead(input); | |
126 | if (fPrevDefinitionScope != definitionScope) { | |
127 | fTagDef = null; | |
128 | fPrevDefinitionScope = definitionScope; | |
129 | } | |
130 | EnumDefinition tagDef = fTagDef; | |
131 | if (tagDef == null) { | |
132 | Definition def = definitionScope.lookupDefinition(fTag); | |
133 | tagDef = (EnumDefinition) ((def instanceof EnumDefinition) ? def : null); | |
134 | } | |
135 | if (tagDef == null) { | |
136 | throw new CTFReaderException("Tag is not defined " + fTag); //$NON-NLS-1$ | |
137 | } | |
138 | String varFieldName = tagDef.getStringValue(); | |
139 | fDeclarationToPopulate = fFields.get(varFieldName); | |
140 | if (fDeclarationToPopulate == null) { | |
141 | throw new CTFReaderException("Unknown enum selector for variant " + //$NON-NLS-1$ | |
142 | definitionScope.getScopePath().toString()); | |
143 | } | |
144 | Definition fieldValue = fDeclarationToPopulate.createDefinition(definitionScope, fieldName, input); | |
145 | return new VariantDefinition(this, definitionScope, varFieldName, fieldName, fieldValue); | |
866e5b51 FC |
146 | } |
147 | ||
9ac2eb62 | 148 | /** |
be6df2d8 | 149 | * Add a field to this CTF Variant |
9ac2eb62 MK |
150 | * |
151 | * @param fieldTag | |
be6df2d8 | 152 | * The tag of the new field |
9ac2eb62 | 153 | * @param declaration |
be6df2d8 | 154 | * The Declaration of this new field |
9ac2eb62 | 155 | */ |
866e5b51 | 156 | public void addField(String fieldTag, IDeclaration declaration) { |
a4fa4e36 MK |
157 | fFields.put(fieldTag, declaration); |
158 | } | |
159 | ||
160 | /** | |
161 | * gets the tag definition | |
162 | * | |
163 | * @return the fTagDef | |
164 | * @since 3.0 | |
165 | */ | |
166 | public EnumDefinition getTagDef() { | |
167 | return fTagDef; | |
168 | } | |
169 | ||
170 | /** | |
171 | * @since 3.0 | |
172 | */ | |
173 | @Override | |
174 | public int getMaximumSize() { | |
175 | Collection<IDeclaration> values = fFields.values(); | |
176 | int maxSize = 0; | |
177 | for (IDeclaration field : values) { | |
178 | maxSize = Math.max(maxSize, field.getMaximumSize()); | |
179 | } | |
180 | return maxSize; | |
866e5b51 FC |
181 | } |
182 | ||
183 | @Override | |
184 | public String toString() { | |
185 | /* Only used for debugging */ | |
186 | return "[declaration] variant[" + Integer.toHexString(hashCode()) + ']'; //$NON-NLS-1$ | |
187 | } | |
188 | ||
189 | } |