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 static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
17 import java
.util
.ArrayList
;
18 import java
.util
.Iterator
;
19 import java
.util
.LinkedHashMap
;
20 import java
.util
.List
;
22 import java
.util
.Map
.Entry
;
24 import org
.eclipse
.jdt
.annotation
.NonNull
;
25 import org
.eclipse
.jdt
.annotation
.Nullable
;
26 import org
.eclipse
.tracecompass
.ctf
.core
.CTFReaderException
;
27 import org
.eclipse
.tracecompass
.ctf
.core
.event
.io
.BitBuffer
;
28 import org
.eclipse
.tracecompass
.ctf
.core
.event
.scope
.IDefinitionScope
;
29 import org
.eclipse
.tracecompass
.ctf
.core
.event
.scope
.LexicalScope
;
32 * A CTF structure declaration.
34 * A structure is similar to a C structure, it is a compound data type that
35 * contains other datatypes in fields. they are stored in an hashmap and indexed
36 * by names which are strings.
39 * @author Matthew Khouzam
40 * @author Simon Marchi
42 public class StructDeclaration
extends Declaration
{
44 // ------------------------------------------------------------------------
46 // ------------------------------------------------------------------------
48 /** linked list of field names. So fieldName->fieldValue */
49 private final @NonNull Map
<String
, IDeclaration
> fFieldMap
= new LinkedHashMap
<>();
51 /** maximum bit alignment */
52 private long fMaxAlign
;
54 // ------------------------------------------------------------------------
56 // ------------------------------------------------------------------------
59 * The struct declaration, add fields later
62 * the minimum alignment of the struct. (if a struct is 8bit
63 * aligned and has a 32 bit aligned field, the struct becomes 32
66 public StructDeclaration(long align
) {
67 fMaxAlign
= Math
.max(align
, 1);
71 * Struct declaration constructor
74 * the names of all the fields
78 public StructDeclaration(String
[] names
, Declaration
[] declarations
) {
81 for (int i
= 0; i
< names
.length
; i
++) {
82 addField(names
[i
], declarations
[i
]);
86 // ------------------------------------------------------------------------
87 // Getters/Setters/Predicates
88 // ------------------------------------------------------------------------
91 * Get current alignment
93 * @return the alignment of the struct and all its fields
95 public long getMaxAlign() {
100 * Query if the struct has a given field
103 * the name of the field, scopeless please
104 * @return does the field exist?
106 public boolean hasField(String name
) {
107 return fFieldMap
.containsKey(name
);
111 * Get the fields of the struct as a map.
113 * @return a Map of the fields (key is the name)
115 public Map
<String
, IDeclaration
> getFields() {
120 * Get the field declaration corresponding to a field name.
124 * @return The declaration of the field, or null if there is no such field.
127 public IDeclaration
getField(String fieldName
) {
128 return fFieldMap
.get(fieldName
);
132 * Gets the field list. Very important since the map of fields does not
133 * retain the order of the fields.
135 * @return the field list.
137 public Iterable
<String
> getFieldsList() {
138 return fFieldMap
.keySet();
142 public long getAlignment() {
143 return this.fMaxAlign
;
147 public int getMaximumSize() {
149 for (IDeclaration field
: fFieldMap
.values()) {
150 maxSize
+= field
.getMaximumSize();
152 return Math
.min(maxSize
, Integer
.MAX_VALUE
);
155 // ------------------------------------------------------------------------
157 // ------------------------------------------------------------------------
160 public StructDefinition
createDefinition(IDefinitionScope definitionScope
,
161 String fieldName
, BitBuffer input
) throws CTFReaderException
{
163 final Definition
[] myFields
= new Definition
[fFieldMap
.size()];
164 StructDefinition structDefinition
= new StructDefinition(this, definitionScope
, fieldName
, fFieldMap
.keySet(), myFields
);
165 fillStruct(input
, myFields
, structDefinition
);
166 return structDefinition
;
170 * Create a definition from this declaration. This is a faster constructor
171 * as it has a lexical scope and this does not need to look it up.
173 * @param definitionScope
174 * the definition scope, the parent where the definition will be
177 * the scope of the definition
179 * a bitbuffer to read from
180 * @return a reference to the definition
181 * @throws CTFReaderException
184 public StructDefinition
createDefinition(IDefinitionScope definitionScope
,
185 LexicalScope fieldScope
, @NonNull BitBuffer input
) throws CTFReaderException
{
187 final Definition
[] myFields
= new Definition
[fFieldMap
.size()];
189 StructDefinition structDefinition
= new StructDefinition(this,definitionScope
,
190 fieldScope
, fieldScope
.getName(), checkNotNull(fFieldMap
.keySet()), myFields
);
191 fillStruct(input
, myFields
, structDefinition
);
192 return structDefinition
;
196 * Add a field to the struct
199 * the name of the field, scopeless
201 * the declaration of the field
203 public void addField(String name
, IDeclaration declaration
) {
204 fFieldMap
.put(name
, declaration
);
205 fMaxAlign
= Math
.max(fMaxAlign
, declaration
.getAlignment());
208 private void fillStruct(@NonNull BitBuffer input
, final Definition
[] myFields
, StructDefinition structDefinition
) throws CTFReaderException
{
209 Iterator
<Map
.Entry
<String
, IDeclaration
>> iter
= fFieldMap
.entrySet().iterator();
210 for (int i
= 0; i
< fFieldMap
.size(); i
++) {
211 Map
.Entry
<String
, IDeclaration
> entry
= iter
.next();
212 /* We should not have inserted null keys... */
213 String key
= checkNotNull(entry
.getKey());
214 myFields
[i
] = entry
.getValue().createDefinition(structDefinition
, key
, input
);
219 public String
toString() {
220 /* Only used for debugging */
221 StringBuilder sb
= new StringBuilder();
222 sb
.append("[declaration] struct["); //$NON-NLS-1$
223 for (Entry
<String
, IDeclaration
> field
: fFieldMap
.entrySet()) {
224 sb
.append(field
.getKey()).append(':').append(field
.getValue());
227 return sb
.toString();
231 public int hashCode() {
232 final int prime
= 31;
234 for (Entry
<String
, IDeclaration
> field
: fFieldMap
.entrySet()) {
235 result
= prime
* result
+ field
.getKey().hashCode();
236 result
= prime
* result
+ field
.getValue().hashCode();
238 result
= (prime
* result
) + (int) (fMaxAlign ^
(fMaxAlign
>>> 32));
243 public boolean equals(Object obj
) {
250 if (!(obj
instanceof StructDeclaration
)) {
253 StructDeclaration other
= (StructDeclaration
) obj
;
254 if (fFieldMap
.size() != other
.fFieldMap
.size()) {
258 List
<String
> localFieldNames
= new ArrayList
<>();
259 localFieldNames
.addAll(fFieldMap
.keySet());
261 List
<IDeclaration
> localDecs
= new ArrayList
<>();
262 localDecs
.addAll(fFieldMap
.values());
264 List
<String
> otherFieldNames
= new ArrayList
<>();
265 otherFieldNames
.addAll(other
.fFieldMap
.keySet());
267 List
<IDeclaration
> otherDecs
= new ArrayList
<>();
268 otherDecs
.addAll(other
.fFieldMap
.values());
270 //check fields in order
271 for (int i
= 0; i
< fFieldMap
.size(); i
++) {
272 if ((!localFieldNames
.get(i
).equals(otherFieldNames
.get(i
))) ||
273 (!otherDecs
.get(i
).equals(localDecs
.get(i
)))) {
278 if (fMaxAlign
!= other
.fMaxAlign
) {
285 public boolean isBinaryEquivalent(IDeclaration obj
) {
292 if (!(obj
instanceof StructDeclaration
)) {
295 StructDeclaration other
= (StructDeclaration
) obj
;
296 if (fFieldMap
.size() != other
.fFieldMap
.size()) {
299 List
<IDeclaration
> localDecs
= new ArrayList
<>();
300 localDecs
.addAll(fFieldMap
.values());
301 List
<IDeclaration
> otherDecs
= new ArrayList
<>();
302 otherDecs
.addAll(other
.fFieldMap
.values());
303 for (int i
= 0; i
< fFieldMap
.size(); i
++) {
304 if (!otherDecs
.get(i
).isBinaryEquivalent(localDecs
.get(i
))) {
309 if (fMaxAlign
!= other
.fMaxAlign
) {