Skip to content

Commit 4a3f5e2

Browse files
ctf: add static string type
Code assisted by CodeRabbit (GPT 5) for javadoc Change-Id: Iaf2558ab50b1f47604da28f4529bd094135a4ce5 Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
1 parent 64179f5 commit 4a3f5e2

4 files changed

Lines changed: 224 additions & 3 deletions

File tree

ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeAliasParser.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.dynamicstring.DynamicLengthStringParser;
2828
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.enumeration.EnumParser;
2929
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.integer.IntegerDeclarationParser;
30+
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.staticstring.StaticLengthStringParser;
3031
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.string.StringDeclarationParser;
3132
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.variant.VariantParser;
3233
import org.eclipse.tracecompass.internal.ctf.core.event.types.ICTFMetadataNode;
@@ -161,7 +162,9 @@ public IDeclaration parse(ICTFMetadataNode typealias, ICommonTreeParserParameter
161162
} else if (JsonMetadataStrings.FIXED_UNSIGNED_ENUMERATION.equals(type)) {
162163
targetDeclaration = EnumParser.INSTANCE.parse(typealias, new EnumParser.Param(trace, scope));
163164
} else if (JsonMetadataStrings.DYNAMIC_LENGTH_STRING.equals(type)) {
164-
targetDeclaration = DynamicLengthStringParser.INSTANCE.parse(typealias, new DynamicLengthStringParser.Param(trace));
165+
targetDeclaration = DynamicLengthStringParser.INSTANCE.parse(typealias, new DynamicLengthStringParser.Param(trace));
166+
} else if (JsonMetadataStrings.STATIC_LENGTH_STRING.equals(type)) {
167+
targetDeclaration = StaticLengthStringParser.INSTANCE.parse(typealias, new StaticLengthStringParser.Param(trace));
165168
} else {
166169
throw new ParseException("Invalid field class: " + type); //$NON-NLS-1$
167170
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Ericsson
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*******************************************************************************/
11+
package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.staticstring;
12+
13+
import java.nio.charset.Charset;
14+
import java.nio.charset.StandardCharsets;
15+
16+
import org.eclipse.jdt.annotation.NonNullByDefault;
17+
import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
18+
import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
19+
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
20+
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.JsonStructureFieldMemberMetadataNode;
21+
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
22+
import org.eclipse.tracecompass.internal.ctf.core.event.types.ICTFMetadataNode;
23+
import org.eclipse.tracecompass.internal.ctf.core.event.types.StaticLengthStringDeclaration;
24+
import org.eclipse.tracecompass.internal.ctf.core.utils.JsonMetadataStrings;
25+
26+
import com.google.gson.JsonElement;
27+
import com.google.gson.JsonObject;
28+
29+
/**
30+
* A dynamic-length string field class is an abstract string field class which
31+
* describes dynamic-length string fields.
32+
*
33+
* A dynamic-length string field is a sequence of zero or more contiguous
34+
* encoded Unicode codepoints. All the encoded codepoints of a dynamic-length
35+
* string field before the first "NULL" (U+0000) codepoint, if any, form the
36+
* resulting string value. The first U+0000 codepoint, if any, and all the
37+
* following bytes are considered padding (garbage data).
38+
*
39+
* The length, or number of bytes, of a dynamic-length string field is the
40+
* value of another, anterior (already encoded/decoded) length field. A
41+
* consumer can locate this length field thanks to the length-field-location
42+
* property of the dynamic-length string field class.
43+
*
44+
* @author Matthew Khouzam
45+
*/
46+
public final class StaticLengthStringParser extends AbstractScopedCommonTreeParser {
47+
48+
/**
49+
* Instance
50+
*/
51+
public static final StaticLengthStringParser INSTANCE = new StaticLengthStringParser();
52+
53+
private StaticLengthStringParser() {
54+
}
55+
56+
@Override
57+
public IDeclaration parse(ICTFMetadataNode node, ICommonTreeParserParameter param) throws ParseException {
58+
if (!(node instanceof JsonStructureFieldMemberMetadataNode)) {
59+
throw new ParseException("Static-length string only supported in JSON metadata"); //$NON-NLS-1$
60+
}
61+
62+
JsonStructureFieldMemberMetadataNode member = (JsonStructureFieldMemberMetadataNode) node;
63+
JsonElement fieldClassElement = member.getFieldClass();
64+
if (fieldClassElement == null || !fieldClassElement.isJsonObject()) {
65+
throw new ParseException(getClass().getName() + " fieldclass must be a json object."); //$NON-NLS-1$
66+
}
67+
JsonObject fieldClass = fieldClassElement.getAsJsonObject();
68+
JsonElement lengthField = fieldClass.get(JsonMetadataStrings.LENGTH);
69+
if (lengthField == null) {
70+
throw new ParseException("Dynamic-length string requires length-field-location property"); //$NON-NLS-1$
71+
}
72+
JsonElement encodingField = fieldClass.get(JsonMetadataStrings.ENCODING);
73+
int length = lengthField.getAsInt();
74+
Charset encoding = encodingField != null ?
75+
JsonMetadataStrings.ENCODINGS.getOrDefault(encodingField.getAsString(), StandardCharsets.UTF_8) :
76+
StandardCharsets.UTF_8;
77+
return new StaticLengthStringDeclaration(length, encoding);
78+
}
79+
80+
/**
81+
* Parameters for the static-length string parser
82+
*/
83+
@NonNullByDefault
84+
public static final class Param implements ICommonTreeParserParameter {
85+
private final CTFTrace fTrace;
86+
87+
/**
88+
* Parameter constructor
89+
*
90+
* @param trace the trace
91+
*/
92+
public Param(CTFTrace trace) {
93+
fTrace = trace;
94+
}
95+
96+
/**
97+
* Get the trace
98+
*
99+
* @return the trace
100+
*/
101+
public CTFTrace getTrace() {
102+
return fTrace;
103+
}
104+
}
105+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Ericsson
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*******************************************************************************/
11+
package org.eclipse.tracecompass.internal.ctf.core.event.types;
12+
13+
import java.nio.charset.Charset;
14+
15+
import org.eclipse.jdt.annotation.Nullable;
16+
import org.eclipse.tracecompass.ctf.core.CTFException;
17+
import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
18+
import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope;
19+
import org.eclipse.tracecompass.ctf.core.event.types.Declaration;
20+
import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
21+
import org.eclipse.tracecompass.ctf.core.event.types.StringDefinition2;
22+
23+
import com.google.common.base.Objects;
24+
25+
/**
26+
* Static-length string declaration with encoding support
27+
*
28+
* @author Matthew Khouzam
29+
*/
30+
public class StaticLengthStringDeclaration extends Declaration {
31+
32+
private final Charset fEncoding;
33+
private final int fLength;
34+
35+
/**
36+
* Constructor
37+
*
38+
* @param length
39+
* the fixed length of the string in bytes
40+
* @param encoding
41+
* the character encoding
42+
*/
43+
public StaticLengthStringDeclaration(int length, Charset encoding) {
44+
fLength = length;
45+
fEncoding = encoding;
46+
}
47+
48+
/**
49+
* Get the encoding
50+
*
51+
* @return the character encoding
52+
*/
53+
public Charset getEncoding() {
54+
return fEncoding;
55+
}
56+
57+
/**
58+
* Get the length
59+
*
60+
* @return the length
61+
*/
62+
public int getLength() {
63+
return fLength;
64+
}
65+
66+
@Override
67+
public StringDefinition2 createDefinition(@Nullable IDefinitionScope definitionScope, String fieldName, BitBuffer input) throws CTFException {
68+
long rawLength = fLength;
69+
if (rawLength < 0) {
70+
throw new CTFException("Cannot have a length < 0, declared = " + rawLength); //$NON-NLS-1$
71+
}
72+
if (rawLength > 1e6) {
73+
throw new CTFException("Cannot have a length > 1000000, declared = " + rawLength); //$NON-NLS-1$
74+
}
75+
int length = (int) rawLength;
76+
byte[] bytes = new byte[length];
77+
for (int i = 0; i < length; i++) {
78+
bytes[i] = (byte) input.get(Byte.SIZE, false);
79+
}
80+
String value = new String(bytes, fEncoding);
81+
int nullIndex = value.indexOf('\0');
82+
if (nullIndex >= 0) {
83+
value = value.substring(0, nullIndex);
84+
}
85+
return new StringDefinition2(this, definitionScope, fieldName, value);
86+
}
87+
88+
@Override
89+
public long getAlignment() {
90+
return Byte.SIZE;
91+
}
92+
93+
@Override
94+
public int getMaximumSize() {
95+
return Integer.MAX_VALUE;
96+
}
97+
98+
@Override
99+
public String toString() {
100+
return "static_string[" + fLength + "]<" + fEncoding.name() + ">"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
101+
}
102+
103+
@Override
104+
public boolean isBinaryEquivalent(IDeclaration other) {
105+
if (!(other instanceof StaticLengthStringDeclaration)) {
106+
return false;
107+
}
108+
StaticLengthStringDeclaration o = (StaticLengthStringDeclaration) other;
109+
return fLength == o.fLength && Objects.equal(fEncoding, o.fEncoding);
110+
}
111+
}

ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/utils/JsonMetadataStrings.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ private JsonMetadataStrings() {
210210
*/
211211
public static final String ENCODING = "encoding"; //$NON-NLS-1$
212212

213-
214-
213+
/**
214+
* Static length string
215+
*/
216+
public static final String STATIC_LENGTH_STRING = "static-length-string"; //$NON-NLS-1$
215217
}

0 commit comments

Comments
 (0)