blob: 9903b3e145231120ff79cd42c5299d78be410909 [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,
75 std::string *extra,
76 bool specifyNamespaces) const {
Andreas Huber881227d2016-08-02 14:20:21 -070077 extra->clear();
78
Steven Moreland979e0992016-09-07 09:18:08 -070079 return specifyNamespaces ? fullName() : partialCppName();
Andreas Huber881227d2016-08-02 14:20:21 -070080}
81
Andreas Huber4c865b72016-09-14 15:26:27 -070082std::string EnumType::getJavaType(
83 std::string *extra, bool forInitializer) const {
84 return mStorageType->resolveToScalarType()->getJavaType(
85 extra, forInitializer);
Andreas Huber2831d512016-08-15 09:33:47 -070086}
87
88std::string EnumType::getJavaSuffix() const {
89 return mStorageType->resolveToScalarType()->getJavaSuffix();
90}
91
Andreas Hubera3558b32016-09-14 09:12:42 -070092std::string EnumType::getJavaWrapperType() const {
93 return mStorageType->resolveToScalarType()->getJavaWrapperType();
94}
95
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -070096std::string EnumType::getVtsType() const {
97 return "TYPE_ENUM";
98}
99
Yifan Hongf24fa852016-09-23 11:03:15 -0700100LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
101 std::vector<const EnumType *> chain;
102 getTypeChain(&chain);
103 for (auto it = chain.begin(); it != chain.end(); ++it) {
104 const auto &type = *it;
105 for(EnumValue *v : type->values()) {
106 if(v->name() == name) {
107 return v;
108 }
109 }
110 }
111 return nullptr;
112}
113
Andreas Huber881227d2016-08-02 14:20:21 -0700114void EnumType::emitReaderWriter(
115 Formatter &out,
116 const std::string &name,
117 const std::string &parcelObj,
118 bool parcelObjIsPointer,
119 bool isReader,
120 ErrorMode mode) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700121 const ScalarType *scalarType = mStorageType->resolveToScalarType();
122 CHECK(scalarType != NULL);
123
124 scalarType->emitReaderWriterWithCast(
125 out,
126 name,
127 parcelObj,
128 parcelObjIsPointer,
129 isReader,
130 mode,
131 true /* needsCast */);
Andreas Huber881227d2016-08-02 14:20:21 -0700132}
133
Andreas Huber85eabdb2016-08-25 11:24:49 -0700134void EnumType::emitJavaFieldReaderWriter(
135 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700136 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700137 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700138 const std::string &blobName,
139 const std::string &fieldName,
140 const std::string &offset,
141 bool isReader) const {
142 return mStorageType->emitJavaFieldReaderWriter(
Andreas Huber709b62d2016-09-19 11:21:18 -0700143 out, depth, parcelName, blobName, fieldName, offset, isReader);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700144}
145
Andreas Huber881227d2016-08-02 14:20:21 -0700146status_t EnumType::emitTypeDeclarations(Formatter &out) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700147 const ScalarType *scalarType = mStorageType->resolveToScalarType();
Andreas Hubere3f769a2016-10-10 10:54:44 -0700148 CHECK(scalarType != nullptr);
Andreas Huber737080b2016-08-02 15:38:04 -0700149
Andreas Huber881227d2016-08-02 14:20:21 -0700150 std::string extra;
Andreas Hubere3f769a2016-10-10 10:54:44 -0700151 const std::string storageType = ((Type *)scalarType)->getCppType(&extra);
Andreas Huber881227d2016-08-02 14:20:21 -0700152
153 out << "enum class "
Andreas Huber0e00de42016-08-03 09:56:02 -0700154 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700155 << " : "
Andreas Hubere3f769a2016-10-10 10:54:44 -0700156 << storageType
Andreas Huber881227d2016-08-02 14:20:21 -0700157 << " {\n";
158
159 out.indent();
160
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700161 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700162 getTypeChain(&chain);
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700163
164 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
165 const auto &type = *it;
166
167 for (const auto &entry : type->values()) {
168 out << entry->name();
169
Yifan Hongfc610cd2016-09-22 13:34:45 -0700170 std::string value = entry->cppValue(scalarType->getKind());
Yifan Hongf24fa852016-09-23 11:03:15 -0700171 CHECK(!value.empty()); // use autofilled values for c++.
172 out << " = " << value;
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700173
Yifan Hong57886972016-08-17 10:42:15 -0700174 out << ",";
175
Yifan Hongfc610cd2016-09-22 13:34:45 -0700176 std::string comment = entry->comment();
177 if (!comment.empty() && comment != value) {
Yifan Hong57886972016-08-17 10:42:15 -0700178 out << " // " << comment;
179 }
180
181 out << "\n";
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700182 }
Andreas Huber881227d2016-08-02 14:20:21 -0700183 }
184
185 out.unindent();
186 out << "};\n\n";
187
188 return OK;
189}
190
Andreas Hubere3f769a2016-10-10 10:54:44 -0700191void EnumType::emitEnumBitwiseOrOperator(Formatter &out, bool mutating) const {
192 const ScalarType *scalarType = mStorageType->resolveToScalarType();
193 CHECK(scalarType != nullptr);
194
195 std::string extra;
196 const std::string storageType = ((Type *)scalarType)->getCppType(&extra);
197
198 out << "inline "
199 << fullName()
200 << (mutating ? " &" : "")
201 << " operator|"
202 << (mutating ? "=" : "")
203 << "(\n";
204
205 out.indent();
206 out.indent();
207
208 out << fullName()
209 << (mutating ? " &" : " ")
210 << "lhs, "
211 << fullName()
212 << " rhs) {\n";
213 out.unindent();
214
215 if (mutating) {
216 out << "lhs = ";
217 } else {
218 out << "return ";
219 }
220 out << "static_cast<"
221 << fullName()
222 << ">(\n";
223 out.indent();
224 out.indent();
225 out << "static_cast<"
226 << storageType
227 << ">(lhs) | static_cast<"
228 << storageType
229 << ">(rhs));\n";
230 out.unindent();
231 out.unindent();
232
233 if (mutating) {
234 out << "return lhs;\n";
235 }
236
237 out.unindent();
238
239 out << "}\n\n";
240}
241
242status_t EnumType::emitGlobalTypeDeclarations(Formatter &out) const {
243 emitEnumBitwiseOrOperator(out, false /* mutating */);
244 emitEnumBitwiseOrOperator(out, true /* mutating */);
245
246 return OK;
247}
248
Andreas Huber85eabdb2016-08-25 11:24:49 -0700249status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool) const {
Andreas Huber2831d512016-08-15 09:33:47 -0700250 const ScalarType *scalarType = mStorageType->resolveToScalarType();
251 CHECK(scalarType != NULL);
252
253 out << "public final class "
254 << localName()
255 << " {\n";
256
257 out.indent();
258
Andreas Huber4c865b72016-09-14 15:26:27 -0700259 std::string extra; // unused, because ScalarType leaves this empty.
260 const std::string typeName =
261 scalarType->getJavaType(&extra, false /* forInitializer */);
Andreas Huber2831d512016-08-15 09:33:47 -0700262
263 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700264 getTypeChain(&chain);
Andreas Huber2831d512016-08-15 09:33:47 -0700265
266 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
267 const auto &type = *it;
268
269 for (const auto &entry : type->values()) {
270 out << "public static final "
271 << typeName
272 << " "
Andreas Huberab647c02016-09-14 09:44:00 -0700273 << entry->name()
274 << " = ";
Andreas Huber2831d512016-08-15 09:33:47 -0700275
Yifan Hongf24fa852016-09-23 11:03:15 -0700276 // javaValue will make the number signed.
Yifan Hongfc610cd2016-09-22 13:34:45 -0700277 std::string value = entry->javaValue(scalarType->getKind());
Yifan Hongf24fa852016-09-23 11:03:15 -0700278 CHECK(!value.empty()); // use autofilled values for java.
279 out << value;
Andreas Huber2831d512016-08-15 09:33:47 -0700280
Yifan Hong19ca75a2016-08-31 10:20:03 -0700281 out << ";";
282
Yifan Hongfc610cd2016-09-22 13:34:45 -0700283 std::string comment = entry->comment();
284 if (!comment.empty() && comment != value) {
Yifan Hong19ca75a2016-08-31 10:20:03 -0700285 out << " // " << comment;
286 }
287
288 out << "\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700289 }
290 }
291
292 out.unindent();
293 out << "};\n\n";
294
295 return OK;
296}
297
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700298status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700299 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700300 out << "type: " << getVtsType() << "\n";
301 out << "enum_value: {\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700302 out.indent();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700303
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700304 out << "scalar_type: \""
305 << mStorageType->resolveToScalarType()->getVtsScalarType()
306 << "\"\n\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700307 std::vector<const EnumType *> chain;
308 getTypeChain(&chain);
309
310 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
311 const auto &type = *it;
312
313 for (const auto &entry : type->values()) {
314 out << "enumerator: \"" << entry->name() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700315 out << "scalar_value: {\n";
316 out.indent();
Yifan Hongf24fa852016-09-23 11:03:15 -0700317 if (!entry->isAutoFill()) {
318 // don't autofill values for vts.
319 std::string value = entry->value();
320 CHECK(!value.empty());
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700321 out << mStorageType->resolveToScalarType()->getVtsScalarType()
322 << ": "
323 << value
324 << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700325 }
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700326 out.unindent();
327 out << "}\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700328 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700329 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700330
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700331 out.unindent();
332 out << "}\n";
333 return OK;
334}
335
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700336status_t EnumType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700337 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700338 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700339 return OK;
340}
341
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700342void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
343 out->clear();
344 const EnumType *type = this;
345 for (;;) {
346 out->push_back(type);
347
348 const Type *superType = type->storageType();
349 if (superType == NULL || !superType->isEnum()) {
350 break;
351 }
352
353 type = static_cast<const EnumType *>(superType);
354 }
355}
356
Andreas Huber85eabdb2016-08-25 11:24:49 -0700357void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
358 mStorageType->getAlignmentAndSize(align, size);
359}
360
Andreas Huber019d21d2016-10-03 12:59:47 -0700361const Annotation *EnumType::findExportAnnotation() const {
362 for (const auto &annotation : annotations()) {
363 if (annotation->name() == "export") {
364 return annotation;
365 }
366 }
367
368 return nullptr;
369}
370
371void EnumType::appendToExportedTypesVector(
372 std::vector<const Type *> *exportedTypes) const {
373 if (findExportAnnotation() != nullptr) {
374 exportedTypes->push_back(this);
375 }
376}
377
Andreas Huber1c507272016-10-05 14:33:21 -0700378status_t EnumType::emitExportedHeader(Formatter &out, bool forJava) const {
Andreas Huber019d21d2016-10-03 12:59:47 -0700379 const Annotation *annotation = findExportAnnotation();
380 CHECK(annotation != nullptr);
381
382 std::string name = localName();
383
384 const AnnotationParam *nameParam = annotation->getParam("name");
385 if (nameParam != nullptr) {
386 CHECK_EQ(nameParam->getValues()->size(), 1u);
387
388 std::string quotedString = nameParam->getValues()->at(0);
389 name = quotedString.substr(1, quotedString.size() - 2);
390 }
391
Andreas Huberb0627fb2016-10-10 09:39:28 -0700392 std::string valuePrefix;
393
394 const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
395 if (prefixParam != nullptr) {
396 CHECK_EQ(prefixParam->getValues()->size(), 1u);
397
398 std::string quotedString = prefixParam->getValues()->at(0);
399 valuePrefix = quotedString.substr(1, quotedString.size() - 2);
400 }
401
Andreas Huber019d21d2016-10-03 12:59:47 -0700402 const ScalarType *scalarType = mStorageType->resolveToScalarType();
Andreas Huber1c507272016-10-05 14:33:21 -0700403 CHECK(scalarType != nullptr);
Andreas Huber019d21d2016-10-03 12:59:47 -0700404
Andreas Huber1c507272016-10-05 14:33:21 -0700405 if (forJava) {
406 if (!name.empty()) {
407 out << "public final class "
408 << name
409 << " {\n";
410
411 out.indent();
412 } else {
413 out << "// Values declared in " << localName() << " follow.\n";
414 }
415
416 std::string extra; // unused, because ScalarType leaves this empty.
417 const std::string typeName =
418 scalarType->getJavaType(&extra, false /* forInitializer */);
419
420 std::vector<const EnumType *> chain;
421 getTypeChain(&chain);
422
423 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
424 const auto &type = *it;
425
426 for (const auto &entry : type->values()) {
427 out << "public static final "
428 << typeName
429 << " "
430 << valuePrefix
431 << entry->name()
432 << " = ";
433
434 // javaValue will make the number signed.
435 std::string value = entry->javaValue(scalarType->getKind());
436 CHECK(!value.empty()); // use autofilled values for java.
437 out << value;
438
439 out << ";";
440
441 std::string comment = entry->comment();
442 if (!comment.empty() && comment != value) {
443 out << " // " << comment;
444 }
445
446 out << "\n";
447 }
448 }
449
450 if (!name.empty()) {
451 out.unindent();
452 out << "};\n";
453 }
454 out << "\n";
455
456 return OK;
457 }
Andreas Huber019d21d2016-10-03 12:59:47 -0700458
459 if (!name.empty()) {
460 out << "typedef ";
461 }
462
463 out << "enum {\n";
464
465 out.indent();
466
467 std::vector<const EnumType *> chain;
468 getTypeChain(&chain);
469
470 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
471 const auto &type = *it;
472
473 for (const auto &entry : type->values()) {
Andreas Huberb0627fb2016-10-10 09:39:28 -0700474 out << valuePrefix << entry->name();
Andreas Huber019d21d2016-10-03 12:59:47 -0700475
476 std::string value = entry->cppValue(scalarType->getKind());
477 CHECK(!value.empty()); // use autofilled values for c++.
478 out << " = " << value;
479
480 out << ",";
481
482 std::string comment = entry->comment();
483 if (!comment.empty() && comment != value) {
484 out << " // " << comment;
485 }
486
487 out << "\n";
488 }
489 }
490
491 out.unindent();
492 out << "}";
493
494 if (!name.empty()) {
495 out << " " << name;
496 }
497
498 out << ";\n\n";
499
500 return OK;
501}
502
Andreas Huber31629bc2016-08-03 09:06:40 -0700503////////////////////////////////////////////////////////////////////////////////
504
Yifan Hongf24fa852016-09-23 11:03:15 -0700505EnumValue::EnumValue(const char *name, ConstantExpression *value)
Andreas Huber31629bc2016-08-03 09:06:40 -0700506 : mName(name),
Yifan Hongf24fa852016-09-23 11:03:15 -0700507 mValue(value),
508 mIsAutoFill(false) {
Andreas Huber31629bc2016-08-03 09:06:40 -0700509}
510
511std::string EnumValue::name() const {
512 return mName;
513}
514
Yifan Hongfc610cd2016-09-22 13:34:45 -0700515std::string EnumValue::value() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700516 CHECK(mValue != nullptr);
517 return mValue->value();
Yifan Hong57886972016-08-17 10:42:15 -0700518}
519
Yifan Hongfc610cd2016-09-22 13:34:45 -0700520std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700521 CHECK(mValue != nullptr);
522 return mValue->cppValue(castKind);
Yifan Hong57886972016-08-17 10:42:15 -0700523}
Yifan Hongfc610cd2016-09-22 13:34:45 -0700524std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700525 CHECK(mValue != nullptr);
526 return mValue->javaValue(castKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700527}
Yifan Hong57886972016-08-17 10:42:15 -0700528
Yifan Hongfc610cd2016-09-22 13:34:45 -0700529std::string EnumValue::comment() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700530 CHECK(mValue != nullptr);
531 return mValue->description();
532}
533
534ConstantExpression *EnumValue::constExpr() const {
535 CHECK(mValue != nullptr);
536 return mValue;
537}
538
539void EnumValue::autofill(const EnumValue *prev, const ScalarType *type) {
540 if(mValue != nullptr)
541 return;
542 mIsAutoFill = true;
543 ConstantExpression *value = new ConstantExpression();
544 if(prev == nullptr) {
545 *value = ConstantExpression::Zero(type->getKind());
546 } else {
547 CHECK(prev->mValue != nullptr);
548 *value = prev->mValue->addOne();
549 }
550 mValue = value;
551}
552
553bool EnumValue::isAutoFill() const {
554 return mIsAutoFill;
555}
556
557bool EnumValue::isEnumValue() const {
558 return true;
Andreas Huber31629bc2016-08-03 09:06:40 -0700559}
560
Andreas Huberc9410c72016-07-28 12:18:40 -0700561} // namespace android
562