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 | ||
2db699c2 | 15 | import java.util.Iterator; |
a4fa4e36 | 16 | import java.util.LinkedHashMap; |
0594c61c | 17 | import java.util.Map; |
866e5b51 | 18 | |
a4fa4e36 | 19 | import org.eclipse.jdt.annotation.NonNull; |
2db699c2 | 20 | import org.eclipse.jdt.annotation.Nullable; |
a4fa4e36 MK |
21 | import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer; |
22 | import org.eclipse.linuxtools.ctf.core.event.scope.IDefinitionScope; | |
70f60307 | 23 | import org.eclipse.linuxtools.ctf.core.event.scope.LexicalScope; |
a4fa4e36 MK |
24 | import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException; |
25 | ||
866e5b51 | 26 | /** |
d37aaa7f | 27 | * A CTF structure declaration. |
77fdc5df | 28 | * |
d37aaa7f FC |
29 | * A structure is similar to a C structure, it is a compound data type that |
30 | * contains other datatypes in fields. they are stored in an hashmap and indexed | |
31 | * by names which are strings. | |
32 | * | |
33 | * @version 1.0 | |
34 | * @author Matthew Khouzam | |
35 | * @author Simon Marchi | |
866e5b51 | 36 | */ |
a4fa4e36 | 37 | public class StructDeclaration extends Declaration { |
866e5b51 FC |
38 | |
39 | // ------------------------------------------------------------------------ | |
40 | // Attributes | |
41 | // ------------------------------------------------------------------------ | |
42 | ||
a4fa4e36 | 43 | /** linked list of field names. So fieldName->fieldValue */ |
2db699c2 | 44 | private final @NonNull Map<String, IDeclaration> fFieldMap = new LinkedHashMap<>(); |
a4fa4e36 MK |
45 | |
46 | /** maximum bit alignment */ | |
47 | private long fMaxAlign; | |
866e5b51 FC |
48 | |
49 | // ------------------------------------------------------------------------ | |
50 | // Constructors | |
51 | // ------------------------------------------------------------------------ | |
52 | ||
9ac2eb62 MK |
53 | /** |
54 | * The struct declaration, add fields later | |
55 | * | |
56 | * @param align | |
57 | * the minimum alignment of the struct. (if a struct is 8bit | |
58 | * aligned and has a 32 bit aligned field, the struct becomes 32 | |
59 | * bit aligned. | |
60 | */ | |
2b7f6f09 | 61 | public StructDeclaration(long align) { |
a4fa4e36 | 62 | fMaxAlign = Math.max(align, 1); |
a4fa4e36 MK |
63 | } |
64 | ||
65 | /** | |
66 | * Struct declaration constructor | |
67 | * | |
68 | * @param names | |
69 | * the names of all the fields | |
70 | * @param declarations | |
71 | * all the fields | |
72 | * @since 3.0 | |
73 | */ | |
a4fa4e36 MK |
74 | public StructDeclaration(String[] names, Declaration[] declarations) { |
75 | fMaxAlign = 1; | |
2db699c2 | 76 | |
a4fa4e36 MK |
77 | for (int i = 0; i < names.length; i++) { |
78 | addField(names[i], declarations[i]); | |
79 | } | |
866e5b51 FC |
80 | } |
81 | ||
82 | // ------------------------------------------------------------------------ | |
83 | // Getters/Setters/Predicates | |
84 | // ------------------------------------------------------------------------ | |
85 | ||
9ac2eb62 MK |
86 | /** |
87 | * Get current alignment | |
a4fa4e36 | 88 | * |
9ac2eb62 MK |
89 | * @return the alignment of the struct and all its fields |
90 | */ | |
2b7f6f09 | 91 | public long getMaxAlign() { |
a4fa4e36 | 92 | return fMaxAlign; |
866e5b51 FC |
93 | } |
94 | ||
9ac2eb62 MK |
95 | /** |
96 | * Query if the struct has a given field | |
a4fa4e36 MK |
97 | * |
98 | * @param name | |
99 | * the name of the field, scopeless please | |
9ac2eb62 MK |
100 | * @return does the field exist? |
101 | */ | |
866e5b51 | 102 | public boolean hasField(String name) { |
a4fa4e36 | 103 | return fFieldMap.containsKey(name); |
866e5b51 FC |
104 | } |
105 | ||
9ac2eb62 | 106 | /** |
2db699c2 | 107 | * Get the fields of the struct as a map. |
a4fa4e36 | 108 | * |
2db699c2 | 109 | * @return a Map of the fields (key is the name) |
0594c61c | 110 | * @since 2.0 |
9ac2eb62 | 111 | */ |
0594c61c | 112 | public Map<String, IDeclaration> getFields() { |
a4fa4e36 | 113 | return fFieldMap; |
866e5b51 FC |
114 | } |
115 | ||
2db699c2 AM |
116 | /** |
117 | * Get the field declaration corresponding to a field name. | |
118 | * | |
119 | * @param fieldName | |
120 | * The field name | |
121 | * @return The declaration of the field, or null if there is no such field. | |
122 | * @since 3.1 | |
123 | */ | |
124 | @Nullable | |
125 | public IDeclaration getField(String fieldName) { | |
126 | return fFieldMap.get(fieldName); | |
127 | } | |
128 | ||
9ac2eb62 | 129 | /** |
a4fa4e36 MK |
130 | * Gets the field list. Very important since the map of fields does not |
131 | * retain the order of the fields. | |
132 | * | |
9ac2eb62 | 133 | * @return the field list. |
a4fa4e36 | 134 | * @since 3.0 |
9ac2eb62 | 135 | */ |
a4fa4e36 MK |
136 | public Iterable<String> getFieldsList() { |
137 | return fFieldMap.keySet(); | |
866e5b51 FC |
138 | } |
139 | ||
fd74e6c1 MK |
140 | @Override |
141 | public long getAlignment() { | |
a4fa4e36 MK |
142 | return this.fMaxAlign; |
143 | } | |
144 | ||
145 | /** | |
146 | * @since 3.0 | |
147 | */ | |
148 | @Override | |
149 | public int getMaximumSize() { | |
150 | int maxSize = 0; | |
2db699c2 AM |
151 | for (IDeclaration field : fFieldMap.values()) { |
152 | maxSize += field.getMaximumSize(); | |
a4fa4e36 MK |
153 | } |
154 | return Math.min(maxSize, Integer.MAX_VALUE); | |
fd74e6c1 | 155 | } |
9ac2eb62 | 156 | |
866e5b51 FC |
157 | // ------------------------------------------------------------------------ |
158 | // Operations | |
159 | // ------------------------------------------------------------------------ | |
160 | ||
a4fa4e36 MK |
161 | /** |
162 | * @since 3.0 | |
163 | */ | |
866e5b51 FC |
164 | @Override |
165 | public StructDefinition createDefinition(IDefinitionScope definitionScope, | |
a4fa4e36 MK |
166 | String fieldName, BitBuffer input) throws CTFReaderException { |
167 | alignRead(input); | |
2db699c2 AM |
168 | final Definition[] myFields = new Definition[fFieldMap.size()]; |
169 | StructDefinition structDefinition = new StructDefinition(this, definitionScope, fieldName, fFieldMap.keySet(), myFields); | |
170 | ||
171 | Iterator<Map.Entry<String, IDeclaration>> iter = fFieldMap.entrySet().iterator(); | |
172 | for (int i = 0; i < fFieldMap.size(); i++) { | |
173 | Map.Entry<String, IDeclaration> entry = iter.next(); | |
174 | String name = entry.getKey(); | |
175 | if (name == null) { | |
176 | throw new IllegalStateException(); | |
177 | } | |
178 | myFields[i] = entry.getValue().createDefinition(structDefinition, name, input); | |
a4fa4e36 MK |
179 | } |
180 | return structDefinition; | |
866e5b51 FC |
181 | } |
182 | ||
70f60307 MK |
183 | /** |
184 | * Accelerated create definition | |
185 | * | |
186 | * @param definitionScope | |
187 | * the definition scope | |
188 | * @param fieldScope | |
189 | * the lexical scope of this element | |
190 | * @param input | |
191 | * the {@Link BitBuffer} to read | |
192 | * @return the Struct definition | |
193 | * @throws CTFReaderException | |
194 | * read error and such | |
195 | * @since 3.1 | |
196 | */ | |
197 | public StructDefinition createDefinition(IDefinitionScope definitionScope, | |
198 | LexicalScope fieldScope, @NonNull BitBuffer input) throws CTFReaderException { | |
199 | alignRead(input); | |
200 | final Definition[] myFields = new Definition[fFieldMap.size()]; | |
bbe3a6a4 MK |
201 | /* |
202 | * Key set is NOT null | |
203 | */ | |
204 | @SuppressWarnings("null") | |
205 | StructDefinition structDefinition = new StructDefinition(this, definitionScope, fieldScope, fieldScope.getName(), fFieldMap.keySet(), myFields); | |
70f60307 MK |
206 | Iterator<Map.Entry<String, IDeclaration>> iter = fFieldMap.entrySet().iterator(); |
207 | for (int i = 0; i < fFieldMap.size(); i++) { | |
208 | Map.Entry<String, IDeclaration> entry = iter.next(); | |
209 | String fieldName = entry.getKey(); | |
210 | if (fieldName == null) { | |
211 | throw new IllegalStateException(); | |
212 | } | |
213 | myFields[i] = entry.getValue().createDefinition(structDefinition, fieldName, input); | |
214 | } | |
215 | return structDefinition; | |
216 | } | |
217 | ||
9ac2eb62 MK |
218 | /** |
219 | * Add a field to the struct | |
a4fa4e36 MK |
220 | * |
221 | * @param name | |
222 | * the name of the field, scopeless | |
223 | * @param declaration | |
224 | * the declaration of the field | |
9ac2eb62 | 225 | */ |
866e5b51 | 226 | public void addField(String name, IDeclaration declaration) { |
a4fa4e36 MK |
227 | fFieldMap.put(name, declaration); |
228 | fMaxAlign = Math.max(fMaxAlign, declaration.getAlignment()); | |
866e5b51 FC |
229 | } |
230 | ||
231 | @Override | |
232 | public String toString() { | |
233 | /* Only used for debugging */ | |
234 | return "[declaration] struct[" + Integer.toHexString(hashCode()) + ']'; //$NON-NLS-1$ | |
235 | } | |
236 | ||
4dd0eaed MK |
237 | @Override |
238 | public int hashCode() { | |
239 | final int prime = 31; | |
240 | int result = 1; | |
a4fa4e36 MK |
241 | result = (prime * result) + fFieldMap.entrySet().hashCode(); |
242 | result = (prime * result) + (int) (fMaxAlign ^ (fMaxAlign >>> 32)); | |
4dd0eaed MK |
243 | return result; |
244 | } | |
245 | ||
4dd0eaed MK |
246 | @Override |
247 | public boolean equals(Object obj) { | |
248 | if (this == obj) { | |
249 | return true; | |
250 | } | |
251 | if (obj == null) { | |
252 | return false; | |
253 | } | |
254 | if (!(obj instanceof StructDeclaration)) { | |
255 | return false; | |
256 | } | |
257 | StructDeclaration other = (StructDeclaration) obj; | |
a4fa4e36 | 258 | if (!fFieldMap.entrySet().equals(other.fFieldMap.entrySet())) { |
4dd0eaed MK |
259 | return false; |
260 | } | |
a4fa4e36 | 261 | if (fMaxAlign != other.fMaxAlign) { |
4dd0eaed MK |
262 | return false; |
263 | } | |
264 | return true; | |
265 | } | |
266 | ||
866e5b51 | 267 | } |