Commit | Line | Data |
---|---|---|
866e5b51 | 1 | /******************************************************************************* |
60ae41e1 | 2 | * Copyright (c) 2011, 2013 Ericsson, Ecole Polytechnique de Montreal and others |
866e5b51 FC |
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 | * Contributors: Simon Marchi - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
13 | package org.eclipse.linuxtools.ctf.core.event.types; | |
14 | ||
a4fa4e36 MK |
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.trace.CTFReaderException; | |
21 | ||
22 | import com.google.common.collect.ArrayListMultimap; | |
23 | import com.google.common.collect.ImmutableList; | |
24 | import com.google.common.collect.ImmutableList.Builder; | |
25 | import com.google.common.collect.Multimap; | |
26 | ||
866e5b51 | 27 | /** |
d37aaa7f FC |
28 | * A CTF array declaration |
29 | * | |
9639bf3a MK |
30 | * Arrays are fixed-length. Their length is declared in the type declaration |
31 | * within the meta-data. They contain an array of "inner type" elements, which | |
32 | * can refer to any type not containing the type of the array being declared (no | |
33 | * circular dependency). The length is the number of elements in an array. | |
d37aaa7f FC |
34 | * |
35 | * @version 1.0 | |
36 | * @author Matthew Khouzam | |
37 | * @author Simon Marchi | |
866e5b51 | 38 | */ |
a4fa4e36 | 39 | public class ArrayDeclaration extends Declaration { |
866e5b51 FC |
40 | |
41 | // ------------------------------------------------------------------------ | |
42 | // Attributes | |
43 | // ------------------------------------------------------------------------ | |
44 | ||
a4fa4e36 MK |
45 | private final int fLength; |
46 | private final IDeclaration fElemType; | |
47 | ||
48 | /** | |
49 | * <pre> | |
50 | * Cache where we can pre-generate the children names | |
51 | * Key: parent name | |
52 | * Value: children names | |
53 | * ex: field → {field[0], field[1], … field[n]} | |
54 | * </pre> | |
55 | * | |
56 | * TODO: investigate performance | |
57 | */ | |
58 | private final Multimap<String, String> fChildrenNames = ArrayListMultimap.<String, String> create(); | |
866e5b51 FC |
59 | |
60 | // ------------------------------------------------------------------------ | |
61 | // Constructors | |
62 | // ------------------------------------------------------------------------ | |
63 | ||
9ac2eb62 MK |
64 | /** |
65 | * Constructor | |
9639bf3a MK |
66 | * |
67 | * @param length | |
68 | * how many elements in the array | |
69 | * @param elemType | |
70 | * what type of element is in the array | |
9ac2eb62 | 71 | */ |
866e5b51 | 72 | public ArrayDeclaration(int length, IDeclaration elemType) { |
a4fa4e36 MK |
73 | fLength = length; |
74 | fElemType = elemType; | |
866e5b51 FC |
75 | } |
76 | ||
77 | // ------------------------------------------------------------------------ | |
78 | // Getters/Setters/Predicates | |
79 | // ------------------------------------------------------------------------ | |
80 | ||
9ac2eb62 MK |
81 | /** |
82 | * | |
83 | * @return the type of element in the array | |
84 | */ | |
866e5b51 | 85 | public IDeclaration getElementType() { |
a4fa4e36 | 86 | return fElemType; |
866e5b51 FC |
87 | } |
88 | ||
9ac2eb62 MK |
89 | /** |
90 | * | |
91 | * @return how many elements in the array | |
92 | */ | |
866e5b51 | 93 | public int getLength() { |
a4fa4e36 | 94 | return fLength; |
866e5b51 FC |
95 | } |
96 | ||
9639bf3a MK |
97 | /** |
98 | * Sometimes, strings are encoded as an array of 1-byte integers (each one | |
99 | * being an UTF-8 byte). | |
100 | * | |
101 | * @return true if this array is in fact an UTF-8 string. false if it's a | |
102 | * "normal" array of generic Definition's. | |
103 | * @since 3.0 | |
104 | */ | |
105 | public boolean isString() { | |
a4fa4e36 | 106 | if (fElemType instanceof IntegerDeclaration) { |
9639bf3a MK |
107 | /* |
108 | * If the first byte is a "character", we'll consider the whole | |
109 | * array a character string. | |
110 | */ | |
a4fa4e36 | 111 | IntegerDeclaration elemInt = (IntegerDeclaration) fElemType; |
9639bf3a MK |
112 | if (elemInt.isCharacter()) { |
113 | return true; | |
114 | } | |
115 | } | |
116 | return false; | |
117 | } | |
118 | ||
fd74e6c1 MK |
119 | @Override |
120 | public long getAlignment() { | |
0594c61c | 121 | return getElementType().getAlignment(); |
fd74e6c1 | 122 | } |
9639bf3a | 123 | |
866e5b51 FC |
124 | // ------------------------------------------------------------------------ |
125 | // Operations | |
126 | // ------------------------------------------------------------------------ | |
127 | ||
a4fa4e36 MK |
128 | /** |
129 | * @since 3.0 | |
130 | */ | |
866e5b51 FC |
131 | @Override |
132 | public ArrayDefinition createDefinition(IDefinitionScope definitionScope, | |
a4fa4e36 MK |
133 | @NonNull String fieldName, BitBuffer input) throws CTFReaderException { |
134 | alignRead(input); | |
135 | List<Definition> definitions = read(input, definitionScope, fieldName); | |
136 | return new ArrayDefinition(this, definitionScope, fieldName, definitions); | |
866e5b51 FC |
137 | } |
138 | ||
139 | @Override | |
140 | public String toString() { | |
141 | /* Only used for debugging */ | |
142 | return "[declaration] array[" + Integer.toHexString(hashCode()) + ']'; //$NON-NLS-1$ | |
143 | } | |
144 | ||
a4fa4e36 MK |
145 | @NonNull |
146 | private List<Definition> read(@NonNull BitBuffer input, IDefinitionScope definitionScope, String fieldName) throws CTFReaderException { | |
147 | Builder<Definition> definitions = new ImmutableList.Builder<>(); | |
148 | if (!fChildrenNames.containsKey(fieldName)) { | |
149 | for (int i = 0; i < fLength; i++) { | |
150 | fChildrenNames.put(fieldName, fieldName + '[' + i + ']'); | |
151 | } | |
152 | } | |
153 | List<String> elemNames = (List<String>) fChildrenNames.get(fieldName); | |
154 | for (int i = 0; i < fLength; i++) { | |
155 | String name = elemNames.get(i); | |
156 | if (name == null) { | |
157 | throw new IllegalStateException(); | |
158 | } | |
159 | definitions.add(fElemType.createDefinition(definitionScope, name, input)); | |
160 | } | |
161 | @SuppressWarnings("null") | |
162 | @NonNull ImmutableList<Definition> ret = definitions.build(); | |
163 | return ret; | |
164 | } | |
165 | ||
166 | /** | |
167 | * @since 3.0 | |
168 | */ | |
169 | @Override | |
170 | public int getMaximumSize() { | |
171 | long val = (long) fLength * fElemType.getMaximumSize(); | |
172 | return (int) Math.min(Integer.MAX_VALUE, val); | |
173 | } | |
174 | ||
866e5b51 | 175 | } |