Commit | Line | Data |
---|---|---|
7b4f13e6 MK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2014 Ericsson, Ecole Polytechnique de Montreal and others | |
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: Matthew Khouzam - Initial API and implementation | |
10 | *******************************************************************************/ | |
11 | ||
12 | package org.eclipse.linuxtools.internal.ctf.core.event.types; | |
13 | ||
14 | import java.util.Collection; | |
15 | import java.util.List; | |
16 | ||
17 | import org.eclipse.jdt.annotation.NonNull; | |
18 | import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer; | |
19 | import org.eclipse.linuxtools.ctf.core.event.scope.IDefinitionScope; | |
20 | import org.eclipse.linuxtools.ctf.core.event.types.AbstractArrayDefinition; | |
21 | import org.eclipse.linuxtools.ctf.core.event.types.CompoundDeclaration; | |
22 | import org.eclipse.linuxtools.ctf.core.event.types.Definition; | |
23 | import org.eclipse.linuxtools.ctf.core.event.types.IDeclaration; | |
cc98c947 | 24 | import org.eclipse.linuxtools.ctf.core.event.types.IDefinition; |
7b4f13e6 MK |
25 | import org.eclipse.linuxtools.ctf.core.event.types.IntegerDefinition; |
26 | import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException; | |
27 | ||
28 | import com.google.common.collect.ArrayListMultimap; | |
29 | import com.google.common.collect.ImmutableList; | |
30 | import com.google.common.collect.ImmutableList.Builder; | |
31 | import com.google.common.collect.Multimap; | |
32 | ||
33 | /** | |
34 | * A CTF sequence declaration. | |
35 | * | |
36 | * An array where the size is fixed but declared in the trace, unlike array | |
37 | * where it is declared with a literal | |
38 | * | |
39 | * @author Matthew Khouzam | |
40 | * @since 3.1 | |
41 | */ | |
42 | public class SequenceDeclaration extends CompoundDeclaration { | |
43 | ||
44 | // ------------------------------------------------------------------------ | |
45 | // Attributes | |
46 | // ------------------------------------------------------------------------ | |
47 | ||
48 | private final IDeclaration fElemType; | |
49 | private final String fLengthName; | |
50 | private final Multimap<String, String> fPaths = ArrayListMultimap.create(); | |
51 | ||
52 | // ------------------------------------------------------------------------ | |
53 | // Constructors | |
54 | // ------------------------------------------------------------------------ | |
55 | ||
56 | /** | |
57 | * Constructor | |
58 | * | |
59 | * @param lengthName | |
60 | * the name of the field describing the length | |
61 | * @param elemType | |
62 | * The element type | |
63 | */ | |
64 | public SequenceDeclaration(String lengthName, IDeclaration elemType) { | |
65 | fElemType = elemType; | |
66 | fLengthName = lengthName; | |
67 | } | |
68 | ||
69 | // ------------------------------------------------------------------------ | |
70 | // Getters/Setters/Predicates | |
71 | // ------------------------------------------------------------------------ | |
72 | ||
73 | @Override | |
74 | public IDeclaration getElementType() { | |
75 | return fElemType; | |
76 | } | |
77 | ||
78 | /** | |
79 | * Gets the name of the length field | |
80 | * | |
81 | * @return the name of the length field | |
82 | */ | |
83 | public String getLengthName() { | |
84 | return fLengthName; | |
85 | } | |
86 | ||
7b4f13e6 MK |
87 | // ------------------------------------------------------------------------ |
88 | // Operations | |
89 | // ------------------------------------------------------------------------ | |
90 | ||
7b4f13e6 MK |
91 | @Override |
92 | public AbstractArrayDefinition createDefinition( | |
93 | IDefinitionScope definitionScope, String fieldName, BitBuffer input) throws CTFReaderException { | |
cc98c947 | 94 | IDefinition lenDef = null; |
7b4f13e6 MK |
95 | |
96 | if (definitionScope != null) { | |
97 | lenDef = definitionScope.lookupDefinition(getLengthName()); | |
98 | } | |
99 | ||
100 | if (lenDef == null) { | |
101 | throw new CTFReaderException("Sequence length field not found"); //$NON-NLS-1$ | |
102 | } | |
103 | ||
104 | if (!(lenDef instanceof IntegerDefinition)) { | |
105 | throw new CTFReaderException("Sequence length field not integer"); //$NON-NLS-1$ | |
106 | } | |
107 | ||
108 | IntegerDefinition lengthDefinition = (IntegerDefinition) lenDef; | |
109 | ||
110 | if (lengthDefinition.getDeclaration().isSigned()) { | |
111 | throw new CTFReaderException("Sequence length must not be signed"); //$NON-NLS-1$ | |
112 | } | |
113 | ||
114 | long length = lengthDefinition.getValue(); | |
115 | if ((length > Integer.MAX_VALUE) || (!input.canRead((int) length * fElemType.getMaximumSize()))) { | |
116 | throw new CTFReaderException("Sequence length too long " + length); //$NON-NLS-1$ | |
117 | } | |
118 | ||
119 | if (isString()) { | |
120 | // Don't create "useless" definitions | |
121 | byte[] data = new byte[(int) length]; | |
122 | input.get(data); | |
123 | return new ByteArrayDefinition(this, definitionScope, fieldName, data); | |
124 | } | |
125 | Collection<String> collection = fPaths.get(fieldName); | |
126 | while (collection.size() < length) { | |
127 | fPaths.put(fieldName, fieldName + '[' + collection.size() + ']'); | |
128 | } | |
129 | List<String> paths = (List<String>) fPaths.get(fieldName); | |
130 | Builder<Definition> definitions = new ImmutableList.Builder<>(); | |
131 | for (int i = 0; i < length; i++) { | |
132 | @SuppressWarnings("null") | |
133 | @NonNull String elemName = paths.get(i); | |
134 | definitions.add(fElemType.createDefinition(definitionScope, elemName, input)); | |
135 | } | |
136 | @SuppressWarnings("null") | |
137 | @NonNull ImmutableList<Definition> build = definitions.build(); | |
138 | return new ArrayDefinition(this, definitionScope, fieldName, build); | |
139 | } | |
140 | ||
141 | @Override | |
142 | public String toString() { | |
143 | /* Only used for debugging */ | |
144 | return "[declaration] sequence[" + Integer.toHexString(hashCode()) + ']'; //$NON-NLS-1$ | |
145 | } | |
146 | ||
147 | @Override | |
148 | public int getMaximumSize() { | |
149 | return Integer.MAX_VALUE; | |
150 | } | |
151 | ||
152 | } |