Commit | Line | Data |
---|---|---|
a3fc8213 | 1 | /******************************************************************************* |
60ae41e1 | 2 | * Copyright (c) 2011, 2014 Ericsson, École Polytechnique de Montréal |
a3fc8213 AM |
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 | * | |
d4a8d935 BH |
9 | * Contributors: |
10 | * Matthew Khouzam - Initial API and implementation | |
404b264a | 11 | * Alexandre Montplaisir - Initial API and implementation, extend TmfEventField |
d4a8d935 | 12 | * Bernd Hufmann - Add Enum field handling |
404b264a | 13 | * Geneviève Bastien - Add Struct and Variant field handling |
459f705b | 14 | * Jean-Christian Kouame - Correct handling of unsigned integer fields |
4591bed9 | 15 | * François Doray - Add generic array field type |
a3fc8213 AM |
16 | *******************************************************************************/ |
17 | ||
9722e5d7 | 18 | package org.eclipse.tracecompass.tmf.ctf.core.event; |
a3fc8213 | 19 | |
a6223d74 | 20 | import java.util.ArrayList; |
7a6cee1a | 21 | import java.util.Arrays; |
7b4f13e6 | 22 | import java.util.Collection; |
a6223d74 MK |
23 | import java.util.List; |
24 | ||
15f6223a | 25 | import org.eclipse.tracecompass.ctf.core.event.types.AbstractArrayDefinition; |
f357bcd4 AM |
26 | import org.eclipse.tracecompass.ctf.core.event.types.CompoundDeclaration; |
27 | import org.eclipse.tracecompass.ctf.core.event.types.Definition; | |
28 | import org.eclipse.tracecompass.ctf.core.event.types.EnumDefinition; | |
29 | import org.eclipse.tracecompass.ctf.core.event.types.FloatDefinition; | |
30 | import org.eclipse.tracecompass.ctf.core.event.types.ICompositeDefinition; | |
31 | import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration; | |
32 | import org.eclipse.tracecompass.ctf.core.event.types.IDefinition; | |
33 | import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration; | |
34 | import org.eclipse.tracecompass.ctf.core.event.types.IntegerDefinition; | |
35 | import org.eclipse.tracecompass.ctf.core.event.types.StringDefinition; | |
36 | import org.eclipse.tracecompass.ctf.core.event.types.VariantDefinition; | |
2bdf0193 AM |
37 | import org.eclipse.tracecompass.tmf.core.event.ITmfEventField; |
38 | import org.eclipse.tracecompass.tmf.core.event.TmfEventField; | |
9722e5d7 | 39 | import org.eclipse.tracecompass.tmf.ctf.core.CtfEnumPair; |
a3fc8213 AM |
40 | |
41 | /** | |
7558a1e1 AM |
42 | * The CTF implementation of the TMF event field model |
43 | * | |
d4a8d935 | 44 | * @version 2.0 |
7558a1e1 | 45 | * @author Matthew Khouzam |
d09f973b | 46 | * @author Alexandre Montplaisir |
a3fc8213 | 47 | */ |
68b18f2f | 48 | public abstract class CtfTmfEventField extends TmfEventField { |
a3fc8213 | 49 | |
a3fc8213 | 50 | // ------------------------------------------------------------------------ |
7558a1e1 | 51 | // Constructor |
a3fc8213 AM |
52 | // ------------------------------------------------------------------------ |
53 | ||
b1baa808 | 54 | /** |
7558a1e1 AM |
55 | * Standard constructor. Only to be used internally, call parseField() to |
56 | * generate a new field object. | |
57 | * | |
58 | * @param name | |
59 | * The name of this field | |
68b18f2f AM |
60 | * @param value |
61 | * The value of this field. Its type should match the field type. | |
81ed27a8 MK |
62 | * @param fields |
63 | * The children fields. Useful for composite fields | |
b1baa808 | 64 | */ |
81ed27a8 | 65 | protected CtfTmfEventField(String name, Object value, ITmfEventField[] fields) { |
68b18f2f AM |
66 | super(/* Strip the underscore from the field name if there is one */ |
67 | name.startsWith("_") ? name.substring(1) : name, //$NON-NLS-1$ | |
68 | value, | |
81ed27a8 | 69 | fields); |
a3fc8213 AM |
70 | } |
71 | ||
72 | // ------------------------------------------------------------------------ | |
73 | // Operations | |
74 | // ------------------------------------------------------------------------ | |
75 | ||
b1baa808 | 76 | /** |
7558a1e1 AM |
77 | * Factory method to instantiate CtfTmfEventField objects. |
78 | * | |
79 | * @param fieldDef | |
80 | * The CTF Definition of this event field | |
81 | * @param fieldName | |
82 | * String The name to assign to this field | |
83 | * @return The resulting CtfTmfEventField object | |
cc98c947 | 84 | * @deprecated use {@link CtfTmfEventField#parseField(IDefinition, String)} |
b1baa808 | 85 | */ |
cc98c947 | 86 | @Deprecated |
a3fc8213 AM |
87 | public static CtfTmfEventField parseField(Definition fieldDef, |
88 | String fieldName) { | |
cc98c947 MK |
89 | return parseField((IDefinition) fieldDef, fieldName); |
90 | } | |
91 | ||
92 | /** | |
93 | * Factory method to instantiate CtfTmfEventField objects. | |
94 | * | |
95 | * @param fieldDef | |
96 | * The CTF Definition of this event field | |
97 | * @param fieldName | |
98 | * String The name to assign to this field | |
99 | * @return The resulting CtfTmfEventField object | |
cc98c947 MK |
100 | */ |
101 | public static CtfTmfEventField parseField(IDefinition fieldDef, | |
102 | String fieldName) { | |
a3fc8213 AM |
103 | CtfTmfEventField field = null; |
104 | ||
105 | /* Determine the Definition type */ | |
106 | if (fieldDef instanceof IntegerDefinition) { | |
367bcd2b AM |
107 | IntegerDefinition intDef = (IntegerDefinition) fieldDef; |
108 | int base = intDef.getDeclaration().getBase(); | |
459f705b | 109 | field = new CTFIntegerField(fieldName, intDef.getValue(), base, intDef.getDeclaration().isSigned()); |
a3fc8213 | 110 | |
21fb02fa MK |
111 | } else if (fieldDef instanceof EnumDefinition) { |
112 | EnumDefinition enumDef = (EnumDefinition) fieldDef; | |
68b18f2f | 113 | field = new CTFEnumField(fieldName, new CtfEnumPair(enumDef.getValue(), enumDef.getIntegerValue())); |
21fb02fa | 114 | |
a3fc8213 | 115 | } else if (fieldDef instanceof StringDefinition) { |
68b18f2f AM |
116 | field = new CTFStringField(fieldName, ((StringDefinition) fieldDef).getValue()); |
117 | ||
118 | } else if (fieldDef instanceof FloatDefinition) { | |
119 | FloatDefinition floatDef = (FloatDefinition) fieldDef; | |
120 | field = new CTFFloatField(fieldName, floatDef.getValue()); | |
a3fc8213 | 121 | |
15f6223a MK |
122 | } else if (fieldDef instanceof AbstractArrayDefinition) { |
123 | AbstractArrayDefinition arrayDef = (AbstractArrayDefinition) fieldDef; | |
7b4f13e6 MK |
124 | IDeclaration decl = arrayDef.getDeclaration(); |
125 | if (!(decl instanceof CompoundDeclaration)) { | |
126 | throw new IllegalArgumentException("Array definitions should only come from sequence or array declarations"); //$NON-NLS-1$ | |
127 | } | |
128 | CompoundDeclaration arrDecl = (CompoundDeclaration) decl; | |
129 | IDeclaration elemType = null; | |
130 | Collection<Definition> definitions = arrayDef.getDefinitions(); | |
131 | elemType = arrDecl.getElementType(); | |
132 | if (elemType instanceof IntegerDeclaration) { | |
15f6223a MK |
133 | /* |
134 | * Array of integers => CTFIntegerArrayField, unless it's a | |
135 | * CTFStringField | |
136 | */ | |
7b4f13e6 | 137 | IntegerDeclaration elemIntType = (IntegerDeclaration) elemType; |
373af311 MK |
138 | /* Are the integers characters and encoded? */ |
139 | if (elemIntType.isCharacter()) { | |
140 | /* it's a CTFStringField */ | |
141 | field = new CTFStringField(fieldName, arrayDef.toString()); | |
142 | } else { | |
143 | /* it's a CTFIntegerArrayField */ | |
15f6223a MK |
144 | int size = arrayDef.getDefinitions().size(); |
145 | long[] values = new long[size]; | |
146 | for (int i = 0; i < size; i++) { | |
373af311 MK |
147 | IDefinition elem = arrayDef.getDefinitions().get(i); |
148 | if (elem == null) { | |
149 | break; | |
150 | } | |
151 | values[i] = ((IntegerDefinition) elem).getValue(); | |
7b4f13e6 | 152 | } |
373af311 MK |
153 | field = new CTFIntegerArrayField(fieldName, values, |
154 | elemIntType.getBase(), | |
155 | elemIntType.isSigned()); | |
7b4f13e6 | 156 | } |
4591bed9 FD |
157 | } else { |
158 | /* Arrays of elements of any other type */ | |
7b4f13e6 | 159 | CtfTmfEventField[] elements = new CtfTmfEventField[arrayDef.getLength()]; |
4591bed9 | 160 | /* Parse the elements of the array. */ |
7b4f13e6 | 161 | int i = 0; |
cc98c947 | 162 | for (IDefinition definition : definitions) { |
4591bed9 | 163 | CtfTmfEventField curField = CtfTmfEventField.parseField( |
7b4f13e6 | 164 | definition, fieldName + '[' + i + ']'); |
4591bed9 | 165 | elements[i] = curField; |
7b4f13e6 | 166 | i++; |
a3fc8213 | 167 | } |
a3fc8213 | 168 | |
4591bed9 FD |
169 | field = new CTFArrayField(fieldName, elements); |
170 | } | |
009883d7 MK |
171 | } else if (fieldDef instanceof ICompositeDefinition) { |
172 | ICompositeDefinition strDef = (ICompositeDefinition) fieldDef; | |
7a6cee1a | 173 | |
a4524c1b | 174 | List<ITmfEventField> list = new ArrayList<>(); |
7a6cee1a | 175 | /* Recursively parse the fields */ |
a4fa4e36 MK |
176 | for (String curFieldName : strDef.getFieldNames()) { |
177 | list.add(CtfTmfEventField.parseField(strDef.getDefinition(curFieldName), curFieldName)); | |
7a6cee1a GB |
178 | } |
179 | field = new CTFStructField(fieldName, list.toArray(new CtfTmfEventField[list.size()])); | |
a0e9eac8 | 180 | |
404b264a GB |
181 | } else if (fieldDef instanceof VariantDefinition) { |
182 | VariantDefinition varDef = (VariantDefinition) fieldDef; | |
183 | ||
184 | String curFieldName = varDef.getCurrentFieldName(); | |
cc98c947 | 185 | IDefinition curFieldDef = varDef.getCurrentField(); |
404b264a | 186 | if (curFieldDef != null) { |
51cc7ef4 GB |
187 | CtfTmfEventField subField = CtfTmfEventField.parseField(curFieldDef, curFieldName); |
188 | field = new CTFVariantField(fieldName, subField); | |
404b264a GB |
189 | } else { |
190 | /* A safe-guard, but curFieldDef should never be null */ | |
191 | field = new CTFStringField(curFieldName, ""); //$NON-NLS-1$ | |
192 | } | |
193 | ||
194 | } else { | |
459f705b JCK |
195 | /* |
196 | * Safe-guard, to avoid null exceptions later, field is expected not | |
197 | * to be null | |
198 | */ | |
91e7f946 | 199 | field = new CTFStringField(fieldName, Messages.CtfTmfEventField_UnsupportedType + fieldDef.getClass().toString()); |
a3fc8213 | 200 | } |
a3fc8213 AM |
201 | return field; |
202 | } | |
203 | ||
a3fc8213 | 204 | @Override |
68b18f2f | 205 | public String toString() { |
51cc7ef4 | 206 | return getName() + '=' + getFormattedValue(); |
a3fc8213 AM |
207 | } |
208 | ||
a3fc8213 AM |
209 | } |
210 | ||
211 | /** | |
7558a1e1 AM |
212 | * The CTF field implementation for integer fields. |
213 | * | |
214 | * @author alexmont | |
a3fc8213 AM |
215 | */ |
216 | final class CTFIntegerField extends CtfTmfEventField { | |
217 | ||
6fc4ce56 MK |
218 | private final int fBase; |
219 | private final boolean fSigned; | |
a3fc8213 AM |
220 | |
221 | /** | |
222 | * A CTF "IntegerDefinition" can be an integer of any byte size, so in the | |
223 | * Java parser this is interpreted as a long. | |
7558a1e1 | 224 | * |
7558a1e1 AM |
225 | * @param name |
226 | * The name of this field | |
459f705b JCK |
227 | * @param longValue |
228 | * The integer value of this field | |
229 | * @param signed | |
230 | * Is the value signed or not | |
a3fc8213 | 231 | */ |
459f705b | 232 | CTFIntegerField(String name, long longValue, int base, boolean signed) { |
81ed27a8 | 233 | super(name, longValue, null); |
6fc4ce56 MK |
234 | fSigned = signed; |
235 | fBase = base; | |
367bcd2b AM |
236 | } |
237 | ||
a3fc8213 AM |
238 | @Override |
239 | public Long getValue() { | |
68b18f2f | 240 | return (Long) super.getValue(); |
a3fc8213 AM |
241 | } |
242 | ||
8f86c552 GB |
243 | @Override |
244 | public String getFormattedValue() { | |
6fc4ce56 | 245 | return IntegerDefinition.formatNumber(getValue(), fBase, fSigned); |
8f86c552 GB |
246 | } |
247 | ||
a3fc8213 AM |
248 | } |
249 | ||
250 | /** | |
7558a1e1 AM |
251 | * The CTF field implementation for string fields |
252 | * | |
253 | * @author alexmont | |
a3fc8213 AM |
254 | */ |
255 | final class CTFStringField extends CtfTmfEventField { | |
256 | ||
b1baa808 MK |
257 | /** |
258 | * Constructor for CTFStringField. | |
7558a1e1 AM |
259 | * |
260 | * @param strValue | |
261 | * The string value of this field | |
262 | * @param name | |
263 | * The name of this field | |
b1baa808 | 264 | */ |
68b18f2f | 265 | CTFStringField(String name, String strValue) { |
81ed27a8 | 266 | super(name, strValue, null); |
a3fc8213 AM |
267 | } |
268 | ||
a3fc8213 AM |
269 | @Override |
270 | public String getValue() { | |
68b18f2f | 271 | return (String) super.getValue(); |
a3fc8213 AM |
272 | } |
273 | } | |
274 | ||
275 | /** | |
7558a1e1 AM |
276 | * CTF field implementation for arrays of integers. |
277 | * | |
278 | * @author alexmont | |
a3fc8213 AM |
279 | */ |
280 | final class CTFIntegerArrayField extends CtfTmfEventField { | |
281 | ||
6fc4ce56 MK |
282 | private final int fBase; |
283 | private final boolean fSigned; | |
284 | private String fFormattedValue = null; | |
404b264a | 285 | |
b1baa808 MK |
286 | /** |
287 | * Constructor for CTFIntegerArrayField. | |
7558a1e1 | 288 | * |
459f705b JCK |
289 | * @param name |
290 | * The name of this field | |
7558a1e1 AM |
291 | * @param longValues |
292 | * The array of integers (as longs) that compose this field's | |
293 | * value | |
459f705b JCK |
294 | * @param signed |
295 | * Are the values in the array signed or not | |
b1baa808 | 296 | */ |
cefe3edf | 297 | CTFIntegerArrayField(String name, long[] longValues, int base, boolean signed) { |
81ed27a8 | 298 | super(name, longValues, null); |
6fc4ce56 MK |
299 | fBase = base; |
300 | fSigned = signed; | |
a3fc8213 AM |
301 | } |
302 | ||
a6223d74 | 303 | @Override |
cefe3edf AM |
304 | public long[] getValue() { |
305 | return (long[]) super.getValue(); | |
a3fc8213 | 306 | } |
404b264a | 307 | |
8f86c552 | 308 | @Override |
4591bed9 | 309 | public synchronized String getFormattedValue() { |
6fc4ce56 | 310 | if (fFormattedValue == null) { |
a4524c1b | 311 | List<String> strings = new ArrayList<>(); |
cefe3edf | 312 | for (long value : getValue()) { |
6fc4ce56 | 313 | strings.add(IntegerDefinition.formatNumber(value, fBase, fSigned)); |
8f86c552 | 314 | } |
6fc4ce56 | 315 | fFormattedValue = strings.toString(); |
8f86c552 | 316 | } |
6fc4ce56 | 317 | return fFormattedValue; |
8f86c552 GB |
318 | } |
319 | ||
a3fc8213 AM |
320 | } |
321 | ||
4591bed9 FD |
322 | /** |
323 | * CTF field implementation for arrays of arbitrary types. | |
324 | * | |
325 | * @author fdoray | |
326 | */ | |
327 | final class CTFArrayField extends CtfTmfEventField { | |
328 | ||
6fc4ce56 | 329 | private String fFormattedValue = null; |
4591bed9 FD |
330 | |
331 | /** | |
332 | * Constructor for CTFArrayField. | |
333 | * | |
334 | * @param name | |
335 | * The name of this field | |
336 | * @param elements | |
337 | * The array elements of this field | |
338 | */ | |
339 | CTFArrayField(String name, CtfTmfEventField[] elements) { | |
340 | super(name, elements, elements); | |
341 | } | |
342 | ||
343 | @Override | |
344 | public CtfTmfEventField[] getValue() { | |
345 | return (CtfTmfEventField[]) super.getValue(); | |
346 | } | |
347 | ||
348 | @Override | |
349 | public synchronized String getFormattedValue() { | |
6fc4ce56 | 350 | if (fFormattedValue == null) { |
a4524c1b | 351 | List<String> strings = new ArrayList<>(); |
4591bed9 FD |
352 | for (CtfTmfEventField element : getValue()) { |
353 | strings.add(element.getFormattedValue()); | |
354 | } | |
6fc4ce56 | 355 | fFormattedValue = strings.toString(); |
4591bed9 | 356 | } |
6fc4ce56 | 357 | return fFormattedValue; |
4591bed9 FD |
358 | } |
359 | } | |
360 | ||
b1baa808 | 361 | /** |
7558a1e1 AM |
362 | * CTF field implementation for floats. |
363 | * | |
364 | * @author emathko | |
b1baa808 | 365 | */ |
a04464b1 MK |
366 | final class CTFFloatField extends CtfTmfEventField { |
367 | ||
b1baa808 MK |
368 | /** |
369 | * Constructor for CTFFloatField. | |
7558a1e1 AM |
370 | * |
371 | * @param value | |
372 | * The float value (actually a double) of this field | |
373 | * @param name | |
374 | * The name of this field | |
b1baa808 | 375 | */ |
68b18f2f | 376 | protected CTFFloatField(String name, double value) { |
81ed27a8 | 377 | super(name, value, null); |
a04464b1 MK |
378 | } |
379 | ||
a04464b1 | 380 | @Override |
81c8e6f7 | 381 | public Double getValue() { |
68b18f2f | 382 | return (Double) super.getValue(); |
a04464b1 | 383 | } |
a04464b1 | 384 | } |
7558a1e1 | 385 | |
d4a8d935 BH |
386 | /** |
387 | * The CTF field implementation for Enum fields | |
388 | * | |
389 | * @author Bernd Hufmann | |
390 | */ | |
391 | final class CTFEnumField extends CtfTmfEventField { | |
392 | ||
d4a8d935 BH |
393 | /** |
394 | * Constructor for CTFEnumField. | |
395 | * | |
396 | * @param enumValue | |
459f705b JCK |
397 | * The Enum value consisting of a pair of Enum value name and its |
398 | * long value | |
d4a8d935 BH |
399 | * @param name |
400 | * The name of this field | |
401 | */ | |
68b18f2f AM |
402 | CTFEnumField(String name, CtfEnumPair enumValue) { |
403 | super(name, new CtfEnumPair(enumValue.getFirst(), | |
0126a8ca | 404 | enumValue.getSecond()), null); |
d4a8d935 BH |
405 | } |
406 | ||
d4a8d935 | 407 | @Override |
68b18f2f AM |
408 | public CtfEnumPair getValue() { |
409 | return (CtfEnumPair) super.getValue(); | |
d4a8d935 BH |
410 | } |
411 | } | |
412 | ||
7a6cee1a | 413 | /** |
51cc7ef4 | 414 | * The CTF field implementation for struct fields with sub-fields |
7a6cee1a GB |
415 | * |
416 | * @author gbastien | |
417 | */ | |
418 | final class CTFStructField extends CtfTmfEventField { | |
419 | ||
420 | /** | |
51cc7ef4 | 421 | * Constructor for CTFStructField. |
7a6cee1a | 422 | * |
51cc7ef4 GB |
423 | * @param fields |
424 | * The children of this field | |
7a6cee1a GB |
425 | * @param name |
426 | * The name of this field | |
427 | */ | |
428 | CTFStructField(String name, CtfTmfEventField[] fields) { | |
81ed27a8 | 429 | super(name, fields, fields); |
7a6cee1a GB |
430 | } |
431 | ||
7a6cee1a GB |
432 | @Override |
433 | public CtfTmfEventField[] getValue() { | |
434 | return (CtfTmfEventField[]) super.getValue(); | |
435 | } | |
436 | ||
437 | @Override | |
51cc7ef4 GB |
438 | public String getFormattedValue() { |
439 | return Arrays.toString(getValue()); | |
7a6cee1a | 440 | } |
51cc7ef4 GB |
441 | |
442 | } | |
443 | ||
444 | /** | |
445 | * The CTF field implementation for variant fields its child | |
446 | * | |
447 | * @author gbastien | |
448 | */ | |
449 | final class CTFVariantField extends CtfTmfEventField { | |
450 | ||
451 | /** | |
452 | * Constructor for CTFVariantField. | |
453 | * | |
454 | * @param field | |
455 | * The field selected for this variant | |
456 | * @param name | |
457 | * The name of this field | |
458 | */ | |
459 | CTFVariantField(String name, CtfTmfEventField field) { | |
459f705b | 460 | super(name, field, new CtfTmfEventField[] { field }); |
51cc7ef4 GB |
461 | } |
462 | ||
463 | @Override | |
464 | public CtfTmfEventField getValue() { | |
465 | return (CtfTmfEventField) super.getValue(); | |
466 | } | |
467 | ||
7a6cee1a GB |
468 | } |
469 | ||
a3fc8213 | 470 | /* Implement other possible fields types here... */ |