blob: 1905a3e02d9266868542552f72399f6a6dbf1e99 [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
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -070095std::string EnumType::getVtsType() const {
96 return "TYPE_ENUM";
97}
98
Yifan Hongf24fa852016-09-23 11:03:15 -070099LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
100 std::vector<const EnumType *> chain;
101 getTypeChain(&chain);
102 for (auto it = chain.begin(); it != chain.end(); ++it) {
103 const auto &type = *it;
104 for(EnumValue *v : type->values()) {
105 if(v->name() == name) {
106 return v;
107 }
108 }
109 }
110 return nullptr;
111}
112
Andreas Huber881227d2016-08-02 14:20:21 -0700113void EnumType::emitReaderWriter(
114 Formatter &out,
115 const std::string &name,
116 const std::string &parcelObj,
117 bool parcelObjIsPointer,
118 bool isReader,
119 ErrorMode mode) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700120 const ScalarType *scalarType = mStorageType->resolveToScalarType();
121 CHECK(scalarType != NULL);
122
123 scalarType->emitReaderWriterWithCast(
124 out,
125 name,
126 parcelObj,
127 parcelObjIsPointer,
128 isReader,
129 mode,
130 true /* needsCast */);
Andreas Huber881227d2016-08-02 14:20:21 -0700131}
132
Andreas Huber85eabdb2016-08-25 11:24:49 -0700133void EnumType::emitJavaFieldReaderWriter(
134 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700135 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700136 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700137 const std::string &blobName,
138 const std::string &fieldName,
139 const std::string &offset,
140 bool isReader) const {
141 return mStorageType->emitJavaFieldReaderWriter(
Andreas Huber709b62d2016-09-19 11:21:18 -0700142 out, depth, parcelName, blobName, fieldName, offset, isReader);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700143}
144
Andreas Huber881227d2016-08-02 14:20:21 -0700145status_t EnumType::emitTypeDeclarations(Formatter &out) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700146 const ScalarType *scalarType = mStorageType->resolveToScalarType();
Andreas Hubere3f769a2016-10-10 10:54:44 -0700147 CHECK(scalarType != nullptr);
Andreas Huber737080b2016-08-02 15:38:04 -0700148
Andreas Huber881227d2016-08-02 14:20:21 -0700149 std::string extra;
Andreas Hubere3f769a2016-10-10 10:54:44 -0700150 const std::string storageType = ((Type *)scalarType)->getCppType(&extra);
Andreas Huber881227d2016-08-02 14:20:21 -0700151
152 out << "enum class "
Andreas Huber0e00de42016-08-03 09:56:02 -0700153 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700154 << " : "
Andreas Hubere3f769a2016-10-10 10:54:44 -0700155 << storageType
Andreas Huber881227d2016-08-02 14:20:21 -0700156 << " {\n";
157
158 out.indent();
159
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700160 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700161 getTypeChain(&chain);
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700162
163 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
164 const auto &type = *it;
165
166 for (const auto &entry : type->values()) {
167 out << entry->name();
168
Yifan Hongfc610cd2016-09-22 13:34:45 -0700169 std::string value = entry->cppValue(scalarType->getKind());
Yifan Hongf24fa852016-09-23 11:03:15 -0700170 CHECK(!value.empty()); // use autofilled values for c++.
171 out << " = " << value;
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700172
Yifan Hong57886972016-08-17 10:42:15 -0700173 out << ",";
174
Yifan Hongfc610cd2016-09-22 13:34:45 -0700175 std::string comment = entry->comment();
176 if (!comment.empty() && comment != value) {
Yifan Hong57886972016-08-17 10:42:15 -0700177 out << " // " << comment;
178 }
179
180 out << "\n";
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700181 }
Andreas Huber881227d2016-08-02 14:20:21 -0700182 }
183
184 out.unindent();
185 out << "};\n\n";
186
187 return OK;
188}
189
Andreas Hubere3f769a2016-10-10 10:54:44 -0700190void EnumType::emitEnumBitwiseOrOperator(Formatter &out, bool mutating) const {
191 const ScalarType *scalarType = mStorageType->resolveToScalarType();
192 CHECK(scalarType != nullptr);
193
194 std::string extra;
195 const std::string storageType = ((Type *)scalarType)->getCppType(&extra);
196
197 out << "inline "
198 << fullName()
199 << (mutating ? " &" : "")
200 << " operator|"
201 << (mutating ? "=" : "")
202 << "(\n";
203
204 out.indent();
205 out.indent();
206
207 out << fullName()
208 << (mutating ? " &" : " ")
209 << "lhs, "
210 << fullName()
211 << " rhs) {\n";
212 out.unindent();
213
214 if (mutating) {
215 out << "lhs = ";
216 } else {
217 out << "return ";
218 }
219 out << "static_cast<"
220 << fullName()
221 << ">(\n";
222 out.indent();
223 out.indent();
224 out << "static_cast<"
225 << storageType
226 << ">(lhs) | static_cast<"
227 << storageType
228 << ">(rhs));\n";
229 out.unindent();
230 out.unindent();
231
232 if (mutating) {
233 out << "return lhs;\n";
234 }
235
236 out.unindent();
237
238 out << "}\n\n";
239}
240
241status_t EnumType::emitGlobalTypeDeclarations(Formatter &out) const {
242 emitEnumBitwiseOrOperator(out, false /* mutating */);
243 emitEnumBitwiseOrOperator(out, true /* mutating */);
244
245 return OK;
246}
247
Andreas Huber85eabdb2016-08-25 11:24:49 -0700248status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool) const {
Andreas Huber2831d512016-08-15 09:33:47 -0700249 const ScalarType *scalarType = mStorageType->resolveToScalarType();
250 CHECK(scalarType != NULL);
251
252 out << "public final class "
253 << localName()
254 << " {\n";
255
256 out.indent();
257
Andreas Huber4c865b72016-09-14 15:26:27 -0700258 std::string extra; // unused, because ScalarType leaves this empty.
259 const std::string typeName =
260 scalarType->getJavaType(&extra, false /* forInitializer */);
Andreas Huber2831d512016-08-15 09:33:47 -0700261
262 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700263 getTypeChain(&chain);
Andreas Huber2831d512016-08-15 09:33:47 -0700264
265 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
266 const auto &type = *it;
267
268 for (const auto &entry : type->values()) {
269 out << "public static final "
270 << typeName
271 << " "
Andreas Huberab647c02016-09-14 09:44:00 -0700272 << entry->name()
273 << " = ";
Andreas Huber2831d512016-08-15 09:33:47 -0700274
Yifan Hongf24fa852016-09-23 11:03:15 -0700275 // javaValue will make the number signed.
Yifan Hongfc610cd2016-09-22 13:34:45 -0700276 std::string value = entry->javaValue(scalarType->getKind());
Yifan Hongf24fa852016-09-23 11:03:15 -0700277 CHECK(!value.empty()); // use autofilled values for java.
278 out << value;
Andreas Huber2831d512016-08-15 09:33:47 -0700279
Yifan Hong19ca75a2016-08-31 10:20:03 -0700280 out << ";";
281
Yifan Hongfc610cd2016-09-22 13:34:45 -0700282 std::string comment = entry->comment();
283 if (!comment.empty() && comment != value) {
Yifan Hong19ca75a2016-08-31 10:20:03 -0700284 out << " // " << comment;
285 }
286
287 out << "\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700288 }
289 }
290
291 out.unindent();
292 out << "};\n\n";
293
294 return OK;
295}
296
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700297status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700298 out << "name: \"" << localName() << "\"\n";
299 out << "type: " << getVtsType() << "\n";
300 out << "enum_value: {\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700301 out.indent();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700302
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700303 out << "scalar_type: \""
304 << mStorageType->resolveToScalarType()->getVtsScalarType()
305 << "\"\n\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700306 std::vector<const EnumType *> chain;
307 getTypeChain(&chain);
308
309 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
310 const auto &type = *it;
311
312 for (const auto &entry : type->values()) {
313 out << "enumerator: \"" << entry->name() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700314 out << "scalar_value: {\n";
315 out.indent();
Yifan Hongf24fa852016-09-23 11:03:15 -0700316 if (!entry->isAutoFill()) {
317 // don't autofill values for vts.
318 std::string value = entry->value();
319 CHECK(!value.empty());
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700320 out << mStorageType->resolveToScalarType()->getVtsScalarType()
321 << ": "
322 << value
323 << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700324 }
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700325 out.unindent();
326 out << "}\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700327 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700328 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700329
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700330 out.unindent();
331 out << "}\n";
332 return OK;
333}
334
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700335status_t EnumType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700336 out << "type: " << getVtsType() << "\n";
337 out << "predefined_type: \"" << localName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700338 return OK;
339}
340
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700341void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
342 out->clear();
343 const EnumType *type = this;
344 for (;;) {
345 out->push_back(type);
346
347 const Type *superType = type->storageType();
348 if (superType == NULL || !superType->isEnum()) {
349 break;
350 }
351
352 type = static_cast<const EnumType *>(superType);
353 }
354}
355
Andreas Huber85eabdb2016-08-25 11:24:49 -0700356void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
357 mStorageType->getAlignmentAndSize(align, size);
358}
359
Andreas Huber019d21d2016-10-03 12:59:47 -0700360const Annotation *EnumType::findExportAnnotation() const {
361 for (const auto &annotation : annotations()) {
362 if (annotation->name() == "export") {
363 return annotation;
364 }
365 }
366
367 return nullptr;
368}
369
370void EnumType::appendToExportedTypesVector(
371 std::vector<const Type *> *exportedTypes) const {
372 if (findExportAnnotation() != nullptr) {
373 exportedTypes->push_back(this);
374 }
375}
376
Andreas Huber1c507272016-10-05 14:33:21 -0700377status_t EnumType::emitExportedHeader(Formatter &out, bool forJava) const {
Andreas Huber019d21d2016-10-03 12:59:47 -0700378 const Annotation *annotation = findExportAnnotation();
379 CHECK(annotation != nullptr);
380
381 std::string name = localName();
382
383 const AnnotationParam *nameParam = annotation->getParam("name");
384 if (nameParam != nullptr) {
385 CHECK_EQ(nameParam->getValues()->size(), 1u);
386
387 std::string quotedString = nameParam->getValues()->at(0);
388 name = quotedString.substr(1, quotedString.size() - 2);
389 }
390
Andreas Huberb0627fb2016-10-10 09:39:28 -0700391 std::string valuePrefix;
392
393 const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
394 if (prefixParam != nullptr) {
395 CHECK_EQ(prefixParam->getValues()->size(), 1u);
396
397 std::string quotedString = prefixParam->getValues()->at(0);
398 valuePrefix = quotedString.substr(1, quotedString.size() - 2);
399 }
400
Andreas Huber019d21d2016-10-03 12:59:47 -0700401 const ScalarType *scalarType = mStorageType->resolveToScalarType();
Andreas Huber1c507272016-10-05 14:33:21 -0700402 CHECK(scalarType != nullptr);
Andreas Huber019d21d2016-10-03 12:59:47 -0700403
Andreas Huber1c507272016-10-05 14:33:21 -0700404 if (forJava) {
405 if (!name.empty()) {
406 out << "public final class "
407 << name
408 << " {\n";
409
410 out.indent();
411 } else {
412 out << "// Values declared in " << localName() << " follow.\n";
413 }
414
415 std::string extra; // unused, because ScalarType leaves this empty.
416 const std::string typeName =
417 scalarType->getJavaType(&extra, false /* forInitializer */);
418
419 std::vector<const EnumType *> chain;
420 getTypeChain(&chain);
421
422 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
423 const auto &type = *it;
424
425 for (const auto &entry : type->values()) {
426 out << "public static final "
427 << typeName
428 << " "
429 << valuePrefix
430 << entry->name()
431 << " = ";
432
433 // javaValue will make the number signed.
434 std::string value = entry->javaValue(scalarType->getKind());
435 CHECK(!value.empty()); // use autofilled values for java.
436 out << value;
437
438 out << ";";
439
440 std::string comment = entry->comment();
441 if (!comment.empty() && comment != value) {
442 out << " // " << comment;
443 }
444
445 out << "\n";
446 }
447 }
448
449 if (!name.empty()) {
450 out.unindent();
451 out << "};\n";
452 }
453 out << "\n";
454
455 return OK;
456 }
Andreas Huber019d21d2016-10-03 12:59:47 -0700457
458 if (!name.empty()) {
459 out << "typedef ";
460 }
461
462 out << "enum {\n";
463
464 out.indent();
465
466 std::vector<const EnumType *> chain;
467 getTypeChain(&chain);
468
469 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
470 const auto &type = *it;
471
472 for (const auto &entry : type->values()) {
Andreas Huberb0627fb2016-10-10 09:39:28 -0700473 out << valuePrefix << entry->name();
Andreas Huber019d21d2016-10-03 12:59:47 -0700474
475 std::string value = entry->cppValue(scalarType->getKind());
476 CHECK(!value.empty()); // use autofilled values for c++.
477 out << " = " << value;
478
479 out << ",";
480
481 std::string comment = entry->comment();
482 if (!comment.empty() && comment != value) {
483 out << " // " << comment;
484 }
485
486 out << "\n";
487 }
488 }
489
490 out.unindent();
491 out << "}";
492
493 if (!name.empty()) {
494 out << " " << name;
495 }
496
497 out << ";\n\n";
498
499 return OK;
500}
501
Andreas Huber31629bc2016-08-03 09:06:40 -0700502////////////////////////////////////////////////////////////////////////////////
503
Yifan Hongf24fa852016-09-23 11:03:15 -0700504EnumValue::EnumValue(const char *name, ConstantExpression *value)
Andreas Huber31629bc2016-08-03 09:06:40 -0700505 : mName(name),
Yifan Hongf24fa852016-09-23 11:03:15 -0700506 mValue(value),
507 mIsAutoFill(false) {
Andreas Huber31629bc2016-08-03 09:06:40 -0700508}
509
510std::string EnumValue::name() const {
511 return mName;
512}
513
Yifan Hongfc610cd2016-09-22 13:34:45 -0700514std::string EnumValue::value() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700515 CHECK(mValue != nullptr);
516 return mValue->value();
Yifan Hong57886972016-08-17 10:42:15 -0700517}
518
Yifan Hongfc610cd2016-09-22 13:34:45 -0700519std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700520 CHECK(mValue != nullptr);
521 return mValue->cppValue(castKind);
Yifan Hong57886972016-08-17 10:42:15 -0700522}
Yifan Hongfc610cd2016-09-22 13:34:45 -0700523std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700524 CHECK(mValue != nullptr);
525 return mValue->javaValue(castKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700526}
Yifan Hong57886972016-08-17 10:42:15 -0700527
Yifan Hongfc610cd2016-09-22 13:34:45 -0700528std::string EnumValue::comment() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700529 CHECK(mValue != nullptr);
530 return mValue->description();
531}
532
533ConstantExpression *EnumValue::constExpr() const {
534 CHECK(mValue != nullptr);
535 return mValue;
536}
537
538void EnumValue::autofill(const EnumValue *prev, const ScalarType *type) {
539 if(mValue != nullptr)
540 return;
541 mIsAutoFill = true;
542 ConstantExpression *value = new ConstantExpression();
543 if(prev == nullptr) {
544 *value = ConstantExpression::Zero(type->getKind());
545 } else {
546 CHECK(prev->mValue != nullptr);
547 *value = prev->mValue->addOne();
548 }
549 mValue = value;
550}
551
552bool EnumValue::isAutoFill() const {
553 return mIsAutoFill;
554}
555
556bool EnumValue::isEnumValue() const {
557 return true;
Andreas Huber31629bc2016-08-03 09:06:40 -0700558}
559
Andreas Huberc9410c72016-07-28 12:18:40 -0700560} // namespace android
561