blob: 6dfabfdcfeaadfc9ce8a7cabce6318ebc351bab0 [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(),
Steven Moreland1c71fd52016-11-29 14:03:33 -080034 mStorageType(storageType) {
Yifan Honge45b5302017-02-22 10:49:07 -080035 mBitfieldType = new BitFieldType();
36 mBitfieldType->setElementType(this);
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
Steven Moreland9df52442016-12-12 08:51:14 -080065bool EnumType::isElidableType() const {
66 return mStorageType->isElidableType();
67}
68
Andreas Huber737080b2016-08-02 15:38:04 -070069const ScalarType *EnumType::resolveToScalarType() const {
70 return mStorageType->resolveToScalarType();
71}
72
Steven Moreland30bb6a82016-11-30 09:18:34 -080073std::string EnumType::typeName() const {
74 return "enum " + localName();
75}
76
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070077bool EnumType::isEnum() const {
78 return true;
79}
80
Yifan Hongc6752dc2016-12-20 14:00:14 -080081bool EnumType::canCheckEquality() const {
82 return true;
83}
84
Steven Moreland979e0992016-09-07 09:18:08 -070085std::string EnumType::getCppType(StorageMode,
Steven Morelande30ee9b2017-05-09 13:31:01 -070086 bool /* specifyNamespaces */) const {
87 return fullName();
Andreas Huber881227d2016-08-02 14:20:21 -070088}
89
Yifan Hong4ed13472016-11-02 10:44:11 -070090std::string EnumType::getJavaType(bool forInitializer) const {
91 return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
Andreas Huber2831d512016-08-15 09:33:47 -070092}
93
94std::string EnumType::getJavaSuffix() const {
95 return mStorageType->resolveToScalarType()->getJavaSuffix();
96}
97
Andreas Hubera3558b32016-09-14 09:12:42 -070098std::string EnumType::getJavaWrapperType() const {
99 return mStorageType->resolveToScalarType()->getJavaWrapperType();
100}
101
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700102std::string EnumType::getVtsType() const {
103 return "TYPE_ENUM";
104}
105
Yifan Honge45b5302017-02-22 10:49:07 -0800106BitFieldType *EnumType::getBitfieldType() const {
107 return mBitfieldType;
108}
109
Yifan Hongf24fa852016-09-23 11:03:15 -0700110LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
111 std::vector<const EnumType *> chain;
112 getTypeChain(&chain);
113 for (auto it = chain.begin(); it != chain.end(); ++it) {
114 const auto &type = *it;
115 for(EnumValue *v : type->values()) {
116 if(v->name() == name) {
117 return v;
118 }
119 }
120 }
121 return nullptr;
122}
123
Andreas Huber881227d2016-08-02 14:20:21 -0700124void EnumType::emitReaderWriter(
125 Formatter &out,
126 const std::string &name,
127 const std::string &parcelObj,
128 bool parcelObjIsPointer,
129 bool isReader,
130 ErrorMode mode) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700131 const ScalarType *scalarType = mStorageType->resolveToScalarType();
132 CHECK(scalarType != NULL);
133
134 scalarType->emitReaderWriterWithCast(
135 out,
136 name,
137 parcelObj,
138 parcelObjIsPointer,
139 isReader,
140 mode,
141 true /* needsCast */);
Andreas Huber881227d2016-08-02 14:20:21 -0700142}
143
Andreas Huber85eabdb2016-08-25 11:24:49 -0700144void EnumType::emitJavaFieldReaderWriter(
145 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700146 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700147 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700148 const std::string &blobName,
149 const std::string &fieldName,
150 const std::string &offset,
151 bool isReader) const {
152 return mStorageType->emitJavaFieldReaderWriter(
Andreas Huber709b62d2016-09-19 11:21:18 -0700153 out, depth, parcelName, blobName, fieldName, offset, isReader);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700154}
155
Andreas Huber881227d2016-08-02 14:20:21 -0700156status_t EnumType::emitTypeDeclarations(Formatter &out) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700157 const ScalarType *scalarType = mStorageType->resolveToScalarType();
Andreas Hubere3f769a2016-10-10 10:54:44 -0700158 CHECK(scalarType != nullptr);
Andreas Huber737080b2016-08-02 15:38:04 -0700159
Yifan Hong3b320f82016-11-01 15:15:54 -0700160 const std::string storageType = scalarType->getCppStackType();
Andreas Huber881227d2016-08-02 14:20:21 -0700161
162 out << "enum class "
Andreas Huber0e00de42016-08-03 09:56:02 -0700163 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700164 << " : "
Andreas Hubere3f769a2016-10-10 10:54:44 -0700165 << storageType
Andreas Huber881227d2016-08-02 14:20:21 -0700166 << " {\n";
167
168 out.indent();
169
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700170 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700171 getTypeChain(&chain);
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700172
173 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
174 const auto &type = *it;
175
176 for (const auto &entry : type->values()) {
177 out << entry->name();
178
Yifan Hongfc610cd2016-09-22 13:34:45 -0700179 std::string value = entry->cppValue(scalarType->getKind());
Yifan Hongf24fa852016-09-23 11:03:15 -0700180 CHECK(!value.empty()); // use autofilled values for c++.
181 out << " = " << value;
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700182
Yifan Hong57886972016-08-17 10:42:15 -0700183 out << ",";
184
Yifan Hongfc610cd2016-09-22 13:34:45 -0700185 std::string comment = entry->comment();
186 if (!comment.empty() && comment != value) {
Yifan Hong57886972016-08-17 10:42:15 -0700187 out << " // " << comment;
188 }
189
190 out << "\n";
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700191 }
Andreas Huber881227d2016-08-02 14:20:21 -0700192 }
193
194 out.unindent();
195 out << "};\n\n";
196
197 return OK;
198}
199
Jayant Chowdhary2820f8a2016-11-10 12:29:09 -0800200void EnumType::emitEnumBitwiseOperator(
201 Formatter &out,
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800202 bool lhsIsEnum,
203 bool rhsIsEnum,
Jayant Chowdhary2820f8a2016-11-10 12:29:09 -0800204 const std::string &op) const {
Andreas Hubere3f769a2016-10-10 10:54:44 -0700205 const ScalarType *scalarType = mStorageType->resolveToScalarType();
206 CHECK(scalarType != nullptr);
207
Yifan Hong3b320f82016-11-01 15:15:54 -0700208 const std::string storageType = scalarType->getCppStackType();
Andreas Hubere3f769a2016-10-10 10:54:44 -0700209
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800210 out << "constexpr "
211 << storageType
Jayant Chowdhary2820f8a2016-11-10 12:29:09 -0800212 << " operator"
213 << op
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800214 << "(const "
215 << (lhsIsEnum ? fullName() : storageType)
216 << " lhs, const "
217 << (rhsIsEnum ? fullName() : storageType)
Andreas Hubere3f769a2016-10-10 10:54:44 -0700218 << " rhs) {\n";
Andreas Hubere3f769a2016-10-10 10:54:44 -0700219
Yifan Hong33223ca2016-12-13 15:07:35 -0800220 out.indent([&] {
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800221 out << "return static_cast<"
222 << storageType
223 << ">(";
Andreas Hubere3f769a2016-10-10 10:54:44 -0700224
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800225 if (lhsIsEnum) {
226 out << "static_cast<"
227 << storageType
228 << ">(lhs)";
229 } else {
230 out << "lhs";
231 }
232 out << " " << op << " ";
233 if (rhsIsEnum) {
234 out << "static_cast<"
235 << storageType
236 << ">(rhs)";
237 } else {
238 out << "rhs";
239 }
240 out << ");\n";
241 });
Andreas Hubere3f769a2016-10-10 10:54:44 -0700242
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800243 out << "}\n\n";
244}
245
246void EnumType::emitBitFieldBitwiseAssignmentOperator(
247 Formatter &out,
248 const std::string &op) const {
249 const ScalarType *scalarType = mStorageType->resolveToScalarType();
250 CHECK(scalarType != nullptr);
251
252 const std::string storageType = scalarType->getCppStackType();
253
254 out << "constexpr " << storageType << " &operator" << op << "=("
255 << storageType << "& v, const " << fullName() << " e) {\n";
256
Yifan Hong33223ca2016-12-13 15:07:35 -0800257 out.indent([&] {
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800258 out << "v " << op << "= static_cast<" << storageType << ">(e);\n";
259 out << "return v;\n";
260 });
Andreas Hubere3f769a2016-10-10 10:54:44 -0700261
262 out << "}\n\n";
263}
264
265status_t EnumType::emitGlobalTypeDeclarations(Formatter &out) const {
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800266 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "|");
267 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "|");
268 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "|");
269 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "&");
270 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "&");
271 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "&");
272
273 emitBitFieldBitwiseAssignmentOperator(out, "|");
274 emitBitFieldBitwiseAssignmentOperator(out, "&");
Andreas Hubere3f769a2016-10-10 10:54:44 -0700275
Yifan Hong870d1a72017-02-22 14:24:17 -0800276 // toString for bitfields, equivalent to dumpBitfield in Java
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800277 out << "template<typename>\n"
278 << "std::string toString("
279 << resolveToScalarType()->getCppArgumentType()
280 << " o);\n";
281 out << "template<>\n"
282 << "std::string toString<" << getCppStackType() << ">("
283 << resolveToScalarType()->getCppArgumentType()
284 << " o);\n\n";
285
Yifan Hong870d1a72017-02-22 14:24:17 -0800286 // toString for enum itself
287 out << "std::string toString("
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800288 << getCppArgumentType()
Yifan Hong870d1a72017-02-22 14:24:17 -0800289 << " o);\n\n";
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800290
291 return OK;
292}
293
294status_t EnumType::emitTypeDefinitions(Formatter &out, const std::string /* prefix */) const {
295
296 const ScalarType *scalarType = mStorageType->resolveToScalarType();
297 CHECK(scalarType != NULL);
298
299 out << "template<>\n"
300 << "std::string toString<" << getCppStackType() << ">("
Yifan Hong870d1a72017-02-22 14:24:17 -0800301 << scalarType->getCppArgumentType()
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800302 << " o) ";
303 out.block([&] {
304 // include toHexString for scalar types
305 out << "using ::android::hardware::details::toHexString;\n"
Yifan Hong870d1a72017-02-22 14:24:17 -0800306 << "std::string os;\n"
307 << getBitfieldType()->getCppStackType() << " flipped = 0;\n"
308 << "bool first = true;\n";
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800309 for (EnumValue *value : values()) {
Yifan Hong870d1a72017-02-22 14:24:17 -0800310 std::string valueName = fullName() + "::" + value->name();
311 out.sIf("(o & " + valueName + ")" +
312 " == static_cast<" + scalarType->getCppStackType() +
313 ">(" + valueName + ")", [&] {
314 out << "os += (first ? \"\" : \" | \");\n"
315 << "os += \"" << value->name() << "\";\n"
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800316 << "first = false;\n"
Yifan Hong870d1a72017-02-22 14:24:17 -0800317 << "flipped |= " << valueName << ";\n";
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800318 }).endl();
319 }
Yifan Hong870d1a72017-02-22 14:24:17 -0800320 // put remaining bits
321 out.sIf("o != flipped", [&] {
322 out << "os += (first ? \"\" : \" | \");\n";
323 scalarType->emitHexDump(out, "os", "o & (~flipped)");
324 });
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800325 out << "os += \" (\";\n";
326 scalarType->emitHexDump(out, "os", "o");
327 out << "os += \")\";\n";
328
329 out << "return os;\n";
330 }).endl().endl();
331
Yifan Hong870d1a72017-02-22 14:24:17 -0800332 out << "std::string toString("
333 << getCppArgumentType()
334 << " o) ";
335
336 out.block([&] {
337 out << "using ::android::hardware::details::toHexString;\n";
338 for (EnumValue *value : values()) {
339 out.sIf("o == " + fullName() + "::" + value->name(), [&] {
340 out << "return \"" << value->name() << "\";\n";
341 }).endl();
342 }
343 out << "std::string os;\n";
344 scalarType->emitHexDump(out, "os",
345 "static_cast<" + scalarType->getCppStackType() + ">(o)");
346 out << "return os;\n";
347 }).endl().endl();
348
Andreas Hubere3f769a2016-10-10 10:54:44 -0700349 return OK;
350}
351
Yifan Honge45b5302017-02-22 10:49:07 -0800352status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool atTopLevel) const {
Andreas Huber2831d512016-08-15 09:33:47 -0700353 const ScalarType *scalarType = mStorageType->resolveToScalarType();
354 CHECK(scalarType != NULL);
355
Yifan Honge45b5302017-02-22 10:49:07 -0800356 out << "public "
357 << (atTopLevel ? "" : "static ")
358 << "final class "
Andreas Huber2831d512016-08-15 09:33:47 -0700359 << localName()
360 << " {\n";
361
362 out.indent();
363
Andreas Huber4c865b72016-09-14 15:26:27 -0700364 const std::string typeName =
Yifan Hong4ed13472016-11-02 10:44:11 -0700365 scalarType->getJavaType(false /* forInitializer */);
Andreas Huber2831d512016-08-15 09:33:47 -0700366
367 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700368 getTypeChain(&chain);
Andreas Huber2831d512016-08-15 09:33:47 -0700369
370 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
371 const auto &type = *it;
372
373 for (const auto &entry : type->values()) {
374 out << "public static final "
375 << typeName
376 << " "
Andreas Huberab647c02016-09-14 09:44:00 -0700377 << entry->name()
378 << " = ";
Andreas Huber2831d512016-08-15 09:33:47 -0700379
Yifan Hongf24fa852016-09-23 11:03:15 -0700380 // javaValue will make the number signed.
Yifan Hongfc610cd2016-09-22 13:34:45 -0700381 std::string value = entry->javaValue(scalarType->getKind());
Yifan Hongf24fa852016-09-23 11:03:15 -0700382 CHECK(!value.empty()); // use autofilled values for java.
383 out << value;
Andreas Huber2831d512016-08-15 09:33:47 -0700384
Yifan Hong19ca75a2016-08-31 10:20:03 -0700385 out << ";";
386
Yifan Hongfc610cd2016-09-22 13:34:45 -0700387 std::string comment = entry->comment();
388 if (!comment.empty() && comment != value) {
Yifan Hong19ca75a2016-08-31 10:20:03 -0700389 out << " // " << comment;
390 }
391
392 out << "\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700393 }
394 }
395
Yifan Honge45b5302017-02-22 10:49:07 -0800396 out << "public static final String toString("
397 << typeName << " o) ";
398 out.block([&] {
399 for (EnumValue *value : values()) {
400 out.sIf("o == " + value->name(), [&] {
401 out << "return \"" << value->name() << "\";\n";
402 }).endl();
403 }
404 out << "return \"0x\" + ";
405 scalarType->emitConvertToJavaHexString(out, "o");
406 out << ";\n";
407 }).endl();
408
409 auto bitfieldType = getBitfieldType()->getJavaType(false /* forInitializer */);
410 auto bitfieldWrapperType = getBitfieldType()->getJavaWrapperType();
411 out << "\n"
412 << "public static final String dumpBitfield("
413 << bitfieldType << " o) ";
414 out.block([&] {
415 out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n";
416 out << bitfieldType << " flipped = 0;\n";
417 for (EnumValue *value : values()) {
Yifan Hongdd7c5742017-07-06 13:16:30 -0700418 if (value->constExpr()->castSizeT() == 0) {
419 out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n";
420 continue;
421 }
Yifan Honge45b5302017-02-22 10:49:07 -0800422 out.sIf("(o & " + value->name() + ") == " + value->name(), [&] {
423 out << "list.add(\"" << value->name() << "\");\n";
424 out << "flipped |= " << value->name() << ";\n";
425 }).endl();
426 }
427 // put remaining bits
428 out.sIf("o != flipped", [&] {
429 out << "list.add(\"0x\" + ";
430 scalarType->emitConvertToJavaHexString(out, "o & (~flipped)");
431 out << ");\n";
432 }).endl();
433 out << "return String.join(\" | \", list);\n";
434 }).endl().endl();
435
Andreas Huber2831d512016-08-15 09:33:47 -0700436 out.unindent();
437 out << "};\n\n";
438
439 return OK;
440}
441
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700442status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
Yifan Hongc07b2022016-11-08 12:44:24 -0800443 const ScalarType *scalarType = mStorageType->resolveToScalarType();
444
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700445 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700446 out << "type: " << getVtsType() << "\n";
447 out << "enum_value: {\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700448 out.indent();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700449
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700450 out << "scalar_type: \""
Yifan Hongc07b2022016-11-08 12:44:24 -0800451 << scalarType->getVtsScalarType()
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700452 << "\"\n\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700453 std::vector<const EnumType *> chain;
454 getTypeChain(&chain);
455
456 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
457 const auto &type = *it;
458
459 for (const auto &entry : type->values()) {
460 out << "enumerator: \"" << entry->name() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700461 out << "scalar_value: {\n";
462 out.indent();
Yifan Hongc07b2022016-11-08 12:44:24 -0800463 // use autofilled values for vts.
464 std::string value = entry->value(scalarType->getKind());
465 CHECK(!value.empty());
466 out << mStorageType->resolveToScalarType()->getVtsScalarType()
467 << ": "
468 << value
469 << "\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700470 out.unindent();
471 out << "}\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700472 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700473 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700474
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700475 out.unindent();
476 out << "}\n";
477 return OK;
478}
479
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700480status_t EnumType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700481 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700482 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700483 return OK;
484}
485
Yifan Honge45b5302017-02-22 10:49:07 -0800486void EnumType::emitJavaDump(
487 Formatter &out,
488 const std::string &streamName,
489 const std::string &name) const {
490 out << streamName << ".append(" << fqName().javaName() << ".toString("
491 << name << "));\n";
492}
493
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700494void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
495 out->clear();
496 const EnumType *type = this;
497 for (;;) {
498 out->push_back(type);
499
500 const Type *superType = type->storageType();
501 if (superType == NULL || !superType->isEnum()) {
502 break;
503 }
504
505 type = static_cast<const EnumType *>(superType);
506 }
507}
508
Andreas Huber85eabdb2016-08-25 11:24:49 -0700509void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
510 mStorageType->getAlignmentAndSize(align, size);
511}
512
Andreas Huber019d21d2016-10-03 12:59:47 -0700513const Annotation *EnumType::findExportAnnotation() const {
514 for (const auto &annotation : annotations()) {
515 if (annotation->name() == "export") {
516 return annotation;
517 }
518 }
519
520 return nullptr;
521}
522
523void EnumType::appendToExportedTypesVector(
524 std::vector<const Type *> *exportedTypes) const {
525 if (findExportAnnotation() != nullptr) {
526 exportedTypes->push_back(this);
527 }
528}
529
Andreas Huber1c507272016-10-05 14:33:21 -0700530status_t EnumType::emitExportedHeader(Formatter &out, bool forJava) const {
Andreas Huber019d21d2016-10-03 12:59:47 -0700531 const Annotation *annotation = findExportAnnotation();
532 CHECK(annotation != nullptr);
533
534 std::string name = localName();
535
536 const AnnotationParam *nameParam = annotation->getParam("name");
537 if (nameParam != nullptr) {
Steven Morelanddb1b1b62017-01-10 09:50:55 -0800538 name = nameParam->getSingleString();
539 }
Andreas Huber019d21d2016-10-03 12:59:47 -0700540
Steven Morelanddb1b1b62017-01-10 09:50:55 -0800541 bool exportParent = true;
542 const AnnotationParam *exportParentParam = annotation->getParam("export_parent");
543 if (exportParentParam != nullptr) {
544 exportParent = exportParentParam->getSingleBool();
Andreas Huber019d21d2016-10-03 12:59:47 -0700545 }
546
Andreas Huberb0627fb2016-10-10 09:39:28 -0700547 std::string valuePrefix;
Andreas Huberb0627fb2016-10-10 09:39:28 -0700548 const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
549 if (prefixParam != nullptr) {
Steven Morelanddb1b1b62017-01-10 09:50:55 -0800550 valuePrefix = prefixParam->getSingleString();
Andreas Huberb0627fb2016-10-10 09:39:28 -0700551 }
552
Steven Moreland73cdc882016-11-21 16:43:50 -0800553 std::string valueSuffix;
554 const AnnotationParam *suffixParam = annotation->getParam("value_suffix");
555 if (suffixParam != nullptr) {
Steven Morelanddb1b1b62017-01-10 09:50:55 -0800556 valueSuffix = suffixParam->getSingleString();
Steven Moreland73cdc882016-11-21 16:43:50 -0800557 }
558
Andreas Huber019d21d2016-10-03 12:59:47 -0700559 const ScalarType *scalarType = mStorageType->resolveToScalarType();
Andreas Huber1c507272016-10-05 14:33:21 -0700560 CHECK(scalarType != nullptr);
Andreas Huber019d21d2016-10-03 12:59:47 -0700561
Steven Morelanddb1b1b62017-01-10 09:50:55 -0800562 std::vector<const EnumType *> chain;
563 if (exportParent) {
564 getTypeChain(&chain);
565 } else {
566 chain = { this };
567 }
568
Andreas Huber1c507272016-10-05 14:33:21 -0700569 if (forJava) {
570 if (!name.empty()) {
571 out << "public final class "
572 << name
573 << " {\n";
574
575 out.indent();
576 } else {
577 out << "// Values declared in " << localName() << " follow.\n";
578 }
579
Andreas Huber1c507272016-10-05 14:33:21 -0700580 const std::string typeName =
Yifan Hong4ed13472016-11-02 10:44:11 -0700581 scalarType->getJavaType(false /* forInitializer */);
Andreas Huber1c507272016-10-05 14:33:21 -0700582
Andreas Huber1c507272016-10-05 14:33:21 -0700583 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
584 const auto &type = *it;
585
586 for (const auto &entry : type->values()) {
587 out << "public static final "
588 << typeName
589 << " "
590 << valuePrefix
591 << entry->name()
Steven Moreland73cdc882016-11-21 16:43:50 -0800592 << valueSuffix
Andreas Huber1c507272016-10-05 14:33:21 -0700593 << " = ";
594
595 // javaValue will make the number signed.
596 std::string value = entry->javaValue(scalarType->getKind());
597 CHECK(!value.empty()); // use autofilled values for java.
598 out << value;
599
600 out << ";";
601
602 std::string comment = entry->comment();
603 if (!comment.empty() && comment != value) {
604 out << " // " << comment;
605 }
606
607 out << "\n";
608 }
609 }
610
611 if (!name.empty()) {
612 out.unindent();
613 out << "};\n";
614 }
615 out << "\n";
616
617 return OK;
618 }
Andreas Huber019d21d2016-10-03 12:59:47 -0700619
620 if (!name.empty()) {
621 out << "typedef ";
622 }
623
624 out << "enum {\n";
625
626 out.indent();
627
Andreas Huber019d21d2016-10-03 12:59:47 -0700628 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
629 const auto &type = *it;
630
631 for (const auto &entry : type->values()) {
Steven Moreland73cdc882016-11-21 16:43:50 -0800632 out << valuePrefix << entry->name() << valueSuffix;
Andreas Huber019d21d2016-10-03 12:59:47 -0700633
634 std::string value = entry->cppValue(scalarType->getKind());
635 CHECK(!value.empty()); // use autofilled values for c++.
636 out << " = " << value;
637
638 out << ",";
639
640 std::string comment = entry->comment();
641 if (!comment.empty() && comment != value) {
642 out << " // " << comment;
643 }
644
645 out << "\n";
646 }
647 }
648
649 out.unindent();
650 out << "}";
651
652 if (!name.empty()) {
653 out << " " << name;
654 }
655
656 out << ";\n\n";
657
658 return OK;
659}
660
Andreas Huber31629bc2016-08-03 09:06:40 -0700661////////////////////////////////////////////////////////////////////////////////
662
Yifan Hongf24fa852016-09-23 11:03:15 -0700663EnumValue::EnumValue(const char *name, ConstantExpression *value)
Andreas Huber31629bc2016-08-03 09:06:40 -0700664 : mName(name),
Yifan Hongf24fa852016-09-23 11:03:15 -0700665 mValue(value),
666 mIsAutoFill(false) {
Andreas Huber31629bc2016-08-03 09:06:40 -0700667}
668
669std::string EnumValue::name() const {
670 return mName;
671}
672
Yifan Hongc07b2022016-11-08 12:44:24 -0800673std::string EnumValue::value(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700674 CHECK(mValue != nullptr);
Yifan Hongc07b2022016-11-08 12:44:24 -0800675 return mValue->value(castKind);
Yifan Hong57886972016-08-17 10:42:15 -0700676}
677
Yifan Hongfc610cd2016-09-22 13:34:45 -0700678std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700679 CHECK(mValue != nullptr);
680 return mValue->cppValue(castKind);
Yifan Hong57886972016-08-17 10:42:15 -0700681}
Yifan Hongfc610cd2016-09-22 13:34:45 -0700682std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700683 CHECK(mValue != nullptr);
684 return mValue->javaValue(castKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700685}
Yifan Hong57886972016-08-17 10:42:15 -0700686
Yifan Hongfc610cd2016-09-22 13:34:45 -0700687std::string EnumValue::comment() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700688 CHECK(mValue != nullptr);
689 return mValue->description();
690}
691
692ConstantExpression *EnumValue::constExpr() const {
693 CHECK(mValue != nullptr);
694 return mValue;
695}
696
697void EnumValue::autofill(const EnumValue *prev, const ScalarType *type) {
698 if(mValue != nullptr)
699 return;
700 mIsAutoFill = true;
701 ConstantExpression *value = new ConstantExpression();
702 if(prev == nullptr) {
703 *value = ConstantExpression::Zero(type->getKind());
704 } else {
705 CHECK(prev->mValue != nullptr);
706 *value = prev->mValue->addOne();
707 }
708 mValue = value;
709}
710
711bool EnumValue::isAutoFill() const {
712 return mIsAutoFill;
713}
714
715bool EnumValue::isEnumValue() const {
716 return true;
Andreas Huber31629bc2016-08-03 09:06:40 -0700717}
718
Yifan Hongabf73ee2016-12-05 18:47:00 -0800719////////////////////////////////////////////////////////////////////////////////
720
721bool BitFieldType::isBitField() const {
722 return true;
723}
724
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800725std::string BitFieldType::typeName() const {
726 return "mask" + (mElementType == nullptr ? "" : (" of " + mElementType->typeName()));
727}
728
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800729bool BitFieldType::isCompatibleElementType(Type *elementType) const {
730 return elementType->isEnum();
731}
732
733const ScalarType *BitFieldType::resolveToScalarType() const {
734 return mElementType->resolveToScalarType();
735}
736
737std::string BitFieldType::getCppType(StorageMode mode,
738 bool specifyNamespaces) const {
739 return resolveToScalarType()->getCppType(mode, specifyNamespaces);
740}
741
742std::string BitFieldType::getJavaType(bool forInitializer) const {
743 return resolveToScalarType()->getJavaType(forInitializer);
744}
745
746std::string BitFieldType::getJavaSuffix() const {
747 return resolveToScalarType()->getJavaSuffix();
748}
749
750std::string BitFieldType::getJavaWrapperType() const {
751 return resolveToScalarType()->getJavaWrapperType();
752}
753
754std::string BitFieldType::getVtsType() const {
755 return "TYPE_MASK";
756}
757
Yifan Hong8c56cbe2016-12-12 15:30:12 -0800758bool BitFieldType::isElidableType() const {
759 return resolveToScalarType()->isElidableType();
760}
761
Yifan Hong7d1839f2017-02-22 13:24:29 -0800762bool BitFieldType::canCheckEquality() const {
763 return resolveToScalarType()->canCheckEquality();
764}
765
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800766status_t BitFieldType::emitVtsAttributeType(Formatter &out) const {
767 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang13236232017-01-24 14:27:55 -0800768 out << "scalar_type: \""
769 << mElementType->resolveToScalarType()->getVtsScalarType()
770 << "\"\n";
Keun Soo Yim36ccc722017-01-13 13:27:33 -0800771 out << "predefined_type: \""
772 << static_cast<NamedType *>(mElementType)->fullName() << "\"\n";
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800773 return OK;
774}
775
776void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
777 resolveToScalarType()->getAlignmentAndSize(align, size);
778}
779
780void BitFieldType::emitReaderWriter(
781 Formatter &out,
782 const std::string &name,
783 const std::string &parcelObj,
784 bool parcelObjIsPointer,
785 bool isReader,
786 ErrorMode mode) const {
787 resolveToScalarType()->emitReaderWriterWithCast(
788 out,
789 name,
790 parcelObj,
791 parcelObjIsPointer,
792 isReader,
793 mode,
794 true /* needsCast */);
795}
796
Yifan Honge45b5302017-02-22 10:49:07 -0800797EnumType *BitFieldType::getEnumType() const {
798 CHECK(mElementType->isEnum());
799 return static_cast<EnumType *>(mElementType);
800}
801
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800802// a bitfield maps to the underlying scalar type in C++, so operator<< is
803// already defined. We can still emit useful information if the bitfield is
804// in a struct / union by overriding emitDump as below.
805void BitFieldType::emitDump(
806 Formatter &out,
807 const std::string &streamName,
808 const std::string &name) const {
Yifan Honge45b5302017-02-22 10:49:07 -0800809 out << streamName << " += "<< getEnumType()->fqName().cppNamespace()
810 << "::toString<" << getEnumType()->getCppStackType()
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800811 << ">(" << name << ");\n";
812}
813
Yifan Honge45b5302017-02-22 10:49:07 -0800814void BitFieldType::emitJavaDump(
815 Formatter &out,
816 const std::string &streamName,
817 const std::string &name) const {
818 out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield("
819 << name << "));\n";
820}
821
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800822void BitFieldType::emitJavaFieldReaderWriter(
823 Formatter &out,
824 size_t depth,
825 const std::string &parcelName,
826 const std::string &blobName,
827 const std::string &fieldName,
828 const std::string &offset,
829 bool isReader) const {
830 return resolveToScalarType()->emitJavaFieldReaderWriter(
831 out, depth, parcelName, blobName, fieldName, offset, isReader);
832}
833
Andreas Huberc9410c72016-07-28 12:18:40 -0700834} // namespace android
835