blob: 99f1b637006c7c43bba7bc70e021832cd0b3e600 [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
Yifan Hong4ed13472016-11-02 10:44:11 -070079std::string EnumType::getJavaType(bool forInitializer) const {
80 return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
Andreas Huber2831d512016-08-15 09:33:47 -070081}
82
83std::string EnumType::getJavaSuffix() const {
84 return mStorageType->resolveToScalarType()->getJavaSuffix();
85}
86
Andreas Hubera3558b32016-09-14 09:12:42 -070087std::string EnumType::getJavaWrapperType() const {
88 return mStorageType->resolveToScalarType()->getJavaWrapperType();
89}
90
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -070091std::string EnumType::getVtsType() const {
92 return "TYPE_ENUM";
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();
Andreas Hubere3f769a2016-10-10 10:54:44 -0700143 CHECK(scalarType != nullptr);
Andreas Huber737080b2016-08-02 15:38:04 -0700144
Yifan Hong3b320f82016-11-01 15:15:54 -0700145 const std::string storageType = scalarType->getCppStackType();
Andreas Huber881227d2016-08-02 14:20:21 -0700146
147 out << "enum class "
Andreas Huber0e00de42016-08-03 09:56:02 -0700148 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700149 << " : "
Andreas Hubere3f769a2016-10-10 10:54:44 -0700150 << storageType
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 Hubere3f769a2016-10-10 10:54:44 -0700185void EnumType::emitEnumBitwiseOrOperator(Formatter &out, bool mutating) const {
186 const ScalarType *scalarType = mStorageType->resolveToScalarType();
187 CHECK(scalarType != nullptr);
188
Yifan Hong3b320f82016-11-01 15:15:54 -0700189 const std::string storageType = scalarType->getCppStackType();
Andreas Hubere3f769a2016-10-10 10:54:44 -0700190
191 out << "inline "
192 << fullName()
193 << (mutating ? " &" : "")
194 << " operator|"
195 << (mutating ? "=" : "")
196 << "(\n";
197
198 out.indent();
199 out.indent();
200
201 out << fullName()
202 << (mutating ? " &" : " ")
203 << "lhs, "
204 << fullName()
205 << " rhs) {\n";
206 out.unindent();
207
208 if (mutating) {
209 out << "lhs = ";
210 } else {
211 out << "return ";
212 }
213 out << "static_cast<"
214 << fullName()
215 << ">(\n";
216 out.indent();
217 out.indent();
218 out << "static_cast<"
219 << storageType
220 << ">(lhs) | static_cast<"
221 << storageType
222 << ">(rhs));\n";
223 out.unindent();
224 out.unindent();
225
226 if (mutating) {
227 out << "return lhs;\n";
228 }
229
230 out.unindent();
231
232 out << "}\n\n";
233}
234
235status_t EnumType::emitGlobalTypeDeclarations(Formatter &out) const {
236 emitEnumBitwiseOrOperator(out, false /* mutating */);
237 emitEnumBitwiseOrOperator(out, true /* mutating */);
238
239 return OK;
240}
241
Andreas Huber85eabdb2016-08-25 11:24:49 -0700242status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool) const {
Andreas Huber2831d512016-08-15 09:33:47 -0700243 const ScalarType *scalarType = mStorageType->resolveToScalarType();
244 CHECK(scalarType != NULL);
245
246 out << "public final class "
247 << localName()
248 << " {\n";
249
250 out.indent();
251
Andreas Huber4c865b72016-09-14 15:26:27 -0700252 const std::string typeName =
Yifan Hong4ed13472016-11-02 10:44:11 -0700253 scalarType->getJavaType(false /* forInitializer */);
Andreas Huber2831d512016-08-15 09:33:47 -0700254
255 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700256 getTypeChain(&chain);
Andreas Huber2831d512016-08-15 09:33:47 -0700257
258 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
259 const auto &type = *it;
260
261 for (const auto &entry : type->values()) {
262 out << "public static final "
263 << typeName
264 << " "
Andreas Huberab647c02016-09-14 09:44:00 -0700265 << entry->name()
266 << " = ";
Andreas Huber2831d512016-08-15 09:33:47 -0700267
Yifan Hongf24fa852016-09-23 11:03:15 -0700268 // javaValue will make the number signed.
Yifan Hongfc610cd2016-09-22 13:34:45 -0700269 std::string value = entry->javaValue(scalarType->getKind());
Yifan Hongf24fa852016-09-23 11:03:15 -0700270 CHECK(!value.empty()); // use autofilled values for java.
271 out << value;
Andreas Huber2831d512016-08-15 09:33:47 -0700272
Yifan Hong19ca75a2016-08-31 10:20:03 -0700273 out << ";";
274
Yifan Hongfc610cd2016-09-22 13:34:45 -0700275 std::string comment = entry->comment();
276 if (!comment.empty() && comment != value) {
Yifan Hong19ca75a2016-08-31 10:20:03 -0700277 out << " // " << comment;
278 }
279
280 out << "\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700281 }
282 }
283
284 out.unindent();
285 out << "};\n\n";
286
287 return OK;
288}
289
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700290status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
Yifan Hongc07b2022016-11-08 12:44:24 -0800291 const ScalarType *scalarType = mStorageType->resolveToScalarType();
292
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700293 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700294 out << "type: " << getVtsType() << "\n";
295 out << "enum_value: {\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700296 out.indent();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700297
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700298 out << "scalar_type: \""
Yifan Hongc07b2022016-11-08 12:44:24 -0800299 << scalarType->getVtsScalarType()
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700300 << "\"\n\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700301 std::vector<const EnumType *> chain;
302 getTypeChain(&chain);
303
304 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
305 const auto &type = *it;
306
307 for (const auto &entry : type->values()) {
308 out << "enumerator: \"" << entry->name() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700309 out << "scalar_value: {\n";
310 out.indent();
Yifan Hongc07b2022016-11-08 12:44:24 -0800311 // use autofilled values for vts.
312 std::string value = entry->value(scalarType->getKind());
313 CHECK(!value.empty());
314 out << mStorageType->resolveToScalarType()->getVtsScalarType()
315 << ": "
316 << value
317 << "\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700318 out.unindent();
319 out << "}\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700320 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700321 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700322
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700323 out.unindent();
324 out << "}\n";
325 return OK;
326}
327
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700328status_t EnumType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700329 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700330 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700331 return OK;
332}
333
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700334void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
335 out->clear();
336 const EnumType *type = this;
337 for (;;) {
338 out->push_back(type);
339
340 const Type *superType = type->storageType();
341 if (superType == NULL || !superType->isEnum()) {
342 break;
343 }
344
345 type = static_cast<const EnumType *>(superType);
346 }
347}
348
Andreas Huber85eabdb2016-08-25 11:24:49 -0700349void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
350 mStorageType->getAlignmentAndSize(align, size);
351}
352
Andreas Huber019d21d2016-10-03 12:59:47 -0700353const Annotation *EnumType::findExportAnnotation() const {
354 for (const auto &annotation : annotations()) {
355 if (annotation->name() == "export") {
356 return annotation;
357 }
358 }
359
360 return nullptr;
361}
362
363void EnumType::appendToExportedTypesVector(
364 std::vector<const Type *> *exportedTypes) const {
365 if (findExportAnnotation() != nullptr) {
366 exportedTypes->push_back(this);
367 }
368}
369
Andreas Huber1c507272016-10-05 14:33:21 -0700370status_t EnumType::emitExportedHeader(Formatter &out, bool forJava) const {
Andreas Huber019d21d2016-10-03 12:59:47 -0700371 const Annotation *annotation = findExportAnnotation();
372 CHECK(annotation != nullptr);
373
374 std::string name = localName();
375
376 const AnnotationParam *nameParam = annotation->getParam("name");
377 if (nameParam != nullptr) {
378 CHECK_EQ(nameParam->getValues()->size(), 1u);
379
380 std::string quotedString = nameParam->getValues()->at(0);
381 name = quotedString.substr(1, quotedString.size() - 2);
382 }
383
Andreas Huberb0627fb2016-10-10 09:39:28 -0700384 std::string valuePrefix;
385
386 const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
387 if (prefixParam != nullptr) {
388 CHECK_EQ(prefixParam->getValues()->size(), 1u);
389
390 std::string quotedString = prefixParam->getValues()->at(0);
391 valuePrefix = quotedString.substr(1, quotedString.size() - 2);
392 }
393
Andreas Huber019d21d2016-10-03 12:59:47 -0700394 const ScalarType *scalarType = mStorageType->resolveToScalarType();
Andreas Huber1c507272016-10-05 14:33:21 -0700395 CHECK(scalarType != nullptr);
Andreas Huber019d21d2016-10-03 12:59:47 -0700396
Andreas Huber1c507272016-10-05 14:33:21 -0700397 if (forJava) {
398 if (!name.empty()) {
399 out << "public final class "
400 << name
401 << " {\n";
402
403 out.indent();
404 } else {
405 out << "// Values declared in " << localName() << " follow.\n";
406 }
407
Andreas Huber1c507272016-10-05 14:33:21 -0700408 const std::string typeName =
Yifan Hong4ed13472016-11-02 10:44:11 -0700409 scalarType->getJavaType(false /* forInitializer */);
Andreas Huber1c507272016-10-05 14:33:21 -0700410
411 std::vector<const EnumType *> chain;
412 getTypeChain(&chain);
413
414 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
415 const auto &type = *it;
416
417 for (const auto &entry : type->values()) {
418 out << "public static final "
419 << typeName
420 << " "
421 << valuePrefix
422 << entry->name()
423 << " = ";
424
425 // javaValue will make the number signed.
426 std::string value = entry->javaValue(scalarType->getKind());
427 CHECK(!value.empty()); // use autofilled values for java.
428 out << value;
429
430 out << ";";
431
432 std::string comment = entry->comment();
433 if (!comment.empty() && comment != value) {
434 out << " // " << comment;
435 }
436
437 out << "\n";
438 }
439 }
440
441 if (!name.empty()) {
442 out.unindent();
443 out << "};\n";
444 }
445 out << "\n";
446
447 return OK;
448 }
Andreas Huber019d21d2016-10-03 12:59:47 -0700449
450 if (!name.empty()) {
451 out << "typedef ";
452 }
453
454 out << "enum {\n";
455
456 out.indent();
457
458 std::vector<const EnumType *> chain;
459 getTypeChain(&chain);
460
461 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
462 const auto &type = *it;
463
464 for (const auto &entry : type->values()) {
Andreas Huberb0627fb2016-10-10 09:39:28 -0700465 out << valuePrefix << entry->name();
Andreas Huber019d21d2016-10-03 12:59:47 -0700466
467 std::string value = entry->cppValue(scalarType->getKind());
468 CHECK(!value.empty()); // use autofilled values for c++.
469 out << " = " << value;
470
471 out << ",";
472
473 std::string comment = entry->comment();
474 if (!comment.empty() && comment != value) {
475 out << " // " << comment;
476 }
477
478 out << "\n";
479 }
480 }
481
482 out.unindent();
483 out << "}";
484
485 if (!name.empty()) {
486 out << " " << name;
487 }
488
489 out << ";\n\n";
490
491 return OK;
492}
493
Andreas Huber31629bc2016-08-03 09:06:40 -0700494////////////////////////////////////////////////////////////////////////////////
495
Yifan Hongf24fa852016-09-23 11:03:15 -0700496EnumValue::EnumValue(const char *name, ConstantExpression *value)
Andreas Huber31629bc2016-08-03 09:06:40 -0700497 : mName(name),
Yifan Hongf24fa852016-09-23 11:03:15 -0700498 mValue(value),
499 mIsAutoFill(false) {
Andreas Huber31629bc2016-08-03 09:06:40 -0700500}
501
502std::string EnumValue::name() const {
503 return mName;
504}
505
Yifan Hongc07b2022016-11-08 12:44:24 -0800506std::string EnumValue::value(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700507 CHECK(mValue != nullptr);
Yifan Hongc07b2022016-11-08 12:44:24 -0800508 return mValue->value(castKind);
Yifan Hong57886972016-08-17 10:42:15 -0700509}
510
Yifan Hongfc610cd2016-09-22 13:34:45 -0700511std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700512 CHECK(mValue != nullptr);
513 return mValue->cppValue(castKind);
Yifan Hong57886972016-08-17 10:42:15 -0700514}
Yifan Hongfc610cd2016-09-22 13:34:45 -0700515std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700516 CHECK(mValue != nullptr);
517 return mValue->javaValue(castKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700518}
Yifan Hong57886972016-08-17 10:42:15 -0700519
Yifan Hongfc610cd2016-09-22 13:34:45 -0700520std::string EnumValue::comment() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700521 CHECK(mValue != nullptr);
522 return mValue->description();
523}
524
525ConstantExpression *EnumValue::constExpr() const {
526 CHECK(mValue != nullptr);
527 return mValue;
528}
529
530void EnumValue::autofill(const EnumValue *prev, const ScalarType *type) {
531 if(mValue != nullptr)
532 return;
533 mIsAutoFill = true;
534 ConstantExpression *value = new ConstantExpression();
535 if(prev == nullptr) {
536 *value = ConstantExpression::Zero(type->getKind());
537 } else {
538 CHECK(prev->mValue != nullptr);
539 *value = prev->mValue->addOne();
540 }
541 mValue = value;
542}
543
544bool EnumValue::isAutoFill() const {
545 return mIsAutoFill;
546}
547
548bool EnumValue::isEnumValue() const {
549 return true;
Andreas Huber31629bc2016-08-03 09:06:40 -0700550}
551
Andreas Huberc9410c72016-07-28 12:18:40 -0700552} // namespace android
553