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