/*******************************************************************************
- * Copyright (c) 2011 Ericsson
+ * Copyright (c) 2011, 2014 Ericsson, École Polytechnique de Montréal
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
- * Contributors: Matthew Khouzam - Initial API and implementation
- * Contributors: Alexendre Montplaisir - Initial API and implementation
+ * Contributors:
+ * Matthew Khouzam - Initial API and implementation
+ * Alexandre Montplaisir - Initial API and implementation, extend TmfEventField
+ * Bernd Hufmann - Add Enum field handling
+ * Geneviève Bastien - Add Struct and Variant field handling
+ * Jean-Christian Kouame - Correct handling of unsigned integer fields
+ * François Doray - Add generic array field type
*******************************************************************************/
package org.eclipse.linuxtools.tmf.core.ctfadaptor;
-import org.eclipse.linuxtools.ctf.core.event.types.ArrayDeclaration;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map.Entry;
+
import org.eclipse.linuxtools.ctf.core.event.types.ArrayDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
import org.eclipse.linuxtools.ctf.core.event.types.EnumDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.SequenceDeclaration;
import org.eclipse.linuxtools.ctf.core.event.types.SequenceDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.StringDefinition;
+import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
+import org.eclipse.linuxtools.ctf.core.event.types.VariantDefinition;
+import org.eclipse.linuxtools.internal.tmf.core.Messages;
import org.eclipse.linuxtools.tmf.core.event.ITmfEventField;
+import org.eclipse.linuxtools.tmf.core.event.TmfEventField;
/**
* The CTF implementation of the TMF event field model
*
- * @version 1.0
+ * @version 2.0
* @author Matthew Khouzam
* @author Alexandre Montplaisir
*/
-public abstract class CtfTmfEventField implements ITmfEventField {
-
- // ------------------------------------------------------------------------
- // Class attributes
- // ------------------------------------------------------------------------
-
- /** @since 1.2 */
- protected static final int FIELDTYPE_INTEGER = 0;
-
- /** @since 1.2 */
- protected static final int FIELDTYPE_STRING = 1;
-
- /** @since 1.2 */
- protected static final int FIELDTYPE_INTEGER_ARRAY = 2;
-
- /** @since 1.2 */
- protected static final int FIELDTYPE_FLOAT = 3;
-
- // ------------------------------------------------------------------------
- // Attributes
- // ------------------------------------------------------------------------
-
- protected final String name;
+public abstract class CtfTmfEventField extends TmfEventField {
// ------------------------------------------------------------------------
// Constructor
*
* @param name
* The name of this field
+ * @param value
+ * The value of this field. Its type should match the field type.
+ * @param fields
+ * The children fields. Useful for composite fields
+ * @since 2.0
*/
- protected CtfTmfEventField(String name) {
- /* Strip the underscore */
- if (name.startsWith("_")) { //$NON-NLS-1$
- this.name = name.substring(1);
- } else {
- this.name = name;
- }
- }
-
- // ------------------------------------------------------------------------
- // Getters/Setters/Predicates
- // ------------------------------------------------------------------------
-
- @Override
- public String getName() {
- return this.name;
+ protected CtfTmfEventField(String name, Object value, ITmfEventField[] fields) {
+ super(/* Strip the underscore from the field name if there is one */
+ name.startsWith("_") ? name.substring(1) : name, //$NON-NLS-1$
+ value,
+ fields);
}
// ------------------------------------------------------------------------
if (fieldDef instanceof IntegerDefinition) {
IntegerDefinition intDef = (IntegerDefinition) fieldDef;
int base = intDef.getDeclaration().getBase();
- field = new CTFIntegerField(intDef.getValue(), fieldName, base);
+ field = new CTFIntegerField(fieldName, intDef.getValue(), base, intDef.getDeclaration().isSigned());
} else if (fieldDef instanceof EnumDefinition) {
EnumDefinition enumDef = (EnumDefinition) fieldDef;
- field = new CTFStringField(enumDef.getValue(), fieldName);
+ field = new CTFEnumField(fieldName, new CtfEnumPair(enumDef.getValue(), enumDef.getIntegerValue()));
} else if (fieldDef instanceof StringDefinition) {
- field = new CTFStringField(
- ((StringDefinition) fieldDef).getValue(), fieldName);
+ field = new CTFStringField(fieldName, ((StringDefinition) fieldDef).getValue());
+
+ } else if (fieldDef instanceof FloatDefinition) {
+ FloatDefinition floatDef = (FloatDefinition) fieldDef;
+ field = new CTFFloatField(fieldName, floatDef.getValue());
} else if (fieldDef instanceof ArrayDefinition) {
ArrayDefinition arrayDef = (ArrayDefinition) fieldDef;
- ArrayDeclaration arrayDecl = arrayDef.getDeclaration();
- if (arrayDef.isString()) {
+ if (arrayDef.getDeclaration().isString()) {
/* This is an array of UTF-8 bytes, a.k.a. a String! */
- field = new CTFStringField(fieldDef.toString(), fieldName);
-
- } else if (arrayDecl.getElementType() instanceof IntegerDeclaration) {
- /* This is a an array of CTF Integers */
- long[] values = new long[arrayDecl.getLength()];
- for (int i = 0; i < arrayDecl.getLength(); i++) {
- values[i] = ((IntegerDefinition) arrayDef.getElem(i))
- .getValue();
+ field = new CTFStringField(fieldName, fieldDef.toString());
+
+ } else {
+ /* Arrays of elements of any other type */
+ Definition[] definitions = arrayDef.getDefinitions();
+ CtfTmfEventField[] elements = new CtfTmfEventField[definitions.length];
+
+ /* Parse the elements of the array. */
+ for (int i = 0; i < definitions.length; i++) {
+ CtfTmfEventField curField = CtfTmfEventField.parseField(
+ definitions[i], fieldName + '[' + i + ']');
+ elements[i] = curField;
}
- field = new CTFIntegerArrayField(values, fieldName);
- }
- /* Add other types of arrays here */
+ field = new CTFArrayField(fieldName, elements);
+ }
} else if (fieldDef instanceof SequenceDefinition) {
SequenceDefinition seqDef = (SequenceDefinition) fieldDef;
SequenceDeclaration seqDecl = seqDef.getDeclaration();
if (seqDef.getLength() == 0) {
/* Some sequences have length = 0. Simply use an empty string */
- field = new CTFStringField("", fieldName); //$NON-NLS-1$
+ field = new CTFStringField(fieldName, ""); //$NON-NLS-1$
} else if (seqDef.isString()) {
/* Interpret this sequence as a String */
- field = new CTFStringField(seqDef.toString(), fieldName);
+ field = new CTFStringField(fieldName, seqDef.toString());
} else if (seqDecl.getElementType() instanceof IntegerDeclaration) {
/* Sequence of integers => CTFIntegerArrayField */
long[] values = new long[seqDef.getLength()];
for (int i = 0; i < seqDef.getLength(); i++) {
- values[i] = ((IntegerDefinition) seqDef.getElem(i))
- .getValue();
+ values[i] = ((IntegerDefinition) seqDef.getElem(i)).getValue();
}
- field = new CTFIntegerArrayField(values, fieldName);
+ field = new CTFIntegerArrayField(fieldName, values,
+ ((IntegerDeclaration) seqDecl.getElementType()).getBase(),
+ ((IntegerDeclaration) seqDecl.getElementType()).isSigned());
+
}
/* Add other Sequence types here */
- } else if (fieldDef instanceof FloatDefinition) {
- FloatDefinition floatDef = (FloatDefinition) fieldDef;
- field = new CTFFloatField(floatDef.getValue(), fieldName);
- }
-
- return field;
- }
+ } else if (fieldDef instanceof StructDefinition) {
+ StructDefinition strDef = (StructDefinition) fieldDef;
+
+ String curFieldName = null;
+ Definition curFieldDef;
+ CtfTmfEventField curField;
+ List<ITmfEventField> list = new ArrayList<>();
+ /* Recursively parse the fields */
+ for (Entry<String, Definition> entry : strDef.getDefinitions().entrySet()) {
+ curFieldName = entry.getKey();
+ curFieldDef = entry.getValue();
+ curField = CtfTmfEventField.parseField(curFieldDef, curFieldName);
+ list.add(curField);
+ }
+ field = new CTFStructField(fieldName, list.toArray(new CtfTmfEventField[list.size()]));
+
+ } else if (fieldDef instanceof VariantDefinition) {
+ VariantDefinition varDef = (VariantDefinition) fieldDef;
+
+ String curFieldName = varDef.getCurrentFieldName();
+ Definition curFieldDef = varDef.getDefinitions().get(curFieldName);
+ if (curFieldDef != null) {
+ CtfTmfEventField subField = CtfTmfEventField.parseField(curFieldDef, curFieldName);
+ field = new CTFVariantField(fieldName, subField);
+ } else {
+ /* A safe-guard, but curFieldDef should never be null */
+ field = new CTFStringField(curFieldName, ""); //$NON-NLS-1$
+ }
- /**
- * Copy factory. Create a new field by (deep-) copying the information in an
- * existing one.
- *
- * @param other
- * The other CtfTmfEventField to copy
- * @return The new CtfTmfEventField
- */
- public static CtfTmfEventField copyFrom(CtfTmfEventField other) {
- switch (other.getFieldType()) {
- case FIELDTYPE_INTEGER:
- CTFIntegerField intOther = (CTFIntegerField) other;
- return new CTFIntegerField(intOther.getValue(), intOther.name,
- intOther.getBase());
- case FIELDTYPE_STRING:
- return new CTFStringField(((CTFStringField) other).getValue(),
- other.name);
- case FIELDTYPE_INTEGER_ARRAY:
- return new CTFIntegerArrayField(
- ((CTFIntegerArrayField) other).getValue(), other.name);
- case FIELDTYPE_FLOAT:
- return new CTFFloatField(((CTFFloatField) other).getValue(),
- other.name);
- default:
- return null;
+ } else {
+ /*
+ * Safe-guard, to avoid null exceptions later, field is expected not
+ * to be null
+ */
+ field = new CTFStringField(fieldName, Messages.TmfEventField_UnsupportedType + fieldDef.getClass().toString());
}
+ return field;
}
@Override
- public CtfTmfEventField clone() {
- return CtfTmfEventField.copyFrom(this);
- }
-
- // ------------------------------------------------------------------------
- // Abstract methods (to be implemented by each specific field type)
- // ------------------------------------------------------------------------
-
- /**
- * Return the int representing this field's value type
- *
- * @return The field type
- */
- public abstract int getFieldType();
-
- /**
- * Return this field's value. You can cast it to the correct type depending
- * on what getFieldType says.
- *
- * @return The field's value
- */
- @Override
- public abstract Object getValue();
-
- // ------------------------------------------------------------------------
- // Other methods defined by ITmfEventField, but not used here.
- // CTF fields do not have sub-fields (yet!)
- // ------------------------------------------------------------------------
-
- @Override
- public String[] getFieldNames() {
- return null;
- }
-
- @Override
- public String getFieldName(int index) {
- return null;
- }
-
- @Override
- public ITmfEventField[] getFields() {
- return null;
- }
-
- @Override
- public ITmfEventField getField(String fieldName) {
- return null;
+ public String toString() {
+ return getName() + '=' + getFormattedValue();
}
- @Override
- public ITmfEventField getField(int index) {
- return null;
- }
}
/**
*/
final class CTFIntegerField extends CtfTmfEventField {
- private final long longValue;
- private final int base;
+ private final int fBase;
+ private final boolean fSigned;
/**
* A CTF "IntegerDefinition" can be an integer of any byte size, so in the
* Java parser this is interpreted as a long.
*
- * @param longValue
- * The integer value of this field
* @param name
* The name of this field
+ * @param longValue
+ * The integer value of this field
+ * @param signed
+ * Is the value signed or not
*/
- CTFIntegerField(long longValue, String name, int base) {
- super(name);
- this.longValue = longValue;
- this.base = base;
- }
-
- /**
- * Return the integer's base. (Not made public until it's needed.)
- *
- * @return The base, usually 10 or 16.
- */
- int getBase() {
- return base;
- }
-
- @Override
- public int getFieldType() {
- return FIELDTYPE_INTEGER;
+ CTFIntegerField(String name, long longValue, int base, boolean signed) {
+ super(name, longValue, null);
+ fSigned = signed;
+ fBase = base;
}
@Override
public Long getValue() {
- return this.longValue;
+ return (Long) super.getValue();
}
@Override
- public String toString() {
- StringBuilder sb = new StringBuilder(name);
- sb.append('=');
-
- /* Format the number correctly according to the integer's base */
- switch (base) {
- case 2:
- sb.append("0b"); //$NON-NLS-1$
- sb.append(Long.toBinaryString(longValue));
- break;
- case 8:
- sb.append('0');
- sb.append(Long.toOctalString(longValue));
- break;
- case 10:
- sb.append(longValue);
- break;
- case 16:
- sb.append("0x"); //$NON-NLS-1$
- sb.append(Long.toHexString(longValue));
- break;
- default:
- /* Non-standard base, we'll just print it as a decimal number */
- sb.append(longValue);
- break;
- }
- return sb.toString();
+ public String getFormattedValue() {
+ return IntegerDefinition.formatNumber(getValue(), fBase, fSigned);
}
+
}
/**
*/
final class CTFStringField extends CtfTmfEventField {
- private final String strValue;
-
/**
* Constructor for CTFStringField.
*
* @param name
* The name of this field
*/
- CTFStringField(String strValue, String name) {
- super(name);
- this.strValue = strValue;
- }
-
- @Override
- public int getFieldType() {
- return FIELDTYPE_STRING;
+ CTFStringField(String name, String strValue) {
+ super(name, strValue, null);
}
@Override
public String getValue() {
- return this.strValue;
- }
-
- @Override
- public String toString() {
- return name + '=' + strValue;
+ return (String) super.getValue();
}
}
*/
final class CTFIntegerArrayField extends CtfTmfEventField {
- private final long[] longValues;
+ private final int fBase;
+ private final boolean fSigned;
+ private String fFormattedValue = null;
/**
* Constructor for CTFIntegerArrayField.
*
+ * @param name
+ * The name of this field
* @param longValues
* The array of integers (as longs) that compose this field's
* value
- * @param name
- * The name of this field
+ * @param signed
+ * Are the values in the array signed or not
*/
- CTFIntegerArrayField(long[] longValues, String name) {
- super(name);
- this.longValues = longValues;
+ CTFIntegerArrayField(String name, long[] longValues, int base, boolean signed) {
+ super(name, longValues, null);
+ fBase = base;
+ fSigned = signed;
}
@Override
- public int getFieldType() {
- return FIELDTYPE_INTEGER_ARRAY;
+ public long[] getValue() {
+ return (long[]) super.getValue();
}
@Override
- public long[] getValue() {
- return this.longValues;
+ public synchronized String getFormattedValue() {
+ if (fFormattedValue == null) {
+ List<String> strings = new ArrayList<>();
+ for (long value : getValue()) {
+ strings.add(IntegerDefinition.formatNumber(value, fBase, fSigned));
+ }
+ fFormattedValue = strings.toString();
+ }
+ return fFormattedValue;
+ }
+
+}
+
+/**
+ * CTF field implementation for arrays of arbitrary types.
+ *
+ * @author fdoray
+ */
+final class CTFArrayField extends CtfTmfEventField {
+
+ private String fFormattedValue = null;
+
+ /**
+ * Constructor for CTFArrayField.
+ *
+ * @param name
+ * The name of this field
+ * @param elements
+ * The array elements of this field
+ */
+ CTFArrayField(String name, CtfTmfEventField[] elements) {
+ super(name, elements, elements);
}
@Override
- public String toString() {
- StringBuffer buffer = new StringBuffer();
- buffer.append("{ "); //$NON-NLS-1$
+ public CtfTmfEventField[] getValue() {
+ return (CtfTmfEventField[]) super.getValue();
+ }
- buffer.append(longValues[0]);
- for (int i = 1; i < longValues.length; i++) {
- buffer.append(", " + longValues[i]); //$NON-NLS-1$
+ @Override
+ public synchronized String getFormattedValue() {
+ if (fFormattedValue == null) {
+ List<String> strings = new ArrayList<>();
+ for (CtfTmfEventField element : getValue()) {
+ strings.add(element.getFormattedValue());
+ }
+ fFormattedValue = strings.toString();
}
- buffer.append('}');
- return name + '=' + buffer.toString();
+ return fFormattedValue;
}
}
*/
final class CTFFloatField extends CtfTmfEventField {
- private final Double value;
-
/**
* Constructor for CTFFloatField.
*
* @param name
* The name of this field
*/
- protected CTFFloatField(double value, String name) {
- super(name);
- this.value = value;
+ protected CTFFloatField(String name, double value) {
+ super(name, value, null);
}
@Override
- public int getFieldType() {
- return FIELDTYPE_FLOAT;
+ public Double getValue() {
+ return (Double) super.getValue();
+ }
+}
+
+/**
+ * The CTF field implementation for Enum fields
+ *
+ * @author Bernd Hufmann
+ */
+final class CTFEnumField extends CtfTmfEventField {
+
+ /**
+ * Constructor for CTFEnumField.
+ *
+ * @param enumValue
+ * The Enum value consisting of a pair of Enum value name and its
+ * long value
+ * @param name
+ * The name of this field
+ */
+ CTFEnumField(String name, CtfEnumPair enumValue) {
+ super(name, new CtfEnumPair(enumValue.getFirst(),
+ enumValue.getSecond()), null);
}
@Override
- public Double getValue() {
- return this.value;
+ public CtfEnumPair getValue() {
+ return (CtfEnumPair) super.getValue();
+ }
+}
+
+/**
+ * The CTF field implementation for struct fields with sub-fields
+ *
+ * @author gbastien
+ */
+final class CTFStructField extends CtfTmfEventField {
+
+ /**
+ * Constructor for CTFStructField.
+ *
+ * @param fields
+ * The children of this field
+ * @param name
+ * The name of this field
+ */
+ CTFStructField(String name, CtfTmfEventField[] fields) {
+ super(name, fields, fields);
}
@Override
- public String toString() {
- return name + '=' + value;
+ public CtfTmfEventField[] getValue() {
+ return (CtfTmfEventField[]) super.getValue();
}
+
+ @Override
+ public String getFormattedValue() {
+ return Arrays.toString(getValue());
+ }
+
+}
+
+/**
+ * The CTF field implementation for variant fields its child
+ *
+ * @author gbastien
+ */
+final class CTFVariantField extends CtfTmfEventField {
+
+ /**
+ * Constructor for CTFVariantField.
+ *
+ * @param field
+ * The field selected for this variant
+ * @param name
+ * The name of this field
+ */
+ CTFVariantField(String name, CtfTmfEventField field) {
+ super(name, field, new CtfTmfEventField[] { field });
+ }
+
+ @Override
+ public CtfTmfEventField getValue() {
+ return (CtfTmfEventField) super.getValue();
+ }
+
}
/* Implement other possible fields types here... */