diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/IntegerDeclaration.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/IntegerDeclaration.java index c6c754b01d..929b7c3843 100644 --- a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/IntegerDeclaration.java +++ b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/IntegerDeclaration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others + * Copyright (c) 2011, 2024 Ericsson, Ecole Polytechnique de Montreal and others * * All rights reserved. This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 which @@ -21,6 +21,10 @@ import java.math.BigInteger; import java.nio.ByteOrder; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tracecompass.ctf.core.CTFException; @@ -129,6 +133,7 @@ public final class IntegerDeclaration extends Declaration implements ISimpleData private final long fAlignment; private final String fClock; private boolean fVarint = false; + private Map> fMappings = new HashMap<>(); // ------------------------------------------------------------------------ // Constructors @@ -315,7 +320,38 @@ public static IntegerDeclaration createDeclaration(int len, boolean signed, int } } } - return new IntegerDeclaration(len, signed, base, byteOrder, encoding, clock, alignment, role); + return new IntegerDeclaration(len, signed, base, byteOrder, encoding, clock, alignment, role, null); + } + + /** + * Alternate create method for CTF2 integers which have roles and mappings + * + * @param len + * The length in bits + * @param signed + * Is the integer signed? false == unsigned + * @param base + * The base (10-16 are most common) + * @param byteOrder + * Big-endian little-endian or other + * @param encoding + * ascii, utf8 or none. + * @param clock + * The clock path, can be null + * @param alignment + * The minimum alignment. Should be >= 1 + * @param role + * The role of the declaration + * @param mappings + * A mapped range of integers + * @return The integer declaration + * @since 4.5 + */ + public static IntegerDeclaration createDeclaration(int len, boolean signed, int base, + @Nullable ByteOrder byteOrder, Encoding encoding, String clock, long alignment, @Nullable String role, Map> mappings) { + IntegerDeclaration decl = createDeclaration(len, signed, base, byteOrder, encoding, clock, alignment, role); + decl.setMappings(mappings); + return decl; } /** @@ -340,6 +376,33 @@ public static IntegerDeclaration createVarintDeclaration(boolean signed, int bas return decl; } + /** + * Create method for CTF2 varints with mappings + * + * @param signed + * Is the integer signed? false == unsigned + * @param base + * The base (10-16 are most common) + * @param role + * The role of the integer declaration + * @param varint + * A boolean indicating if the declaration is a varint + * @param mappings + * A mapped range of integers + * @return IntegerDeclaration + * + * @since 4.5 + */ + public static IntegerDeclaration createVarintDeclaration(boolean signed, int base, @Nullable String role, boolean varint, @Nullable Map> mappings) { + IntegerDeclaration decl = new IntegerDeclaration(0, signed, base, null, Encoding.NONE, "", 0); //$NON-NLS-1$ + decl.setRole(role); + decl.setVarint(varint); + if (mappings != null) { + decl.setMappings(mappings); + } + return decl; + } + private static boolean isBigEndian(@Nullable ByteOrder byteOrder) { return (byteOrder != null) && byteOrder.equals(ByteOrder.BIG_ENDIAN); } @@ -396,13 +459,16 @@ private IntegerDeclaration(int len, boolean signed, int base, * The role of the integer declaration */ private IntegerDeclaration(int len, boolean signed, int base, - @Nullable ByteOrder byteOrder, Encoding encoding, String clock, long alignment, @Nullable String role) { + @Nullable ByteOrder byteOrder, Encoding encoding, String clock, long alignment, @Nullable String role, @Nullable Map> mappings) { this(len, signed, base, byteOrder, encoding, clock, alignment); setRole(role); + if (mappings != null) { + setMappings(mappings); + } } private IntegerDeclaration(int len, boolean signed, @Nullable ByteOrder byteOrder) { - this(len, signed, BASE_10, byteOrder, Encoding.NONE, "", BYTE_ALIGN, null); //$NON-NLS-1$ + this(len, signed, BASE_10, byteOrder, Encoding.NONE, "", BYTE_ALIGN, null, null); //$NON-NLS-1$ } // ------------------------------------------------------------------------ @@ -438,6 +504,26 @@ private void setVarint(boolean varint) { fVarint = varint; } + /** + * Getter for mappings + * + * @return a mapped range of integers + * @since 4.5 + */ + public Map> getMappings() { + return fMappings; + } + + /** + * Setter for mappings + * + * @param mappings + * a mapped range of integers + */ + private void setMappings(Map> mappings) { + fMappings = mappings; + } + /** * Get the integer base commonly decimal or hex * @@ -526,7 +612,11 @@ public IntegerDefinition createDefinition(@Nullable IDefinitionScope definitionS input.setByteOrder(fByteOrder); long value = read(input); input.setByteOrder(byteOrder); - return new IntegerDefinition(this, definitionScope, fieldName, value); + if (fMappings.size() == 0) { + return new IntegerDefinition(this, definitionScope, fieldName, value); + } + String mappingName = getMappingForValue(value); + return new IntegerDefinition(this, definitionScope, fieldName, value, mappingName); } @Override @@ -687,4 +777,25 @@ private boolean isBinaryEquivalent(IntegerDeclaration other) { return !((fLength != BYTE_ALIGN) && !fByteOrder.equals(other.fByteOrder)); } + private String getMappingForValue(long value) { + String mapping = ""; //$NON-NLS-1$ + int count = 0; + for (Map.Entry> entry : fMappings.entrySet()) { + String mappingName = entry.getKey(); + List ranges = entry.getValue(); + + for (IntegerRange range : ranges) { + if (range.getStart() <= value && value <= range.getEnd()) { + if (count != 0) { + mapping += " " + mappingName; //$NON-NLS-1$ + } else { + mapping += mappingName; + } + count++; + + } + } + } + return mapping; + } } diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/IntegerDefinition.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/IntegerDefinition.java index ea3f8d815c..18b2502eff 100644 --- a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/IntegerDefinition.java +++ b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/IntegerDefinition.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others + * Copyright (c) 2011, 2024 Ericsson, Ecole Polytechnique de Montreal and others * * All rights reserved. This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 which @@ -41,6 +41,7 @@ public final class IntegerDefinition extends SimpleDatatypeDefinition { private static final int INT_BASE_8 = 8; private static final int INT_BASE_2 = 2; private final long fValue; + private final String fMapping; // ------------------------------------------------------------------------ // Constructors @@ -62,8 +63,30 @@ public IntegerDefinition(@NonNull IntegerDeclaration declaration, IDefinitionScope definitionScope, @NonNull String fieldName, long value) { super(declaration, definitionScope, fieldName); fValue = value; + fMapping = null; } + /** + * Constructor with mappings + * + * @param declaration + * the parent declaration + * @param definitionScope + * the parent scope + * @param fieldName + * the field name + * @param value + * integer value + * @param mappings + * mapping value + * @since 4.5 + */ + public IntegerDefinition(@NonNull IntegerDeclaration declaration, + IDefinitionScope definitionScope, @NonNull String fieldName, long value, String mappings) { + super(declaration, definitionScope, fieldName); + fMapping = mappings; + fValue = value; + } // ------------------------------------------------------------------------ // Getters/Setters/Predicates // ------------------------------------------------------------------------ @@ -77,6 +100,16 @@ public long getValue() { return fValue; } + /** + * Gets the value of the mappings + * + * @return A mapped range of integers + * @since 4.5 + */ + public String getMappings() { + return fMapping; + } + @Override public IntegerDeclaration getDeclaration() { return (IntegerDeclaration) super.getDeclaration(); @@ -159,10 +192,11 @@ public static String formatNumber(long value, int base, boolean signed) { @Override public byte[] getBytes() { - byte[] data = new byte[(int) Math.ceil(getDeclaration().getLength()/8.0)]; + byte[] data = new byte[(int) Math.ceil(getDeclaration().getLength() / 8.0)]; ByteBuffer bb = ByteBuffer.wrap(data); bb.order(getDeclaration().getByteOrder()); bb.putLong(fValue); return data; } + } diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/IntegerRange.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/IntegerRange.java new file mode 100644 index 0000000000..5759873d05 --- /dev/null +++ b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/IntegerRange.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2024 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License 2.0 which + * accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.tracecompass.ctf.core.event.types; + +/** + * A simple range class + * + * @author Vlad Arama + * @since 4.5 + */ +public class IntegerRange { + private final long startRange; + private final long endRange; + + /** + * Constructor + * + * @param start + * The start of the range + * @param end + * The end of the range + */ + public IntegerRange(long start, long end) { + startRange = start; + endRange = end; + } + + /** + * Getter for the start of the range + * + * @return The start of the range + */ + public long getStart() { + if (startRange > endRange) { + return endRange; + } + return startRange; + } + + /** + * Getter for the end of the range + * + * @return The end of the range + */ + public long getEnd() { + if (startRange > endRange) { + return startRange; + } + return endRange; + } +} \ No newline at end of file diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/IntegerDeclarationParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/IntegerDeclarationParser.java index 2cbc6777fe..f21b89dac3 100644 --- a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/IntegerDeclarationParser.java +++ b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/IntegerDeclarationParser.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2023 Ericsson + * Copyright (c) 2015, 2024 Ericsson * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -16,12 +16,16 @@ import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString; import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.tracecompass.ctf.core.event.types.Encoding; import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration; +import org.eclipse.tracecompass.ctf.core.event.types.IntegerRange; import org.eclipse.tracecompass.ctf.core.trace.CTFTrace; import org.eclipse.tracecompass.ctf.parser.CTFParser; import org.eclipse.tracecompass.internal.ctf.core.CtfCoreLoggerUtil; @@ -37,6 +41,8 @@ import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.string.EncodingParser; import org.eclipse.tracecompass.internal.ctf.core.event.types.ICTFMetadataNode; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; /** @@ -111,6 +117,7 @@ public Param(CTFTrace trace) { private static final @NonNull String SIGNED = "signed"; //$NON-NLS-1$ private static final @NonNull String ALIGNMENT = "alignment"; //$NON-NLS-1$ private static final @NonNull String VARINT = "varint"; //$NON-NLS-1$ + private static final @NonNull String MAPPINGS = "mappings"; //$NON-NLS-1$ private IntegerDeclarationParser() { } @@ -133,6 +140,8 @@ public IntegerDeclaration parse(ICTFMetadataNode integer, ICommonTreeParserParam /* The return value */ boolean signed = false; boolean varint = false; + @NonNull + Map<@NonNull String, @NonNull List<@NonNull IntegerRange>> mappings = new HashMap<>(); ByteOrder byteOrder = trace.getByteOrder(); long size = 0; long alignment = 0; @@ -157,7 +166,30 @@ public IntegerDeclaration parse(ICTFMetadataNode integer, ICommonTreeParserParam if (fieldclass.has(VARINT)) { varint = fieldclass.get(VARINT).getAsBoolean(); } + if (fieldclass.has(MAPPINGS)) { + JsonObject mappingsJson = fieldclass.get(MAPPINGS).getAsJsonObject(); + + for (String mappingName : mappingsJson.keySet()) { + if (mappingName != null) { + JsonArray mappingRangesJson = mappingsJson.getAsJsonArray(mappingName); + List mappingRanges = new ArrayList<>(); + + for (JsonElement rangeElement : mappingRangesJson) { + JsonArray rangeArray = rangeElement.getAsJsonArray(); + long start = rangeArray.get(0).getAsBigInteger().longValueExact(); + long end = rangeArray.get(1).getAsBigInteger().longValueExact(); + IntegerRange range = new IntegerRange(start, end); + mappingRanges.add(range); + } + + mappings.put(mappingName, mappingRanges); + } + } + } if (varint) { + if (mappings.size() > 0) { + return IntegerDeclaration.createVarintDeclaration(signed, base, role, true, mappings); + } return IntegerDeclaration.createVarintDeclaration(signed, base, role, true); } if (fieldclass.has(ALIGNMENT)) { @@ -229,6 +261,10 @@ public IntegerDeclaration parse(ICTFMetadataNode integer, ICommonTreeParserParam alignment = 1; } + if (mappings.size() > 0) { + return IntegerDeclaration.createDeclaration(base, signed, base, byteOrder, encoding, clock, alignment, role, mappings); + } + return IntegerDeclaration.createDeclaration((int) size, signed, base, byteOrder, encoding, clock, alignment, role); } diff --git a/ctf/org.eclipse.tracecompass.tmf.ctf.core/src/org/eclipse/tracecompass/tmf/ctf/core/event/CtfTmfEventField.java b/ctf/org.eclipse.tracecompass.tmf.ctf.core/src/org/eclipse/tracecompass/tmf/ctf/core/event/CtfTmfEventField.java index d156b50792..780de9b190 100644 --- a/ctf/org.eclipse.tracecompass.tmf.ctf.core/src/org/eclipse/tracecompass/tmf/ctf/core/event/CtfTmfEventField.java +++ b/ctf/org.eclipse.tracecompass.tmf.ctf.core/src/org/eclipse/tracecompass/tmf/ctf/core/event/CtfTmfEventField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2014 Ericsson, École Polytechnique de Montréal + * Copyright (c) 2011, 2024 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 2.0 which @@ -106,7 +106,12 @@ protected CtfTmfEventField(@NonNull String name, Object value, ITmfEventField[] if (fieldDef instanceof IntegerDefinition) { IntegerDefinition intDef = (IntegerDefinition) fieldDef; int base = intDef.getDeclaration().getBase(); - field = new CTFIntegerField(fieldName, intDef.getValue(), base, intDef.getDeclaration().isSigned()); + String mappings = intDef.getMappings(); + if (mappings != null) { + field = new CTFIntegerField(fieldName, intDef.getValue(), base, intDef.getDeclaration().isSigned(), mappings); + } else { + field = new CTFIntegerField(fieldName, intDef.getValue(), base, intDef.getDeclaration().isSigned()); + } } else if (fieldDef instanceof EnumDefinition) { EnumDefinition enumDef = (EnumDefinition) fieldDef; @@ -229,6 +234,7 @@ final class CTFIntegerField extends CtfTmfEventField { private final int fBase; private final boolean fSigned; + private final String fMappings; /** * A CTF "IntegerDefinition" can be an integer of any byte size, so in the @@ -245,6 +251,31 @@ final class CTFIntegerField extends CtfTmfEventField { super(name, Long.valueOf(longValue), null); fSigned = signed; fBase = base; + fMappings = null; + } + + /** + * A CTF "IntegerDefinition" can be an integer of any byte size, so in the + * Java parser this is interpreted as a long. + * + * @param name + * The name of this field + * @param longValue + * The integer value of this field + * @param signed + * Is the value signed or not + * @param mapping + * The mapping of the integer + */ + CTFIntegerField(@NonNull String name, long longValue, int base, boolean signed, String mappings) { + super(name, Long.valueOf(longValue), null); + fSigned = signed; + fBase = base; + fMappings = mappings; + } + + public String getMappings() { + return fMappings; } @Override @@ -254,6 +285,9 @@ public Long getValue() { @Override public String getFormattedValue() { + if (fMappings != null && !fMappings.equals("")) { //$NON-NLS-1$ + return fMappings; + } return IntegerDefinition.formatNumber(getValue(), fBase, fSigned); } @@ -285,7 +319,7 @@ public String getValue() { @Override public String getFormattedValue() { - return "\""+getValue()+"\""; //$NON-NLS-1$//$NON-NLS-2$ + return "\"" + getValue() + "\""; //$NON-NLS-1$//$NON-NLS-2$ } } @@ -522,8 +556,8 @@ public CtfTmfEventField getValue() { @Override public ITmfEventField getField(final String... path) { /* - * We use the == to make sure that this constant was used, otherwise, it could - * conflict with a field with the same name + * We use the == to make sure that this constant was used, otherwise, it + * could conflict with a field with the same name */ if (path.length == 1 && path[0] == FIELD_VARIANT_SELECTED) { Iterator it = getFields().iterator();