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