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