blob: eaadc230e7915c81ba3a4e16067dff55c5fa5981 [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"
Timur Iskhakov505316c2017-08-05 03:38:59 +000020#include "Location.h"
Andreas Huber881227d2016-08-02 14:20:21 -070021#include "ScalarType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070022
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070023#include <inttypes.h>
24#include <hidl-util/Formatter.h>
Andreas Huber737080b2016-08-02 15:38:04 -070025#include <android-base/logging.h>
26
Andreas Huberc9410c72016-07-28 12:18:40 -070027namespace android {
28
Timur Iskhakov505316c2017-08-05 03:38:59 +000029EnumType::EnumType(const char* localName, const Location& location,
30 const Reference<Type>& storageType, Scope* parent)
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070031 : Scope(localName, location, parent), mValues(), mStorageType(storageType) {
Timur Iskhakov505316c2017-08-05 03:38:59 +000032 BitFieldType* bitfieldType = new BitFieldType();
33 bitfieldType->setElementType(Reference<Type>(this, Location()));
34 mBitfieldType.set(bitfieldType);
Andreas Huberc9410c72016-07-28 12:18:40 -070035}
36
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070037const Type *EnumType::storageType() const {
38 return mStorageType;
39}
40
41const std::vector<EnumValue *> &EnumType::values() const {
Yifan Hongf24fa852016-09-23 11:03:15 -070042 return mValues;
43}
44
45void EnumType::addValue(EnumValue *value) {
46 CHECK(value != nullptr);
47
48 EnumValue *prev = nullptr;
Timur Iskhakovf1b902d2017-08-13 20:14:31 -070049 std::vector<const EnumType*> chain = typeChain();
Yifan Hongf24fa852016-09-23 11:03:15 -070050 for (auto it = chain.begin(); it != chain.end(); ++it) {
51 const auto &type = *it;
52 if(!type->values().empty()) {
53 prev = type->values().back();
54 break;
55 }
56 }
57
58 value->autofill(prev, resolveToScalarType());
59 mValues.push_back(value);
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070060}
61
Steven Moreland9df52442016-12-12 08:51:14 -080062bool EnumType::isElidableType() const {
63 return mStorageType->isElidableType();
64}
65
Andreas Huber737080b2016-08-02 15:38:04 -070066const ScalarType *EnumType::resolveToScalarType() const {
67 return mStorageType->resolveToScalarType();
68}
69
Steven Moreland30bb6a82016-11-30 09:18:34 -080070std::string EnumType::typeName() const {
71 return "enum " + localName();
72}
73
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070074bool EnumType::isEnum() const {
75 return true;
76}
77
Yifan Hongc6752dc2016-12-20 14:00:14 -080078bool EnumType::canCheckEquality() const {
79 return true;
80}
81
Steven Moreland979e0992016-09-07 09:18:08 -070082std::string EnumType::getCppType(StorageMode,
Steven Morelande30ee9b2017-05-09 13:31:01 -070083 bool /* specifyNamespaces */) const {
84 return fullName();
Andreas Huber881227d2016-08-02 14:20:21 -070085}
86
Yifan Hong4ed13472016-11-02 10:44:11 -070087std::string EnumType::getJavaType(bool forInitializer) const {
88 return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
Andreas Huber2831d512016-08-15 09:33:47 -070089}
90
91std::string EnumType::getJavaSuffix() const {
92 return mStorageType->resolveToScalarType()->getJavaSuffix();
93}
94
Andreas Hubera3558b32016-09-14 09:12:42 -070095std::string EnumType::getJavaWrapperType() const {
96 return mStorageType->resolveToScalarType()->getJavaWrapperType();
97}
98
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -070099std::string EnumType::getVtsType() const {
100 return "TYPE_ENUM";
101}
102
Timur Iskhakov505316c2017-08-05 03:38:59 +0000103BitFieldType* EnumType::getBitfieldType() const {
Yifan Honge45b5302017-02-22 10:49:07 -0800104 return mBitfieldType;
105}
106
Yifan Hongf24fa852016-09-23 11:03:15 -0700107LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
Timur Iskhakovf1b902d2017-08-13 20:14:31 -0700108 std::vector<const EnumType*> chain = typeChain();
Yifan Hongf24fa852016-09-23 11:03:15 -0700109 for (auto it = chain.begin(); it != chain.end(); ++it) {
110 const auto &type = *it;
111 for(EnumValue *v : type->values()) {
112 if(v->name() == name) {
113 return v;
114 }
115 }
116 }
117 return nullptr;
118}
119
Andreas Huber881227d2016-08-02 14:20:21 -0700120void EnumType::emitReaderWriter(
121 Formatter &out,
122 const std::string &name,
123 const std::string &parcelObj,
124 bool parcelObjIsPointer,
125 bool isReader,
126 ErrorMode mode) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700127 const ScalarType *scalarType = mStorageType->resolveToScalarType();
128 CHECK(scalarType != NULL);
129
130 scalarType->emitReaderWriterWithCast(
131 out,
132 name,
133 parcelObj,
134 parcelObjIsPointer,
135 isReader,
136 mode,
137 true /* needsCast */);
Andreas Huber881227d2016-08-02 14:20:21 -0700138}
139
Andreas Huber85eabdb2016-08-25 11:24:49 -0700140void EnumType::emitJavaFieldReaderWriter(
141 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700142 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700143 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700144 const std::string &blobName,
145 const std::string &fieldName,
146 const std::string &offset,
147 bool isReader) const {
148 return mStorageType->emitJavaFieldReaderWriter(
Andreas Huber709b62d2016-09-19 11:21:18 -0700149 out, depth, parcelName, blobName, fieldName, offset, isReader);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700150}
151
Andreas Huber881227d2016-08-02 14:20:21 -0700152status_t EnumType::emitTypeDeclarations(Formatter &out) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700153 const ScalarType *scalarType = mStorageType->resolveToScalarType();
Andreas Hubere3f769a2016-10-10 10:54:44 -0700154 CHECK(scalarType != nullptr);
Andreas Huber737080b2016-08-02 15:38:04 -0700155
Yifan Hong3b320f82016-11-01 15:15:54 -0700156 const std::string storageType = scalarType->getCppStackType();
Andreas Huber881227d2016-08-02 14:20:21 -0700157
158 out << "enum class "
Andreas Huber0e00de42016-08-03 09:56:02 -0700159 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700160 << " : "
Andreas Hubere3f769a2016-10-10 10:54:44 -0700161 << storageType
Andreas Huber881227d2016-08-02 14:20:21 -0700162 << " {\n";
163
164 out.indent();
165
Timur Iskhakovf1b902d2017-08-13 20:14:31 -0700166 std::vector<const EnumType*> chain = typeChain();
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700167
168 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
169 const auto &type = *it;
170
171 for (const auto &entry : type->values()) {
172 out << entry->name();
173
Yifan Hongfc610cd2016-09-22 13:34:45 -0700174 std::string value = entry->cppValue(scalarType->getKind());
Yifan Hongf24fa852016-09-23 11:03:15 -0700175 CHECK(!value.empty()); // use autofilled values for c++.
176 out << " = " << value;
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700177
Yifan Hong57886972016-08-17 10:42:15 -0700178 out << ",";
179
Yifan Hongfc610cd2016-09-22 13:34:45 -0700180 std::string comment = entry->comment();
181 if (!comment.empty() && comment != value) {
Yifan Hong57886972016-08-17 10:42:15 -0700182 out << " // " << comment;
183 }
184
185 out << "\n";
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700186 }
Andreas Huber881227d2016-08-02 14:20:21 -0700187 }
188
189 out.unindent();
190 out << "};\n\n";
191
192 return OK;
193}
194
Jayant Chowdhary2820f8a2016-11-10 12:29:09 -0800195void EnumType::emitEnumBitwiseOperator(
196 Formatter &out,
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800197 bool lhsIsEnum,
198 bool rhsIsEnum,
Jayant Chowdhary2820f8a2016-11-10 12:29:09 -0800199 const std::string &op) const {
Andreas Hubere3f769a2016-10-10 10:54:44 -0700200 const ScalarType *scalarType = mStorageType->resolveToScalarType();
201 CHECK(scalarType != nullptr);
202
Yifan Hong3b320f82016-11-01 15:15:54 -0700203 const std::string storageType = scalarType->getCppStackType();
Andreas Hubere3f769a2016-10-10 10:54:44 -0700204
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800205 out << "constexpr "
206 << storageType
Jayant Chowdhary2820f8a2016-11-10 12:29:09 -0800207 << " operator"
208 << op
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800209 << "(const "
210 << (lhsIsEnum ? fullName() : storageType)
211 << " lhs, const "
212 << (rhsIsEnum ? fullName() : storageType)
Andreas Hubere3f769a2016-10-10 10:54:44 -0700213 << " rhs) {\n";
Andreas Hubere3f769a2016-10-10 10:54:44 -0700214
Yifan Hong33223ca2016-12-13 15:07:35 -0800215 out.indent([&] {
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800216 out << "return static_cast<"
217 << storageType
218 << ">(";
Andreas Hubere3f769a2016-10-10 10:54:44 -0700219
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800220 if (lhsIsEnum) {
221 out << "static_cast<"
222 << storageType
223 << ">(lhs)";
224 } else {
225 out << "lhs";
226 }
227 out << " " << op << " ";
228 if (rhsIsEnum) {
229 out << "static_cast<"
230 << storageType
231 << ">(rhs)";
232 } else {
233 out << "rhs";
234 }
235 out << ");\n";
236 });
Andreas Hubere3f769a2016-10-10 10:54:44 -0700237
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800238 out << "}\n\n";
239}
240
241void EnumType::emitBitFieldBitwiseAssignmentOperator(
242 Formatter &out,
243 const std::string &op) const {
244 const ScalarType *scalarType = mStorageType->resolveToScalarType();
245 CHECK(scalarType != nullptr);
246
247 const std::string storageType = scalarType->getCppStackType();
248
249 out << "constexpr " << storageType << " &operator" << op << "=("
250 << storageType << "& v, const " << fullName() << " e) {\n";
251
Yifan Hong33223ca2016-12-13 15:07:35 -0800252 out.indent([&] {
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800253 out << "v " << op << "= static_cast<" << storageType << ">(e);\n";
254 out << "return v;\n";
255 });
Andreas Hubere3f769a2016-10-10 10:54:44 -0700256
257 out << "}\n\n";
258}
259
260status_t EnumType::emitGlobalTypeDeclarations(Formatter &out) const {
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800261 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "|");
262 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "|");
263 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "|");
264 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "&");
265 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "&");
266 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "&");
267
268 emitBitFieldBitwiseAssignmentOperator(out, "|");
269 emitBitFieldBitwiseAssignmentOperator(out, "&");
Andreas Hubere3f769a2016-10-10 10:54:44 -0700270
Yifan Hong870d1a72017-02-22 14:24:17 -0800271 // toString for bitfields, equivalent to dumpBitfield in Java
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800272 out << "template<typename>\n"
273 << "std::string toString("
274 << resolveToScalarType()->getCppArgumentType()
275 << " o);\n";
276 out << "template<>\n"
277 << "std::string toString<" << getCppStackType() << ">("
278 << resolveToScalarType()->getCppArgumentType()
279 << " o);\n\n";
280
Yifan Hong870d1a72017-02-22 14:24:17 -0800281 // toString for enum itself
282 out << "std::string toString("
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800283 << getCppArgumentType()
Yifan Hong870d1a72017-02-22 14:24:17 -0800284 << " o);\n\n";
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800285
286 return OK;
287}
288
289status_t EnumType::emitTypeDefinitions(Formatter &out, const std::string /* prefix */) const {
290
291 const ScalarType *scalarType = mStorageType->resolveToScalarType();
292 CHECK(scalarType != NULL);
293
294 out << "template<>\n"
295 << "std::string toString<" << getCppStackType() << ">("
Yifan Hong870d1a72017-02-22 14:24:17 -0800296 << scalarType->getCppArgumentType()
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800297 << " o) ";
298 out.block([&] {
299 // include toHexString for scalar types
300 out << "using ::android::hardware::details::toHexString;\n"
Yifan Hong870d1a72017-02-22 14:24:17 -0800301 << "std::string os;\n"
302 << getBitfieldType()->getCppStackType() << " flipped = 0;\n"
303 << "bool first = true;\n";
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800304 for (EnumValue *value : values()) {
Yifan Hong870d1a72017-02-22 14:24:17 -0800305 std::string valueName = fullName() + "::" + value->name();
306 out.sIf("(o & " + valueName + ")" +
307 " == static_cast<" + scalarType->getCppStackType() +
308 ">(" + valueName + ")", [&] {
309 out << "os += (first ? \"\" : \" | \");\n"
310 << "os += \"" << value->name() << "\";\n"
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800311 << "first = false;\n"
Yifan Hong870d1a72017-02-22 14:24:17 -0800312 << "flipped |= " << valueName << ";\n";
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800313 }).endl();
314 }
Yifan Hong870d1a72017-02-22 14:24:17 -0800315 // put remaining bits
316 out.sIf("o != flipped", [&] {
317 out << "os += (first ? \"\" : \" | \");\n";
318 scalarType->emitHexDump(out, "os", "o & (~flipped)");
319 });
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800320 out << "os += \" (\";\n";
321 scalarType->emitHexDump(out, "os", "o");
322 out << "os += \")\";\n";
323
324 out << "return os;\n";
325 }).endl().endl();
326
Yifan Hong870d1a72017-02-22 14:24:17 -0800327 out << "std::string toString("
328 << getCppArgumentType()
329 << " o) ";
330
331 out.block([&] {
332 out << "using ::android::hardware::details::toHexString;\n";
333 for (EnumValue *value : values()) {
334 out.sIf("o == " + fullName() + "::" + value->name(), [&] {
335 out << "return \"" << value->name() << "\";\n";
336 }).endl();
337 }
338 out << "std::string os;\n";
339 scalarType->emitHexDump(out, "os",
340 "static_cast<" + scalarType->getCppStackType() + ">(o)");
341 out << "return os;\n";
342 }).endl().endl();
343
Andreas Hubere3f769a2016-10-10 10:54:44 -0700344 return OK;
345}
346
Yifan Honge45b5302017-02-22 10:49:07 -0800347status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool atTopLevel) const {
Andreas Huber2831d512016-08-15 09:33:47 -0700348 const ScalarType *scalarType = mStorageType->resolveToScalarType();
349 CHECK(scalarType != NULL);
350
Yifan Honge45b5302017-02-22 10:49:07 -0800351 out << "public "
352 << (atTopLevel ? "" : "static ")
353 << "final class "
Andreas Huber2831d512016-08-15 09:33:47 -0700354 << localName()
355 << " {\n";
356
357 out.indent();
358
Andreas Huber4c865b72016-09-14 15:26:27 -0700359 const std::string typeName =
Yifan Hong4ed13472016-11-02 10:44:11 -0700360 scalarType->getJavaType(false /* forInitializer */);
Andreas Huber2831d512016-08-15 09:33:47 -0700361
Timur Iskhakovf1b902d2017-08-13 20:14:31 -0700362 std::vector<const EnumType*> chain = typeChain();
Andreas Huber2831d512016-08-15 09:33:47 -0700363
364 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
365 const auto &type = *it;
366
367 for (const auto &entry : type->values()) {
368 out << "public static final "
369 << typeName
370 << " "
Andreas Huberab647c02016-09-14 09:44:00 -0700371 << entry->name()
372 << " = ";
Andreas Huber2831d512016-08-15 09:33:47 -0700373
Yifan Hongf24fa852016-09-23 11:03:15 -0700374 // javaValue will make the number signed.
Yifan Hongfc610cd2016-09-22 13:34:45 -0700375 std::string value = entry->javaValue(scalarType->getKind());
Yifan Hongf24fa852016-09-23 11:03:15 -0700376 CHECK(!value.empty()); // use autofilled values for java.
377 out << value;
Andreas Huber2831d512016-08-15 09:33:47 -0700378
Yifan Hong19ca75a2016-08-31 10:20:03 -0700379 out << ";";
380
Yifan Hongfc610cd2016-09-22 13:34:45 -0700381 std::string comment = entry->comment();
382 if (!comment.empty() && comment != value) {
Yifan Hong19ca75a2016-08-31 10:20:03 -0700383 out << " // " << comment;
384 }
385
386 out << "\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700387 }
388 }
389
Yifan Honge45b5302017-02-22 10:49:07 -0800390 out << "public static final String toString("
391 << typeName << " o) ";
392 out.block([&] {
393 for (EnumValue *value : values()) {
394 out.sIf("o == " + value->name(), [&] {
395 out << "return \"" << value->name() << "\";\n";
396 }).endl();
397 }
398 out << "return \"0x\" + ";
399 scalarType->emitConvertToJavaHexString(out, "o");
400 out << ";\n";
401 }).endl();
402
403 auto bitfieldType = getBitfieldType()->getJavaType(false /* forInitializer */);
404 auto bitfieldWrapperType = getBitfieldType()->getJavaWrapperType();
405 out << "\n"
406 << "public static final String dumpBitfield("
407 << bitfieldType << " o) ";
408 out.block([&] {
409 out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n";
410 out << bitfieldType << " flipped = 0;\n";
411 for (EnumValue *value : values()) {
Yifan Hongdd7c5742017-07-06 13:16:30 -0700412 if (value->constExpr()->castSizeT() == 0) {
413 out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n";
414 continue;
415 }
Yifan Honge45b5302017-02-22 10:49:07 -0800416 out.sIf("(o & " + value->name() + ") == " + value->name(), [&] {
417 out << "list.add(\"" << value->name() << "\");\n";
418 out << "flipped |= " << value->name() << ";\n";
419 }).endl();
420 }
421 // put remaining bits
422 out.sIf("o != flipped", [&] {
423 out << "list.add(\"0x\" + ";
424 scalarType->emitConvertToJavaHexString(out, "o & (~flipped)");
425 out << ");\n";
426 }).endl();
427 out << "return String.join(\" | \", list);\n";
428 }).endl().endl();
429
Andreas Huber2831d512016-08-15 09:33:47 -0700430 out.unindent();
431 out << "};\n\n";
432
433 return OK;
434}
435
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700436status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
Yifan Hongc07b2022016-11-08 12:44:24 -0800437 const ScalarType *scalarType = mStorageType->resolveToScalarType();
438
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700439 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700440 out << "type: " << getVtsType() << "\n";
441 out << "enum_value: {\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700442 out.indent();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700443
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700444 out << "scalar_type: \""
Yifan Hongc07b2022016-11-08 12:44:24 -0800445 << scalarType->getVtsScalarType()
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700446 << "\"\n\n";
Timur Iskhakovf1b902d2017-08-13 20:14:31 -0700447 std::vector<const EnumType*> chain = typeChain();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700448
449 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
450 const auto &type = *it;
451
452 for (const auto &entry : type->values()) {
453 out << "enumerator: \"" << entry->name() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700454 out << "scalar_value: {\n";
455 out.indent();
Yifan Hongc07b2022016-11-08 12:44:24 -0800456 // use autofilled values for vts.
457 std::string value = entry->value(scalarType->getKind());
458 CHECK(!value.empty());
459 out << mStorageType->resolveToScalarType()->getVtsScalarType()
460 << ": "
461 << value
462 << "\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700463 out.unindent();
464 out << "}\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700465 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700466 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700467
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700468 out.unindent();
469 out << "}\n";
470 return OK;
471}
472
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700473status_t EnumType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700474 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700475 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700476 return OK;
477}
478
Yifan Honge45b5302017-02-22 10:49:07 -0800479void EnumType::emitJavaDump(
480 Formatter &out,
481 const std::string &streamName,
482 const std::string &name) const {
483 out << streamName << ".append(" << fqName().javaName() << ".toString("
484 << name << "));\n";
485}
486
Timur Iskhakovf1b902d2017-08-13 20:14:31 -0700487std::vector<const EnumType*> EnumType::typeChain() const {
488 std::vector<const EnumType*> types;
489 for (const EnumType* type = this; type != nullptr;) {
490 types.push_back(type);
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700491
Timur Iskhakovf1b902d2017-08-13 20:14:31 -0700492 const Type* superType = type->storageType();
493 if (superType != nullptr && superType->isEnum()) {
494 type = static_cast<const EnumType*>(superType);
495 } else {
496 type = nullptr;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700497 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700498 }
Timur Iskhakovf1b902d2017-08-13 20:14:31 -0700499
500 return types;
501}
502
503std::vector<const EnumType*> EnumType::superTypeChain() const {
504 const Type* superType = storageType();
505 if (superType == nullptr || !superType->isEnum()) {
506 return {};
507 }
508 return static_cast<const EnumType*>(superType)->typeChain();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700509}
510
Andreas Huber85eabdb2016-08-25 11:24:49 -0700511void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
512 mStorageType->getAlignmentAndSize(align, size);
513}
514
Andreas Huber019d21d2016-10-03 12:59:47 -0700515const Annotation *EnumType::findExportAnnotation() const {
516 for (const auto &annotation : annotations()) {
517 if (annotation->name() == "export") {
518 return annotation;
519 }
520 }
521
522 return nullptr;
523}
524
525void EnumType::appendToExportedTypesVector(
526 std::vector<const Type *> *exportedTypes) const {
527 if (findExportAnnotation() != nullptr) {
528 exportedTypes->push_back(this);
529 }
530}
531
Andreas Huber1c507272016-10-05 14:33:21 -0700532status_t EnumType::emitExportedHeader(Formatter &out, bool forJava) const {
Andreas Huber019d21d2016-10-03 12:59:47 -0700533 const Annotation *annotation = findExportAnnotation();
534 CHECK(annotation != nullptr);
535
536 std::string name = localName();
537
538 const AnnotationParam *nameParam = annotation->getParam("name");
539 if (nameParam != nullptr) {
Steven Morelanddb1b1b62017-01-10 09:50:55 -0800540 name = nameParam->getSingleString();
541 }
Andreas Huber019d21d2016-10-03 12:59:47 -0700542
Steven Morelanddb1b1b62017-01-10 09:50:55 -0800543 bool exportParent = true;
544 const AnnotationParam *exportParentParam = annotation->getParam("export_parent");
545 if (exportParentParam != nullptr) {
546 exportParent = exportParentParam->getSingleBool();
Andreas Huber019d21d2016-10-03 12:59:47 -0700547 }
548
Andreas Huberb0627fb2016-10-10 09:39:28 -0700549 std::string valuePrefix;
Andreas Huberb0627fb2016-10-10 09:39:28 -0700550 const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
551 if (prefixParam != nullptr) {
Steven Morelanddb1b1b62017-01-10 09:50:55 -0800552 valuePrefix = prefixParam->getSingleString();
Andreas Huberb0627fb2016-10-10 09:39:28 -0700553 }
554
Steven Moreland73cdc882016-11-21 16:43:50 -0800555 std::string valueSuffix;
556 const AnnotationParam *suffixParam = annotation->getParam("value_suffix");
557 if (suffixParam != nullptr) {
Steven Morelanddb1b1b62017-01-10 09:50:55 -0800558 valueSuffix = suffixParam->getSingleString();
Steven Moreland73cdc882016-11-21 16:43:50 -0800559 }
560
Andreas Huber019d21d2016-10-03 12:59:47 -0700561 const ScalarType *scalarType = mStorageType->resolveToScalarType();
Andreas Huber1c507272016-10-05 14:33:21 -0700562 CHECK(scalarType != nullptr);
Andreas Huber019d21d2016-10-03 12:59:47 -0700563
Steven Morelanddb1b1b62017-01-10 09:50:55 -0800564 std::vector<const EnumType *> chain;
565 if (exportParent) {
Timur Iskhakovf1b902d2017-08-13 20:14:31 -0700566 chain = typeChain();
Steven Morelanddb1b1b62017-01-10 09:50:55 -0800567 } else {
568 chain = { this };
569 }
570
Andreas Huber1c507272016-10-05 14:33:21 -0700571 if (forJava) {
572 if (!name.empty()) {
573 out << "public final class "
574 << name
575 << " {\n";
576
577 out.indent();
578 } else {
579 out << "// Values declared in " << localName() << " follow.\n";
580 }
581
Andreas Huber1c507272016-10-05 14:33:21 -0700582 const std::string typeName =
Yifan Hong4ed13472016-11-02 10:44:11 -0700583 scalarType->getJavaType(false /* forInitializer */);
Andreas Huber1c507272016-10-05 14:33:21 -0700584
Andreas Huber1c507272016-10-05 14:33:21 -0700585 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
586 const auto &type = *it;
587
588 for (const auto &entry : type->values()) {
589 out << "public static final "
590 << typeName
591 << " "
592 << valuePrefix
593 << entry->name()
Steven Moreland73cdc882016-11-21 16:43:50 -0800594 << valueSuffix
Andreas Huber1c507272016-10-05 14:33:21 -0700595 << " = ";
596
597 // javaValue will make the number signed.
598 std::string value = entry->javaValue(scalarType->getKind());
599 CHECK(!value.empty()); // use autofilled values for java.
600 out << value;
601
602 out << ";";
603
604 std::string comment = entry->comment();
605 if (!comment.empty() && comment != value) {
606 out << " // " << comment;
607 }
608
609 out << "\n";
610 }
611 }
612
613 if (!name.empty()) {
614 out.unindent();
615 out << "};\n";
616 }
617 out << "\n";
618
619 return OK;
620 }
Andreas Huber019d21d2016-10-03 12:59:47 -0700621
622 if (!name.empty()) {
623 out << "typedef ";
624 }
625
626 out << "enum {\n";
627
628 out.indent();
629
Andreas Huber019d21d2016-10-03 12:59:47 -0700630 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
631 const auto &type = *it;
632
633 for (const auto &entry : type->values()) {
Steven Moreland73cdc882016-11-21 16:43:50 -0800634 out << valuePrefix << entry->name() << valueSuffix;
Andreas Huber019d21d2016-10-03 12:59:47 -0700635
636 std::string value = entry->cppValue(scalarType->getKind());
637 CHECK(!value.empty()); // use autofilled values for c++.
638 out << " = " << value;
639
640 out << ",";
641
642 std::string comment = entry->comment();
643 if (!comment.empty() && comment != value) {
644 out << " // " << comment;
645 }
646
647 out << "\n";
648 }
649 }
650
651 out.unindent();
652 out << "}";
653
654 if (!name.empty()) {
655 out << " " << name;
656 }
657
658 out << ";\n\n";
659
660 return OK;
661}
662
Andreas Huber31629bc2016-08-03 09:06:40 -0700663////////////////////////////////////////////////////////////////////////////////
664
Yifan Hongf24fa852016-09-23 11:03:15 -0700665EnumValue::EnumValue(const char *name, ConstantExpression *value)
Andreas Huber31629bc2016-08-03 09:06:40 -0700666 : mName(name),
Yifan Hongf24fa852016-09-23 11:03:15 -0700667 mValue(value),
668 mIsAutoFill(false) {
Andreas Huber31629bc2016-08-03 09:06:40 -0700669}
670
671std::string EnumValue::name() const {
672 return mName;
673}
674
Yifan Hongc07b2022016-11-08 12:44:24 -0800675std::string EnumValue::value(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700676 CHECK(mValue != nullptr);
Yifan Hongc07b2022016-11-08 12:44:24 -0800677 return mValue->value(castKind);
Yifan Hong57886972016-08-17 10:42:15 -0700678}
679
Yifan Hongfc610cd2016-09-22 13:34:45 -0700680std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700681 CHECK(mValue != nullptr);
682 return mValue->cppValue(castKind);
Yifan Hong57886972016-08-17 10:42:15 -0700683}
Yifan Hongfc610cd2016-09-22 13:34:45 -0700684std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700685 CHECK(mValue != nullptr);
686 return mValue->javaValue(castKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700687}
Yifan Hong57886972016-08-17 10:42:15 -0700688
Yifan Hongfc610cd2016-09-22 13:34:45 -0700689std::string EnumValue::comment() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700690 CHECK(mValue != nullptr);
691 return mValue->description();
692}
693
694ConstantExpression *EnumValue::constExpr() const {
695 CHECK(mValue != nullptr);
696 return mValue;
697}
698
Timur Iskhakov7296af12017-08-09 21:52:48 +0000699void EnumValue::autofill(const EnumValue* prev, const ScalarType* type) {
700 if (mValue != nullptr) return;
Yifan Hongf24fa852016-09-23 11:03:15 -0700701 mIsAutoFill = true;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000702 if (prev == nullptr) {
703 mValue = ConstantExpression::Zero(type->getKind()).release();
Yifan Hongf24fa852016-09-23 11:03:15 -0700704 } else {
705 CHECK(prev->mValue != nullptr);
Timur Iskhakov7296af12017-08-09 21:52:48 +0000706 mValue = prev->mValue->addOne(type->getKind()).release();
Yifan Hongf24fa852016-09-23 11:03:15 -0700707 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000708 mValue->evaluate();
Yifan Hongf24fa852016-09-23 11:03:15 -0700709}
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
Timur Iskhakov505316c2017-08-05 03:38:59 +0000729bool BitFieldType::isCompatibleElementType(Type* elementType) const {
Yifan Hongc57c8bb2016-12-01 11:37:18 -0800730 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";
Timur Iskhakov505316c2017-08-05 03:38:59 +0000771 out << "predefined_type: \"" << static_cast<NamedType*>(mElementType.get())->fullName()
772 << "\"\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
Timur Iskhakov505316c2017-08-05 03:38:59 +0000797EnumType* BitFieldType::getEnumType() const {
Yifan Honge45b5302017-02-22 10:49:07 -0800798 CHECK(mElementType->isEnum());
Timur Iskhakov505316c2017-08-05 03:38:59 +0000799 return static_cast<EnumType*>(mElementType.get());
Yifan Honge45b5302017-02-22 10:49:07 -0800800}
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