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