blob: 4a25bbe9eb068a04e249b37f948e002406a91ab1 [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,
Yifan Honga4b53d02016-10-31 17:29:10 -070030 const Location &location,
Andreas Huber9ed827c2016-08-22 12:31:13 -070031 Type *storageType)
Yifan Honga4b53d02016-10-31 17:29:10 -070032 : Scope(localName, location),
Yifan Hongf24fa852016-09-23 11:03:15 -070033 mValues(),
Andreas Huber881227d2016-08-02 14:20:21 -070034 mStorageType(
35 storageType != NULL
36 ? storageType
37 : new ScalarType(ScalarType::KIND_INT32)) {
Andreas Huberc9410c72016-07-28 12:18:40 -070038}
39
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070040const Type *EnumType::storageType() const {
41 return mStorageType;
42}
43
44const std::vector<EnumValue *> &EnumType::values() const {
Yifan Hongf24fa852016-09-23 11:03:15 -070045 return mValues;
46}
47
48void EnumType::addValue(EnumValue *value) {
49 CHECK(value != nullptr);
50
51 EnumValue *prev = nullptr;
52 std::vector<const EnumType *> chain;
53 getTypeChain(&chain);
54 for (auto it = chain.begin(); it != chain.end(); ++it) {
55 const auto &type = *it;
56 if(!type->values().empty()) {
57 prev = type->values().back();
58 break;
59 }
60 }
61
62 value->autofill(prev, resolveToScalarType());
63 mValues.push_back(value);
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070064}
65
Andreas Huber737080b2016-08-02 15:38:04 -070066const ScalarType *EnumType::resolveToScalarType() const {
67 return mStorageType->resolveToScalarType();
68}
69
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070070bool EnumType::isEnum() const {
71 return true;
72}
73
Steven Moreland979e0992016-09-07 09:18:08 -070074std::string EnumType::getCppType(StorageMode,
Steven Moreland979e0992016-09-07 09:18:08 -070075 bool specifyNamespaces) const {
Steven Moreland979e0992016-09-07 09:18:08 -070076 return specifyNamespaces ? fullName() : partialCppName();
Andreas Huber881227d2016-08-02 14:20:21 -070077}
78
Andreas Huber4c865b72016-09-14 15:26:27 -070079std::string EnumType::getJavaType(
80 std::string *extra, bool forInitializer) const {
81 return mStorageType->resolveToScalarType()->getJavaType(
82 extra, forInitializer);
Andreas Huber2831d512016-08-15 09:33:47 -070083}
84
85std::string EnumType::getJavaSuffix() const {
86 return mStorageType->resolveToScalarType()->getJavaSuffix();
87}
88
Andreas Hubera3558b32016-09-14 09:12:42 -070089std::string EnumType::getJavaWrapperType() const {
90 return mStorageType->resolveToScalarType()->getJavaWrapperType();
91}
92
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -070093std::string EnumType::getVtsType() const {
94 return "TYPE_ENUM";
95}
96
Yifan Hongf24fa852016-09-23 11:03:15 -070097LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
98 std::vector<const EnumType *> chain;
99 getTypeChain(&chain);
100 for (auto it = chain.begin(); it != chain.end(); ++it) {
101 const auto &type = *it;
102 for(EnumValue *v : type->values()) {
103 if(v->name() == name) {
104 return v;
105 }
106 }
107 }
108 return nullptr;
109}
110
Andreas Huber881227d2016-08-02 14:20:21 -0700111void EnumType::emitReaderWriter(
112 Formatter &out,
113 const std::string &name,
114 const std::string &parcelObj,
115 bool parcelObjIsPointer,
116 bool isReader,
117 ErrorMode mode) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700118 const ScalarType *scalarType = mStorageType->resolveToScalarType();
119 CHECK(scalarType != NULL);
120
121 scalarType->emitReaderWriterWithCast(
122 out,
123 name,
124 parcelObj,
125 parcelObjIsPointer,
126 isReader,
127 mode,
128 true /* needsCast */);
Andreas Huber881227d2016-08-02 14:20:21 -0700129}
130
Andreas Huber85eabdb2016-08-25 11:24:49 -0700131void EnumType::emitJavaFieldReaderWriter(
132 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700133 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700134 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700135 const std::string &blobName,
136 const std::string &fieldName,
137 const std::string &offset,
138 bool isReader) const {
139 return mStorageType->emitJavaFieldReaderWriter(
Andreas Huber709b62d2016-09-19 11:21:18 -0700140 out, depth, parcelName, blobName, fieldName, offset, isReader);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700141}
142
Andreas Huber881227d2016-08-02 14:20:21 -0700143status_t EnumType::emitTypeDeclarations(Formatter &out) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700144 const ScalarType *scalarType = mStorageType->resolveToScalarType();
Andreas Hubere3f769a2016-10-10 10:54:44 -0700145 CHECK(scalarType != nullptr);
Andreas Huber737080b2016-08-02 15:38:04 -0700146
Yifan Hong3b320f82016-11-01 15:15:54 -0700147 const std::string storageType = scalarType->getCppStackType();
Andreas Huber881227d2016-08-02 14:20:21 -0700148
149 out << "enum class "
Andreas Huber0e00de42016-08-03 09:56:02 -0700150 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700151 << " : "
Andreas Hubere3f769a2016-10-10 10:54:44 -0700152 << storageType
Andreas Huber881227d2016-08-02 14:20:21 -0700153 << " {\n";
154
155 out.indent();
156
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700157 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700158 getTypeChain(&chain);
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700159
160 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
161 const auto &type = *it;
162
163 for (const auto &entry : type->values()) {
164 out << entry->name();
165
Yifan Hongfc610cd2016-09-22 13:34:45 -0700166 std::string value = entry->cppValue(scalarType->getKind());
Yifan Hongf24fa852016-09-23 11:03:15 -0700167 CHECK(!value.empty()); // use autofilled values for c++.
168 out << " = " << value;
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700169
Yifan Hong57886972016-08-17 10:42:15 -0700170 out << ",";
171
Yifan Hongfc610cd2016-09-22 13:34:45 -0700172 std::string comment = entry->comment();
173 if (!comment.empty() && comment != value) {
Yifan Hong57886972016-08-17 10:42:15 -0700174 out << " // " << comment;
175 }
176
177 out << "\n";
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700178 }
Andreas Huber881227d2016-08-02 14:20:21 -0700179 }
180
181 out.unindent();
182 out << "};\n\n";
183
184 return OK;
185}
186
Andreas Hubere3f769a2016-10-10 10:54:44 -0700187void EnumType::emitEnumBitwiseOrOperator(Formatter &out, bool mutating) const {
188 const ScalarType *scalarType = mStorageType->resolveToScalarType();
189 CHECK(scalarType != nullptr);
190
Yifan Hong3b320f82016-11-01 15:15:54 -0700191 const std::string storageType = scalarType->getCppStackType();
Andreas Hubere3f769a2016-10-10 10:54:44 -0700192
193 out << "inline "
194 << fullName()
195 << (mutating ? " &" : "")
196 << " operator|"
197 << (mutating ? "=" : "")
198 << "(\n";
199
200 out.indent();
201 out.indent();
202
203 out << fullName()
204 << (mutating ? " &" : " ")
205 << "lhs, "
206 << fullName()
207 << " rhs) {\n";
208 out.unindent();
209
210 if (mutating) {
211 out << "lhs = ";
212 } else {
213 out << "return ";
214 }
215 out << "static_cast<"
216 << fullName()
217 << ">(\n";
218 out.indent();
219 out.indent();
220 out << "static_cast<"
221 << storageType
222 << ">(lhs) | static_cast<"
223 << storageType
224 << ">(rhs));\n";
225 out.unindent();
226 out.unindent();
227
228 if (mutating) {
229 out << "return lhs;\n";
230 }
231
232 out.unindent();
233
234 out << "}\n\n";
235}
236
237status_t EnumType::emitGlobalTypeDeclarations(Formatter &out) const {
238 emitEnumBitwiseOrOperator(out, false /* mutating */);
239 emitEnumBitwiseOrOperator(out, true /* mutating */);
240
241 return OK;
242}
243
Andreas Huber85eabdb2016-08-25 11:24:49 -0700244status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool) const {
Andreas Huber2831d512016-08-15 09:33:47 -0700245 const ScalarType *scalarType = mStorageType->resolveToScalarType();
246 CHECK(scalarType != NULL);
247
248 out << "public final class "
249 << localName()
250 << " {\n";
251
252 out.indent();
253
Andreas Huber4c865b72016-09-14 15:26:27 -0700254 std::string extra; // unused, because ScalarType leaves this empty.
255 const std::string typeName =
256 scalarType->getJavaType(&extra, false /* forInitializer */);
Andreas Huber2831d512016-08-15 09:33:47 -0700257
258 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700259 getTypeChain(&chain);
Andreas Huber2831d512016-08-15 09:33:47 -0700260
261 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
262 const auto &type = *it;
263
264 for (const auto &entry : type->values()) {
265 out << "public static final "
266 << typeName
267 << " "
Andreas Huberab647c02016-09-14 09:44:00 -0700268 << entry->name()
269 << " = ";
Andreas Huber2831d512016-08-15 09:33:47 -0700270
Yifan Hongf24fa852016-09-23 11:03:15 -0700271 // javaValue will make the number signed.
Yifan Hongfc610cd2016-09-22 13:34:45 -0700272 std::string value = entry->javaValue(scalarType->getKind());
Yifan Hongf24fa852016-09-23 11:03:15 -0700273 CHECK(!value.empty()); // use autofilled values for java.
274 out << value;
Andreas Huber2831d512016-08-15 09:33:47 -0700275
Yifan Hong19ca75a2016-08-31 10:20:03 -0700276 out << ";";
277
Yifan Hongfc610cd2016-09-22 13:34:45 -0700278 std::string comment = entry->comment();
279 if (!comment.empty() && comment != value) {
Yifan Hong19ca75a2016-08-31 10:20:03 -0700280 out << " // " << comment;
281 }
282
283 out << "\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700284 }
285 }
286
287 out.unindent();
288 out << "};\n\n";
289
290 return OK;
291}
292
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700293status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700294 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700295 out << "type: " << getVtsType() << "\n";
296 out << "enum_value: {\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700297 out.indent();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700298
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700299 out << "scalar_type: \""
300 << mStorageType->resolveToScalarType()->getVtsScalarType()
301 << "\"\n\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700302 std::vector<const EnumType *> chain;
303 getTypeChain(&chain);
304
305 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
306 const auto &type = *it;
307
308 for (const auto &entry : type->values()) {
309 out << "enumerator: \"" << entry->name() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700310 out << "scalar_value: {\n";
311 out.indent();
Yifan Hongf24fa852016-09-23 11:03:15 -0700312 if (!entry->isAutoFill()) {
313 // don't autofill values for vts.
314 std::string value = entry->value();
315 CHECK(!value.empty());
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700316 out << mStorageType->resolveToScalarType()->getVtsScalarType()
317 << ": "
318 << value
319 << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700320 }
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700321 out.unindent();
322 out << "}\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700323 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700324 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700325
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700326 out.unindent();
327 out << "}\n";
328 return OK;
329}
330
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700331status_t EnumType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700332 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700333 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700334 return OK;
335}
336
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700337void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
338 out->clear();
339 const EnumType *type = this;
340 for (;;) {
341 out->push_back(type);
342
343 const Type *superType = type->storageType();
344 if (superType == NULL || !superType->isEnum()) {
345 break;
346 }
347
348 type = static_cast<const EnumType *>(superType);
349 }
350}
351
Andreas Huber85eabdb2016-08-25 11:24:49 -0700352void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
353 mStorageType->getAlignmentAndSize(align, size);
354}
355
Andreas Huber019d21d2016-10-03 12:59:47 -0700356const Annotation *EnumType::findExportAnnotation() const {
357 for (const auto &annotation : annotations()) {
358 if (annotation->name() == "export") {
359 return annotation;
360 }
361 }
362
363 return nullptr;
364}
365
366void EnumType::appendToExportedTypesVector(
367 std::vector<const Type *> *exportedTypes) const {
368 if (findExportAnnotation() != nullptr) {
369 exportedTypes->push_back(this);
370 }
371}
372
Andreas Huber1c507272016-10-05 14:33:21 -0700373status_t EnumType::emitExportedHeader(Formatter &out, bool forJava) const {
Andreas Huber019d21d2016-10-03 12:59:47 -0700374 const Annotation *annotation = findExportAnnotation();
375 CHECK(annotation != nullptr);
376
377 std::string name = localName();
378
379 const AnnotationParam *nameParam = annotation->getParam("name");
380 if (nameParam != nullptr) {
381 CHECK_EQ(nameParam->getValues()->size(), 1u);
382
383 std::string quotedString = nameParam->getValues()->at(0);
384 name = quotedString.substr(1, quotedString.size() - 2);
385 }
386
Andreas Huberb0627fb2016-10-10 09:39:28 -0700387 std::string valuePrefix;
388
389 const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
390 if (prefixParam != nullptr) {
391 CHECK_EQ(prefixParam->getValues()->size(), 1u);
392
393 std::string quotedString = prefixParam->getValues()->at(0);
394 valuePrefix = quotedString.substr(1, quotedString.size() - 2);
395 }
396
Andreas Huber019d21d2016-10-03 12:59:47 -0700397 const ScalarType *scalarType = mStorageType->resolveToScalarType();
Andreas Huber1c507272016-10-05 14:33:21 -0700398 CHECK(scalarType != nullptr);
Andreas Huber019d21d2016-10-03 12:59:47 -0700399
Andreas Huber1c507272016-10-05 14:33:21 -0700400 if (forJava) {
401 if (!name.empty()) {
402 out << "public final class "
403 << name
404 << " {\n";
405
406 out.indent();
407 } else {
408 out << "// Values declared in " << localName() << " follow.\n";
409 }
410
411 std::string extra; // unused, because ScalarType leaves this empty.
412 const std::string typeName =
413 scalarType->getJavaType(&extra, false /* forInitializer */);
414
415 std::vector<const EnumType *> chain;
416 getTypeChain(&chain);
417
418 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
419 const auto &type = *it;
420
421 for (const auto &entry : type->values()) {
422 out << "public static final "
423 << typeName
424 << " "
425 << valuePrefix
426 << entry->name()
427 << " = ";
428
429 // javaValue will make the number signed.
430 std::string value = entry->javaValue(scalarType->getKind());
431 CHECK(!value.empty()); // use autofilled values for java.
432 out << value;
433
434 out << ";";
435
436 std::string comment = entry->comment();
437 if (!comment.empty() && comment != value) {
438 out << " // " << comment;
439 }
440
441 out << "\n";
442 }
443 }
444
445 if (!name.empty()) {
446 out.unindent();
447 out << "};\n";
448 }
449 out << "\n";
450
451 return OK;
452 }
Andreas Huber019d21d2016-10-03 12:59:47 -0700453
454 if (!name.empty()) {
455 out << "typedef ";
456 }
457
458 out << "enum {\n";
459
460 out.indent();
461
462 std::vector<const EnumType *> chain;
463 getTypeChain(&chain);
464
465 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
466 const auto &type = *it;
467
468 for (const auto &entry : type->values()) {
Andreas Huberb0627fb2016-10-10 09:39:28 -0700469 out << valuePrefix << entry->name();
Andreas Huber019d21d2016-10-03 12:59:47 -0700470
471 std::string value = entry->cppValue(scalarType->getKind());
472 CHECK(!value.empty()); // use autofilled values for c++.
473 out << " = " << value;
474
475 out << ",";
476
477 std::string comment = entry->comment();
478 if (!comment.empty() && comment != value) {
479 out << " // " << comment;
480 }
481
482 out << "\n";
483 }
484 }
485
486 out.unindent();
487 out << "}";
488
489 if (!name.empty()) {
490 out << " " << name;
491 }
492
493 out << ";\n\n";
494
495 return OK;
496}
497
Andreas Huber31629bc2016-08-03 09:06:40 -0700498////////////////////////////////////////////////////////////////////////////////
499
Yifan Hongf24fa852016-09-23 11:03:15 -0700500EnumValue::EnumValue(const char *name, ConstantExpression *value)
Andreas Huber31629bc2016-08-03 09:06:40 -0700501 : mName(name),
Yifan Hongf24fa852016-09-23 11:03:15 -0700502 mValue(value),
503 mIsAutoFill(false) {
Andreas Huber31629bc2016-08-03 09:06:40 -0700504}
505
506std::string EnumValue::name() const {
507 return mName;
508}
509
Yifan Hongfc610cd2016-09-22 13:34:45 -0700510std::string EnumValue::value() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700511 CHECK(mValue != nullptr);
512 return mValue->value();
Yifan Hong57886972016-08-17 10:42:15 -0700513}
514
Yifan Hongfc610cd2016-09-22 13:34:45 -0700515std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700516 CHECK(mValue != nullptr);
517 return mValue->cppValue(castKind);
Yifan Hong57886972016-08-17 10:42:15 -0700518}
Yifan Hongfc610cd2016-09-22 13:34:45 -0700519std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700520 CHECK(mValue != nullptr);
521 return mValue->javaValue(castKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700522}
Yifan Hong57886972016-08-17 10:42:15 -0700523
Yifan Hongfc610cd2016-09-22 13:34:45 -0700524std::string EnumValue::comment() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700525 CHECK(mValue != nullptr);
526 return mValue->description();
527}
528
529ConstantExpression *EnumValue::constExpr() const {
530 CHECK(mValue != nullptr);
531 return mValue;
532}
533
534void EnumValue::autofill(const EnumValue *prev, const ScalarType *type) {
535 if(mValue != nullptr)
536 return;
537 mIsAutoFill = true;
538 ConstantExpression *value = new ConstantExpression();
539 if(prev == nullptr) {
540 *value = ConstantExpression::Zero(type->getKind());
541 } else {
542 CHECK(prev->mValue != nullptr);
543 *value = prev->mValue->addOne();
544 }
545 mValue = value;
546}
547
548bool EnumValue::isAutoFill() const {
549 return mIsAutoFill;
550}
551
552bool EnumValue::isEnumValue() const {
553 return true;
Andreas Huber31629bc2016-08-03 09:06:40 -0700554}
555
Andreas Huberc9410c72016-07-28 12:18:40 -0700556} // namespace android
557