blob: 5a8706bac0d8c9d6a8e102e243a1812b2f354e0e [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Huberc9410c72016-07-28 12:18:40 -070017#include "EnumType.h"
18
Andreas Huber019d21d2016-10-03 12:59:47 -070019#include "Annotation.h"
Andreas Huber881227d2016-08-02 14:20:21 -070020#include "ScalarType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070021
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070022#include <inttypes.h>
23#include <hidl-util/Formatter.h>
Andreas Huber737080b2016-08-02 15:38:04 -070024#include <android-base/logging.h>
25
Andreas Huberc9410c72016-07-28 12:18:40 -070026namespace android {
27
Andreas Huberc9410c72016-07-28 12:18:40 -070028EnumType::EnumType(
Andreas Huber9ed827c2016-08-22 12:31:13 -070029 const char *localName,
Andreas Huber9ed827c2016-08-22 12:31:13 -070030 Type *storageType)
Yifan Hongf24fa852016-09-23 11:03:15 -070031 : Scope(localName),
32 mValues(),
Andreas Huber881227d2016-08-02 14:20:21 -070033 mStorageType(
34 storageType != NULL
35 ? storageType
36 : new ScalarType(ScalarType::KIND_INT32)) {
Andreas Huberc9410c72016-07-28 12:18:40 -070037}
38
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070039const Type *EnumType::storageType() const {
40 return mStorageType;
41}
42
43const std::vector<EnumValue *> &EnumType::values() const {
Yifan Hongf24fa852016-09-23 11:03:15 -070044 return mValues;
45}
46
47void EnumType::addValue(EnumValue *value) {
48 CHECK(value != nullptr);
49
50 EnumValue *prev = nullptr;
51 std::vector<const EnumType *> chain;
52 getTypeChain(&chain);
53 for (auto it = chain.begin(); it != chain.end(); ++it) {
54 const auto &type = *it;
55 if(!type->values().empty()) {
56 prev = type->values().back();
57 break;
58 }
59 }
60
61 value->autofill(prev, resolveToScalarType());
62 mValues.push_back(value);
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070063}
64
Andreas Huber737080b2016-08-02 15:38:04 -070065const ScalarType *EnumType::resolveToScalarType() const {
66 return mStorageType->resolveToScalarType();
67}
68
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070069bool EnumType::isEnum() const {
70 return true;
71}
72
Steven Moreland979e0992016-09-07 09:18:08 -070073std::string EnumType::getCppType(StorageMode,
74 std::string *extra,
75 bool specifyNamespaces) const {
Andreas Huber881227d2016-08-02 14:20:21 -070076 extra->clear();
77
Steven Moreland979e0992016-09-07 09:18:08 -070078 return specifyNamespaces ? fullName() : partialCppName();
Andreas Huber881227d2016-08-02 14:20:21 -070079}
80
Andreas Huber4c865b72016-09-14 15:26:27 -070081std::string EnumType::getJavaType(
82 std::string *extra, bool forInitializer) const {
83 return mStorageType->resolveToScalarType()->getJavaType(
84 extra, forInitializer);
Andreas Huber2831d512016-08-15 09:33:47 -070085}
86
87std::string EnumType::getJavaSuffix() const {
88 return mStorageType->resolveToScalarType()->getJavaSuffix();
89}
90
Andreas Hubera3558b32016-09-14 09:12:42 -070091std::string EnumType::getJavaWrapperType() const {
92 return mStorageType->resolveToScalarType()->getJavaWrapperType();
93}
94
Yifan Hongf24fa852016-09-23 11:03:15 -070095LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
96 std::vector<const EnumType *> chain;
97 getTypeChain(&chain);
98 for (auto it = chain.begin(); it != chain.end(); ++it) {
99 const auto &type = *it;
100 for(EnumValue *v : type->values()) {
101 if(v->name() == name) {
102 return v;
103 }
104 }
105 }
106 return nullptr;
107}
108
Andreas Huber881227d2016-08-02 14:20:21 -0700109void EnumType::emitReaderWriter(
110 Formatter &out,
111 const std::string &name,
112 const std::string &parcelObj,
113 bool parcelObjIsPointer,
114 bool isReader,
115 ErrorMode mode) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700116 const ScalarType *scalarType = mStorageType->resolveToScalarType();
117 CHECK(scalarType != NULL);
118
119 scalarType->emitReaderWriterWithCast(
120 out,
121 name,
122 parcelObj,
123 parcelObjIsPointer,
124 isReader,
125 mode,
126 true /* needsCast */);
Andreas Huber881227d2016-08-02 14:20:21 -0700127}
128
Andreas Huber85eabdb2016-08-25 11:24:49 -0700129void EnumType::emitJavaFieldReaderWriter(
130 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700131 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700132 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700133 const std::string &blobName,
134 const std::string &fieldName,
135 const std::string &offset,
136 bool isReader) const {
137 return mStorageType->emitJavaFieldReaderWriter(
Andreas Huber709b62d2016-09-19 11:21:18 -0700138 out, depth, parcelName, blobName, fieldName, offset, isReader);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700139}
140
Andreas Huber881227d2016-08-02 14:20:21 -0700141status_t EnumType::emitTypeDeclarations(Formatter &out) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700142 const ScalarType *scalarType = mStorageType->resolveToScalarType();
143 CHECK(scalarType != NULL);
144
Andreas Huber881227d2016-08-02 14:20:21 -0700145 std::string extra;
146
147 out << "enum class "
Andreas Huber0e00de42016-08-03 09:56:02 -0700148 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700149 << " : "
Andreas Huber737080b2016-08-02 15:38:04 -0700150 << ((Type *)scalarType)->getCppType(&extra)
Andreas Huber881227d2016-08-02 14:20:21 -0700151 << " {\n";
152
153 out.indent();
154
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700155 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700156 getTypeChain(&chain);
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700157
158 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
159 const auto &type = *it;
160
161 for (const auto &entry : type->values()) {
162 out << entry->name();
163
Yifan Hongfc610cd2016-09-22 13:34:45 -0700164 std::string value = entry->cppValue(scalarType->getKind());
Yifan Hongf24fa852016-09-23 11:03:15 -0700165 CHECK(!value.empty()); // use autofilled values for c++.
166 out << " = " << value;
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700167
Yifan Hong57886972016-08-17 10:42:15 -0700168 out << ",";
169
Yifan Hongfc610cd2016-09-22 13:34:45 -0700170 std::string comment = entry->comment();
171 if (!comment.empty() && comment != value) {
Yifan Hong57886972016-08-17 10:42:15 -0700172 out << " // " << comment;
173 }
174
175 out << "\n";
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700176 }
Andreas Huber881227d2016-08-02 14:20:21 -0700177 }
178
179 out.unindent();
180 out << "};\n\n";
181
182 return OK;
183}
184
Andreas Huber85eabdb2016-08-25 11:24:49 -0700185status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool) const {
Andreas Huber2831d512016-08-15 09:33:47 -0700186 const ScalarType *scalarType = mStorageType->resolveToScalarType();
187 CHECK(scalarType != NULL);
188
189 out << "public final class "
190 << localName()
191 << " {\n";
192
193 out.indent();
194
Andreas Huber4c865b72016-09-14 15:26:27 -0700195 std::string extra; // unused, because ScalarType leaves this empty.
196 const std::string typeName =
197 scalarType->getJavaType(&extra, false /* forInitializer */);
Andreas Huber2831d512016-08-15 09:33:47 -0700198
199 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700200 getTypeChain(&chain);
Andreas Huber2831d512016-08-15 09:33:47 -0700201
202 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
203 const auto &type = *it;
204
205 for (const auto &entry : type->values()) {
206 out << "public static final "
207 << typeName
208 << " "
Andreas Huberab647c02016-09-14 09:44:00 -0700209 << entry->name()
210 << " = ";
Andreas Huber2831d512016-08-15 09:33:47 -0700211
Yifan Hongf24fa852016-09-23 11:03:15 -0700212 // javaValue will make the number signed.
Yifan Hongfc610cd2016-09-22 13:34:45 -0700213 std::string value = entry->javaValue(scalarType->getKind());
Yifan Hongf24fa852016-09-23 11:03:15 -0700214 CHECK(!value.empty()); // use autofilled values for java.
215 out << value;
Andreas Huber2831d512016-08-15 09:33:47 -0700216
Yifan Hong19ca75a2016-08-31 10:20:03 -0700217 out << ";";
218
Yifan Hongfc610cd2016-09-22 13:34:45 -0700219 std::string comment = entry->comment();
220 if (!comment.empty() && comment != value) {
Yifan Hong19ca75a2016-08-31 10:20:03 -0700221 out << " // " << comment;
222 }
223
224 out << "\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700225 }
226 }
227
228 out.unindent();
229 out << "};\n\n";
230
231 return OK;
232}
233
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700234status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700235 out << "name: \"" << localName() << "\"\n"
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700236 << "type: TYPE_ENUM\n"
237 << "enum_value: {\n";
238 out.indent();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700239
240 std::vector<const EnumType *> chain;
241 getTypeChain(&chain);
242
243 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
244 const auto &type = *it;
245
246 for (const auto &entry : type->values()) {
247 out << "enumerator: \"" << entry->name() << "\"\n";
248
Yifan Hongf24fa852016-09-23 11:03:15 -0700249 if (!entry->isAutoFill()) {
250 // don't autofill values for vts.
251 std::string value = entry->value();
252 CHECK(!value.empty());
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700253 out << "value: " << value << "\n";
254 }
255 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700256 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700257
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700258 out.unindent();
259 out << "}\n";
260 return OK;
261}
262
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700263status_t EnumType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang19933522016-08-29 15:06:38 -0700264 out << "type: TYPE_ENUM\n"
265 << "predefined_type: \""
266 << localName()
267 << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700268 return OK;
269}
270
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700271void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
272 out->clear();
273 const EnumType *type = this;
274 for (;;) {
275 out->push_back(type);
276
277 const Type *superType = type->storageType();
278 if (superType == NULL || !superType->isEnum()) {
279 break;
280 }
281
282 type = static_cast<const EnumType *>(superType);
283 }
284}
285
Andreas Huber85eabdb2016-08-25 11:24:49 -0700286void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
287 mStorageType->getAlignmentAndSize(align, size);
288}
289
Andreas Huber019d21d2016-10-03 12:59:47 -0700290const Annotation *EnumType::findExportAnnotation() const {
291 for (const auto &annotation : annotations()) {
292 if (annotation->name() == "export") {
293 return annotation;
294 }
295 }
296
297 return nullptr;
298}
299
300void EnumType::appendToExportedTypesVector(
301 std::vector<const Type *> *exportedTypes) const {
302 if (findExportAnnotation() != nullptr) {
303 exportedTypes->push_back(this);
304 }
305}
306
307status_t EnumType::emitExportedHeader(Formatter &out) const {
308 const Annotation *annotation = findExportAnnotation();
309 CHECK(annotation != nullptr);
310
311 std::string name = localName();
312
313 const AnnotationParam *nameParam = annotation->getParam("name");
314 if (nameParam != nullptr) {
315 CHECK_EQ(nameParam->getValues()->size(), 1u);
316
317 std::string quotedString = nameParam->getValues()->at(0);
318 name = quotedString.substr(1, quotedString.size() - 2);
319 }
320
321 const ScalarType *scalarType = mStorageType->resolveToScalarType();
322 CHECK(scalarType != NULL);
323
324 std::string extra;
325
326 if (!name.empty()) {
327 out << "typedef ";
328 }
329
330 out << "enum {\n";
331
332 out.indent();
333
334 std::vector<const EnumType *> chain;
335 getTypeChain(&chain);
336
337 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
338 const auto &type = *it;
339
340 for (const auto &entry : type->values()) {
341 out << entry->name();
342
343 std::string value = entry->cppValue(scalarType->getKind());
344 CHECK(!value.empty()); // use autofilled values for c++.
345 out << " = " << value;
346
347 out << ",";
348
349 std::string comment = entry->comment();
350 if (!comment.empty() && comment != value) {
351 out << " // " << comment;
352 }
353
354 out << "\n";
355 }
356 }
357
358 out.unindent();
359 out << "}";
360
361 if (!name.empty()) {
362 out << " " << name;
363 }
364
365 out << ";\n\n";
366
367 return OK;
368}
369
Andreas Huber31629bc2016-08-03 09:06:40 -0700370////////////////////////////////////////////////////////////////////////////////
371
Yifan Hongf24fa852016-09-23 11:03:15 -0700372EnumValue::EnumValue(const char *name, ConstantExpression *value)
Andreas Huber31629bc2016-08-03 09:06:40 -0700373 : mName(name),
Yifan Hongf24fa852016-09-23 11:03:15 -0700374 mValue(value),
375 mIsAutoFill(false) {
Andreas Huber31629bc2016-08-03 09:06:40 -0700376}
377
378std::string EnumValue::name() const {
379 return mName;
380}
381
Yifan Hongfc610cd2016-09-22 13:34:45 -0700382std::string EnumValue::value() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700383 CHECK(mValue != nullptr);
384 return mValue->value();
Yifan Hong57886972016-08-17 10:42:15 -0700385}
386
Yifan Hongfc610cd2016-09-22 13:34:45 -0700387std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700388 CHECK(mValue != nullptr);
389 return mValue->cppValue(castKind);
Yifan Hong57886972016-08-17 10:42:15 -0700390}
Yifan Hongfc610cd2016-09-22 13:34:45 -0700391std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700392 CHECK(mValue != nullptr);
393 return mValue->javaValue(castKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700394}
Yifan Hong57886972016-08-17 10:42:15 -0700395
Yifan Hongfc610cd2016-09-22 13:34:45 -0700396std::string EnumValue::comment() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700397 CHECK(mValue != nullptr);
398 return mValue->description();
399}
400
401ConstantExpression *EnumValue::constExpr() const {
402 CHECK(mValue != nullptr);
403 return mValue;
404}
405
406void EnumValue::autofill(const EnumValue *prev, const ScalarType *type) {
407 if(mValue != nullptr)
408 return;
409 mIsAutoFill = true;
410 ConstantExpression *value = new ConstantExpression();
411 if(prev == nullptr) {
412 *value = ConstantExpression::Zero(type->getKind());
413 } else {
414 CHECK(prev->mValue != nullptr);
415 *value = prev->mValue->addOne();
416 }
417 mValue = value;
418}
419
420bool EnumValue::isAutoFill() const {
421 return mIsAutoFill;
422}
423
424bool EnumValue::isEnumValue() const {
425 return true;
Andreas Huber31629bc2016-08-03 09:06:40 -0700426}
427
Andreas Huberc9410c72016-07-28 12:18:40 -0700428} // namespace android
429