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