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