ctf: Fix race condition in ctfiterator
[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 field = new CTFIntegerArrayField(fieldName, values, ((IntegerDeclaration) arrayDecl.getElementType()).getBase(),
122 ((IntegerDeclaration) arrayDecl.getElementType()).isSigned());
123 }
124 /* Add other types of arrays here */
125
126 } else if (fieldDef instanceof SequenceDefinition) {
127 SequenceDefinition seqDef = (SequenceDefinition) fieldDef;
128 SequenceDeclaration seqDecl = seqDef.getDeclaration();
129
130 if (seqDef.getLength() == 0) {
131 /* Some sequences have length = 0. Simply use an empty string */
132 field = new CTFStringField(fieldName, ""); //$NON-NLS-1$
133 } else if (seqDef.isString()) {
134 /* Interpret this sequence as a String */
135 field = new CTFStringField(fieldName, seqDef.toString());
136 } else if (seqDecl.getElementType() instanceof IntegerDeclaration) {
137 /* Sequence of integers => CTFIntegerArrayField */
138 List<Long> values = new ArrayList<Long>(seqDef.getLength());
139 for (int i = 0; i < seqDef.getLength(); i++) {
140 values.add(((IntegerDefinition) seqDef.getElem(i)).getValue());
141 }
142 field = new CTFIntegerArrayField(fieldName, values, ((IntegerDeclaration) seqDecl.getElementType()).getBase(),
143 ((IntegerDeclaration) seqDecl.getElementType()).isSigned());
144 }
145 /* Add other Sequence types here */
146
147 } else if (fieldDef instanceof StructDefinition) {
148 StructDefinition strDef = (StructDefinition) fieldDef;
149
150 String curFieldName = null;
151 Definition curFieldDef;
152 CtfTmfEventField curField;
153 List<ITmfEventField> list = new ArrayList<ITmfEventField>();
154 /* Recursively parse the fields */
155 for (Entry<String, Definition> entry : strDef.getDefinitions().entrySet()) {
156 curFieldName = entry.getKey();
157 curFieldDef = entry.getValue();
158 curField = CtfTmfEventField.parseField(curFieldDef, curFieldName);
159 list.add(curField);
160 }
161 field = new CTFStructField(fieldName, list.toArray(new CtfTmfEventField[list.size()]));
162
163 } else if (fieldDef instanceof VariantDefinition) {
164 VariantDefinition varDef = (VariantDefinition) fieldDef;
165
166 String curFieldName = varDef.getCurrentFieldName();
167 Definition curFieldDef = varDef.getDefinitions().get(curFieldName);
168 if (curFieldDef != null) {
169 CtfTmfEventField subField = CtfTmfEventField.parseField(curFieldDef, curFieldName);
170 field = new CTFVariantField(fieldName, subField);
171 } else {
172 /* A safe-guard, but curFieldDef should never be null */
173 field = new CTFStringField(curFieldName, ""); //$NON-NLS-1$
174 }
175
176 } else {
177 /*
178 * Safe-guard, to avoid null exceptions later, field is expected not
179 * to be null
180 */
181 field = new CTFStringField(fieldName, Messages.TmfEventField_UnsupportedType + fieldDef.getClass().toString());
182 }
183 return field;
184 }
185
186 @Override
187 public String toString() {
188 return getName() + '=' + getFormattedValue();
189 }
190
191 /**
192 * Print a numeric value as a string in a given base
193 *
194 * @param value
195 * The value to print as string
196 * @param base
197 * The base for this value
198 * @param signed
199 * Is the value signed or not
200 * @return formatted number string
201 * @since 2.0
202 */
203 public final static String formatNumber(long value, int base, boolean signed) {
204 String s;
205
206 /* Format the number correctly according to the integer's base */
207 switch (base) {
208 case 2:
209 s = "0b" + Long.toBinaryString(value); //$NON-NLS-1$
210 break;
211 case 8:
212 s = "0" + Long.toOctalString(value); //$NON-NLS-1$
213
214 break;
215 case 16:
216 s = "0x" + Long.toHexString(value); //$NON-NLS-1$
217 break;
218 case 10:
219 default:
220 /* For non-standard base, we'll just print it as a decimal number */
221 if (!signed && value < 0) {
222 /* Since there are no 'unsigned long', handle this case with BigInteger */
223 BigInteger bigInteger = BigInteger.valueOf(value);
224 /*
225 * powerOfTwo = 2^64 we add 2^64 to the negative number to get
226 * the real unsigned value
227 */
228 BigInteger powerOfTwo = (BigInteger.valueOf(Long.MAX_VALUE)).add(BigInteger.valueOf(1));
229 powerOfTwo = powerOfTwo.multiply(BigInteger.valueOf(2));
230 bigInteger = bigInteger.add(powerOfTwo);
231
232 s = bigInteger.toString();
233 } else {
234 s = Long.toString(value);
235 }
236 break;
237 }
238 return s;
239 }
240
241 }
242
243 /**
244 * The CTF field implementation for integer fields.
245 *
246 * @author alexmont
247 */
248 final class CTFIntegerField extends CtfTmfEventField {
249
250 private final int base;
251 private final boolean signed;
252
253 /**
254 * A CTF "IntegerDefinition" can be an integer of any byte size, so in the
255 * Java parser this is interpreted as a long.
256 *
257 * @param name
258 * The name of this field
259 * @param longValue
260 * The integer value of this field
261 * @param signed
262 * Is the value signed or not
263 */
264 CTFIntegerField(String name, long longValue, int base, boolean signed) {
265 super(name, longValue, null);
266 this.signed = signed;
267 this.base = base;
268 }
269
270 @Override
271 public Long getValue() {
272 return (Long) super.getValue();
273 }
274
275 @Override
276 public String getFormattedValue() {
277 return formatNumber(getValue(), base, signed);
278 }
279
280 }
281
282 /**
283 * The CTF field implementation for string fields
284 *
285 * @author alexmont
286 */
287 final class CTFStringField extends CtfTmfEventField {
288
289 /**
290 * Constructor for CTFStringField.
291 *
292 * @param strValue
293 * The string value of this field
294 * @param name
295 * The name of this field
296 */
297 CTFStringField(String name, String strValue) {
298 super(name, strValue, null);
299 }
300
301 @Override
302 public String getValue() {
303 return (String) super.getValue();
304 }
305 }
306
307 /**
308 * CTF field implementation for arrays of integers.
309 *
310 * @author alexmont
311 */
312 final class CTFIntegerArrayField extends CtfTmfEventField {
313
314 private final int base;
315 private final boolean signed;
316 private String formattedValue = null;
317
318 /**
319 * Constructor for CTFIntegerArrayField.
320 *
321 * @param name
322 * The name of this field
323 * @param longValues
324 * The array of integers (as longs) that compose this field's
325 * value
326 * @param signed
327 * Are the values in the array signed or not
328 */
329 CTFIntegerArrayField(String name, List<Long> longValues, int base, boolean signed) {
330 super(name, longValues, null);
331 this.base = base;
332 this.signed = signed;
333 }
334
335 @Override
336 public List<Long> getValue() {
337 return (List<Long>) super.getValue();
338 }
339
340 @Override
341 public String getFormattedValue() {
342 if (formattedValue == null) {
343 List<String> strings = new ArrayList<String>();
344 for (Long value : getValue()) {
345 strings.add(formatNumber(value, base, signed));
346 }
347 formattedValue = strings.toString();
348 }
349 return formattedValue;
350 }
351
352 }
353
354 /**
355 * CTF field implementation for floats.
356 *
357 * @author emathko
358 */
359 final class CTFFloatField extends CtfTmfEventField {
360
361 /**
362 * Constructor for CTFFloatField.
363 *
364 * @param value
365 * The float value (actually a double) of this field
366 * @param name
367 * The name of this field
368 */
369 protected CTFFloatField(String name, double value) {
370 super(name, value, null);
371 }
372
373 @Override
374 public Double getValue() {
375 return (Double) super.getValue();
376 }
377 }
378
379 /**
380 * The CTF field implementation for Enum fields
381 *
382 * @author Bernd Hufmann
383 */
384 final class CTFEnumField extends CtfTmfEventField {
385
386 /**
387 * Constructor for CTFEnumField.
388 *
389 * @param enumValue
390 * The Enum value consisting of a pair of Enum value name and its
391 * long value
392 * @param name
393 * The name of this field
394 */
395 CTFEnumField(String name, CtfEnumPair enumValue) {
396 super(name, new CtfEnumPair(enumValue.getFirst(),
397 enumValue.getSecond().longValue()), null);
398 }
399
400 @Override
401 public CtfEnumPair getValue() {
402 return (CtfEnumPair) super.getValue();
403 }
404 }
405
406 /**
407 * The CTF field implementation for struct fields with sub-fields
408 *
409 * @author gbastien
410 */
411 final class CTFStructField extends CtfTmfEventField {
412
413 /**
414 * Constructor for CTFStructField.
415 *
416 * @param fields
417 * The children of this field
418 * @param name
419 * The name of this field
420 */
421 CTFStructField(String name, CtfTmfEventField[] fields) {
422 super(name, fields, fields);
423 }
424
425 @Override
426 public CtfTmfEventField[] getValue() {
427 return (CtfTmfEventField[]) super.getValue();
428 }
429
430 @Override
431 public String getFormattedValue() {
432 return Arrays.toString(getValue());
433 }
434
435 }
436
437 /**
438 * The CTF field implementation for variant fields its child
439 *
440 * @author gbastien
441 */
442 final class CTFVariantField extends CtfTmfEventField {
443
444 /**
445 * Constructor for CTFVariantField.
446 *
447 * @param field
448 * The field selected for this variant
449 * @param name
450 * The name of this field
451 */
452 CTFVariantField(String name, CtfTmfEventField field) {
453 super(name, field, new CtfTmfEventField[] { field });
454 }
455
456 @Override
457 public CtfTmfEventField getValue() {
458 return (CtfTmfEventField) super.getValue();
459 }
460
461 }
462
463 /* Implement other possible fields types here... */
This page took 0.040735 seconds and 5 git commands to generate.