Commit | Line | Data |
---|---|---|
866e5b51 | 1 | /******************************************************************************* |
60ae41e1 | 2 | * Copyright (c) 2011, 2014 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 | ||
f357bcd4 | 13 | package org.eclipse.tracecompass.ctf.core.event.types; |
866e5b51 | 14 | |
a4fa4e36 MK |
15 | import java.util.Collections; |
16 | import java.util.LinkedList; | |
2b7f6f09 | 17 | import java.util.List; |
843f986b | 18 | import java.util.Map; |
866e5b51 | 19 | |
a4fa4e36 | 20 | import org.eclipse.jdt.annotation.NonNull; |
f357bcd4 | 21 | import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope; |
fbe6fa6f | 22 | import org.eclipse.tracecompass.ctf.core.event.scope.ILexicalScope; |
5b341dc8 | 23 | import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration.InternalDef; |
a4fa4e36 MK |
24 | |
25 | import com.google.common.base.Joiner; | |
26 | import com.google.common.collect.ImmutableList; | |
27 | import com.google.common.collect.ImmutableMap; | |
28 | import com.google.common.collect.ImmutableMap.Builder; | |
866e5b51 FC |
29 | |
30 | /** | |
d37aaa7f | 31 | * A CTF structure definition (similar to a C structure). |
486efb2e | 32 | * |
d37aaa7f FC |
33 | * A structure is similar to a C structure, it is a compound data type that |
34 | * contains other datatypes in fields. they are stored in an hashmap and indexed | |
35 | * by names which are strings. | |
36 | * | |
6c7592e1 MK |
37 | * TODO: move me to internal |
38 | * | |
d37aaa7f FC |
39 | * @version 1.0 |
40 | * @author Matthew Khouzam | |
41 | * @author Simon Marchi | |
866e5b51 | 42 | */ |
009883d7 | 43 | public final class StructDefinition extends ScopedDefinition implements ICompositeDefinition { |
866e5b51 FC |
44 | |
45 | // ------------------------------------------------------------------------ | |
46 | // Attributes | |
47 | // ------------------------------------------------------------------------ | |
48 | ||
367e2932 | 49 | private final @NonNull List<@NonNull String> fFieldNames; |
a4fa4e36 MK |
50 | private final Definition[] fDefinitions; |
51 | private Map<String, Definition> fDefinitionsMap = null; | |
866e5b51 FC |
52 | |
53 | // ------------------------------------------------------------------------ | |
54 | // Constructors | |
55 | // ------------------------------------------------------------------------ | |
56 | ||
9ac2eb62 MK |
57 | /** |
58 | * Constructor | |
59 | * | |
60 | * @param declaration | |
61 | * the parent declaration | |
62 | * @param definitionScope | |
63 | * the parent scope | |
be6df2d8 | 64 | * @param structFieldName |
9ac2eb62 | 65 | * the field name |
a4fa4e36 MK |
66 | * @param definitions |
67 | * the definitions | |
8e0c9d81 | 68 | * @since 1.0 |
9ac2eb62 | 69 | */ |
a4fa4e36 | 70 | public StructDefinition(@NonNull StructDeclaration declaration, |
2db699c2 AM |
71 | IDefinitionScope definitionScope, |
72 | @NonNull String structFieldName, | |
2db699c2 | 73 | Definition[] definitions) { |
a4fa4e36 | 74 | super(declaration, definitionScope, structFieldName); |
8e0c9d81 | 75 | fFieldNames = ImmutableList.copyOf(declaration.getFieldsList()); |
a4fa4e36 | 76 | fDefinitions = definitions; |
70f60307 MK |
77 | if (fFieldNames.isEmpty()) { |
78 | fDefinitionsMap = Collections.EMPTY_MAP; | |
79 | } | |
80 | } | |
81 | ||
82 | /** | |
83 | * Constructor This one takes the scope and thus speeds up definition | |
84 | * creation | |
85 | * | |
86 | * @param declaration | |
87 | * the parent declaration | |
88 | * @param definitionScope | |
89 | * the parent scope | |
90 | * @param scope | |
91 | * the scope of this variable | |
92 | * @param structFieldName | |
93 | * the field name | |
94 | * @param fieldNames | |
95 | * the list of fields | |
96 | * @param definitions | |
97 | * the definitions | |
fbe6fa6f | 98 | * @since 1.0 |
70f60307 MK |
99 | */ |
100 | public StructDefinition(@NonNull StructDeclaration declaration, | |
367e2932 AM |
101 | IDefinitionScope definitionScope, |
102 | @NonNull ILexicalScope scope, | |
103 | @NonNull String structFieldName, | |
104 | @NonNull Iterable<@NonNull String> fieldNames, | |
105 | Definition[] definitions) { | |
70f60307 MK |
106 | super(declaration, definitionScope, structFieldName, scope); |
107 | fFieldNames = ImmutableList.copyOf(fieldNames); | |
108 | fDefinitions = definitions; | |
009883d7 | 109 | if (fFieldNames.isEmpty()) { |
a4fa4e36 | 110 | fDefinitionsMap = Collections.EMPTY_MAP; |
866e5b51 FC |
111 | } |
112 | } | |
113 | ||
114 | // ------------------------------------------------------------------------ | |
115 | // Getters/Setters/Predicates | |
116 | // ------------------------------------------------------------------------ | |
117 | ||
009883d7 | 118 | @Override |
a4fa4e36 MK |
119 | public Definition getDefinition(String fieldName) { |
120 | if (fDefinitionsMap == null) { | |
2db699c2 AM |
121 | /* Build the definitions map */ |
122 | Builder<String, Definition> mapBuilder = new ImmutableMap.Builder<>(); | |
123 | for (int i = 0; i < fFieldNames.size(); i++) { | |
124 | if (fDefinitions[i] != null) { | |
125 | mapBuilder.put(fFieldNames.get(i), fDefinitions[i]); | |
126 | } | |
a4fa4e36 | 127 | } |
2db699c2 | 128 | fDefinitionsMap = mapBuilder.build(); |
a4fa4e36 | 129 | } |
2db699c2 | 130 | return fDefinitionsMap.get(fieldName); |
a4fa4e36 MK |
131 | } |
132 | ||
009883d7 | 133 | @Override |
367e2932 | 134 | public @NonNull List<@NonNull String> getFieldNames() { |
a4fa4e36 | 135 | return fFieldNames; |
866e5b51 FC |
136 | } |
137 | ||
9ac2eb62 | 138 | @Override |
866e5b51 | 139 | public StructDeclaration getDeclaration() { |
a4fa4e36 | 140 | return (StructDeclaration) super.getDeclaration(); |
866e5b51 FC |
141 | } |
142 | ||
143 | // ------------------------------------------------------------------------ | |
144 | // Operations | |
145 | // ------------------------------------------------------------------------ | |
146 | ||
866e5b51 FC |
147 | @Override |
148 | public Definition lookupDefinition(String lookupPath) { | |
5b341dc8 | 149 | return lookupDefinition(lookupPath, null); |
866e5b51 FC |
150 | } |
151 | ||
866e5b51 FC |
152 | @Override |
153 | public String toString() { | |
154 | StringBuilder builder = new StringBuilder(); | |
155 | ||
419f09a8 | 156 | builder.append("{ "); //$NON-NLS-1$ |
866e5b51 | 157 | |
aa353506 AM |
158 | List<String> fields = new LinkedList<>(); |
159 | for (String field : fFieldNames) { | |
160 | String appendee = field + " = " + lookupDefinition(field).toString(); //$NON-NLS-1$ | |
161 | fields.add(appendee); | |
866e5b51 | 162 | } |
aa353506 AM |
163 | Joiner joiner = Joiner.on(", ").skipNulls(); //$NON-NLS-1$ |
164 | builder.append(joiner.join(fields)); | |
866e5b51 | 165 | |
419f09a8 | 166 | builder.append(" }"); //$NON-NLS-1$ |
866e5b51 FC |
167 | |
168 | return builder.toString(); | |
169 | } | |
a4fa4e36 | 170 | |
5b341dc8 MK |
171 | /** |
172 | * Lookup definition while exclusing the caller | |
173 | * | |
174 | * @param lookupPath | |
175 | * the path to lookup | |
176 | * @param defintionToExclude | |
177 | * the definition to exclude, can be null | |
178 | * @return the definition or null | |
0336f981 | 179 | * @since 1.1 |
5b341dc8 MK |
180 | */ |
181 | public Definition lookupDefinition(String lookupPath, ScopedDefinition defintionToExclude) { | |
182 | /* | |
183 | * The fields are created in order of appearance, so if a variant or | |
184 | * sequence refers to a field that is after it, the field's definition | |
185 | * will not be there yet in the hashmap. | |
186 | */ | |
187 | int val = fFieldNames.indexOf(lookupPath); | |
188 | if (val != -1) { | |
189 | return fDefinitions[val]; | |
190 | } | |
191 | String lookupUnderscored = "_" + lookupPath; //$NON-NLS-1$ | |
192 | val = fFieldNames.indexOf(lookupUnderscored); | |
193 | if (val != -1) { | |
194 | return fDefinitions[val]; | |
195 | } | |
196 | for (IDefinition child : fDefinitions) { | |
197 | if (child instanceof ScopedDefinition) { | |
198 | if (!child.equals(defintionToExclude)) { | |
199 | IDefinition def = ((ScopedDefinition) child).lookupDefinition(lookupPath); | |
200 | if (def instanceof Definition) { | |
201 | return (Definition) def; | |
202 | } | |
203 | } | |
204 | } | |
205 | } | |
206 | if (getDefinitionScope() instanceof InternalDef) { | |
207 | return (Definition) ((InternalDef) getDefinitionScope()).lookupDefinitionBreakLoop(lookupPath); | |
208 | } | |
209 | return (Definition) getDefinitionScope().lookupDefinition(lookupPath); | |
210 | } | |
211 | ||
866e5b51 | 212 | } |