1 /*******************************************************************************
2 * Copyright (c) 2014 Ericsson, Ecole Polytechnique de Montreal and others
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
9 * Contributors: Matthew Khouzam - Initial API and implementation
10 *******************************************************************************/
12 package org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.types
;
14 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
16 import java
.util
.Collection
;
17 import java
.util
.List
;
19 import org
.eclipse
.jdt
.annotation
.Nullable
;
20 import org
.eclipse
.tracecompass
.ctf
.core
.CTFException
;
21 import org
.eclipse
.tracecompass
.ctf
.core
.event
.io
.BitBuffer
;
22 import org
.eclipse
.tracecompass
.ctf
.core
.event
.scope
.IDefinitionScope
;
23 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.AbstractArrayDefinition
;
24 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.CompoundDeclaration
;
25 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.Definition
;
26 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IDeclaration
;
27 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IDefinition
;
28 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IntegerDefinition
;
30 import com
.google
.common
.collect
.ArrayListMultimap
;
31 import com
.google
.common
.collect
.ImmutableList
;
32 import com
.google
.common
.collect
.ImmutableList
.Builder
;
33 import com
.google
.common
.collect
.Multimap
;
36 * A CTF sequence declaration.
38 * An array where the size is fixed but declared in the trace, unlike array
39 * where it is declared with a literal
41 * @author Matthew Khouzam
43 public class SequenceDeclaration
extends CompoundDeclaration
{
45 // ------------------------------------------------------------------------
47 // ------------------------------------------------------------------------
49 private final IDeclaration fElemType
;
50 private final String fLengthName
;
51 private final transient Multimap
<String
, String
> fPaths
= ArrayListMultimap
.create();
53 // ------------------------------------------------------------------------
55 // ------------------------------------------------------------------------
61 * the name of the field describing the length
65 public SequenceDeclaration(@Nullable String lengthName
, IDeclaration elemType
) {
67 fLengthName
= lengthName
;
70 // ------------------------------------------------------------------------
71 // Getters/Setters/Predicates
72 // ------------------------------------------------------------------------
75 public IDeclaration
getElementType() {
80 * Gets the name of the length field
82 * @return the name of the length field
84 public String
getLengthName() {
88 // ------------------------------------------------------------------------
90 // ------------------------------------------------------------------------
93 public AbstractArrayDefinition
createDefinition(
94 @Nullable IDefinitionScope definitionScope
, String fieldName
, BitBuffer input
) throws CTFException
{
95 IDefinition lenDef
= null;
97 if (definitionScope
!= null) {
98 lenDef
= definitionScope
.lookupDefinition(getLengthName());
101 if (lenDef
== null) {
102 throw new CTFException("Sequence length field not found"); //$NON-NLS-1$
105 if (!(lenDef
instanceof IntegerDefinition
)) {
106 throw new CTFException("Sequence length field not integer"); //$NON-NLS-1$
109 IntegerDefinition lengthDefinition
= (IntegerDefinition
) lenDef
;
111 if (lengthDefinition
.getDeclaration().isSigned()) {
112 throw new CTFException("Sequence length must not be signed"); //$NON-NLS-1$
115 long length
= lengthDefinition
.getValue();
116 if ((length
> Integer
.MAX_VALUE
) || (!input
.canRead((int) length
* fElemType
.getMaximumSize()))) {
117 throw new CTFException("Sequence length too long " + length
); //$NON-NLS-1$
120 if (isAlignedBytes()) {
121 // Don't create "useless" definitions
122 byte[] data
= new byte[(int) length
];
124 return new ByteArrayDefinition(this, definitionScope
, fieldName
, data
);
126 Collection
<String
> collection
= fPaths
.get(fieldName
);
127 while (collection
.size() < length
) {
128 fPaths
.put(fieldName
, fieldName
+ '[' + collection
.size() + ']');
130 List
<String
> paths
= (List
<String
>) fPaths
.get(fieldName
);
131 Builder
<Definition
> definitions
= new ImmutableList
.Builder
<>();
132 for (int i
= 0; i
< length
; i
++) {
133 /* We should not have inserted any null values */
134 String elemName
= checkNotNull(paths
.get(i
));
135 definitions
.add(fElemType
.createDefinition(definitionScope
, elemName
, input
));
137 List
<Definition
> list
= checkNotNull(definitions
.build());
138 return new ArrayDefinition(this, definitionScope
, fieldName
, list
);
142 public String
toString() {
143 /* Only used for debugging */
144 return "[declaration] sequence[" + Integer
.toHexString(hashCode()) + ']'; //$NON-NLS-1$
148 public int getMaximumSize() {
149 return Integer
.MAX_VALUE
;
153 public int hashCode() {
154 final int prime
= 31;
156 result
= prime
* result
+ fElemType
.hashCode();
157 result
= prime
* result
+ fLengthName
.hashCode();
162 public boolean equals(@Nullable Object obj
) {
169 if (getClass() != obj
.getClass()) {
172 SequenceDeclaration other
= (SequenceDeclaration
) obj
;
173 if (!fElemType
.equals(other
.fElemType
)) {
176 if (!fLengthName
.equals(other
.fLengthName
)) {
183 public boolean isBinaryEquivalent(@Nullable IDeclaration obj
) {
190 if (getClass() != obj
.getClass()) {
193 SequenceDeclaration other
= (SequenceDeclaration
) obj
;
194 if (!fElemType
.isBinaryEquivalent(other
.fElemType
)) {
197 if (!fLengthName
.equals(other
.fLengthName
)) {