1 /*
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
17 #include "EnumType.h"
18
19 #include "Annotation.h"
20 #include "ScalarType.h"
21
22 #include <inttypes.h>
23 #include <hidl-util/Formatter.h>
24 #include <android-base/logging.h>
25
26 namespace android {
27
EnumType(const char * localName,const Location & location,Type * storageType,Scope * parent)28 EnumType::EnumType(const char* localName, const Location& location, Type* storageType,
29 Scope* parent)
30 : Scope(localName, location, parent), mValues(), mStorageType(storageType) {
31 mBitfieldType = new BitFieldType();
32 mBitfieldType->setElementType(this);
33 }
34
storageType() const35 const Type *EnumType::storageType() const {
36 return mStorageType;
37 }
38
values() const39 const std::vector<EnumValue *> &EnumType::values() const {
40 return mValues;
41 }
42
addValue(EnumValue * value)43 void EnumType::addValue(EnumValue *value) {
44 CHECK(value != nullptr);
45
46 EnumValue *prev = nullptr;
47 std::vector<const EnumType *> chain;
48 getTypeChain(&chain);
49 for (auto it = chain.begin(); it != chain.end(); ++it) {
50 const auto &type = *it;
51 if(!type->values().empty()) {
52 prev = type->values().back();
53 break;
54 }
55 }
56
57 value->autofill(prev, resolveToScalarType());
58 mValues.push_back(value);
59 }
60
isElidableType() const61 bool EnumType::isElidableType() const {
62 return mStorageType->isElidableType();
63 }
64
resolveToScalarType() const65 const ScalarType *EnumType::resolveToScalarType() const {
66 return mStorageType->resolveToScalarType();
67 }
68
typeName() const69 std::string EnumType::typeName() const {
70 return "enum " + localName();
71 }
72
isEnum() const73 bool EnumType::isEnum() const {
74 return true;
75 }
76
canCheckEquality() const77 bool EnumType::canCheckEquality() const {
78 return true;
79 }
80
getCppType(StorageMode,bool) const81 std::string EnumType::getCppType(StorageMode,
82 bool /* specifyNamespaces */) const {
83 return fullName();
84 }
85
getJavaType(bool forInitializer) const86 std::string EnumType::getJavaType(bool forInitializer) const {
87 return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
88 }
89
getJavaSuffix() const90 std::string EnumType::getJavaSuffix() const {
91 return mStorageType->resolveToScalarType()->getJavaSuffix();
92 }
93
getJavaWrapperType() const94 std::string EnumType::getJavaWrapperType() const {
95 return mStorageType->resolveToScalarType()->getJavaWrapperType();
96 }
97
getVtsType() const98 std::string EnumType::getVtsType() const {
99 return "TYPE_ENUM";
100 }
101
getBitfieldType() const102 BitFieldType *EnumType::getBitfieldType() const {
103 return mBitfieldType;
104 }
105
lookupIdentifier(const std::string & name) const106 LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
107 std::vector<const EnumType *> chain;
108 getTypeChain(&chain);
109 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
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const120 void 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 {
127 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 */);
138 }
139
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const140 void EnumType::emitJavaFieldReaderWriter(
141 Formatter &out,
142 size_t depth,
143 const std::string &parcelName,
144 const std::string &blobName,
145 const std::string &fieldName,
146 const std::string &offset,
147 bool isReader) const {
148 return mStorageType->emitJavaFieldReaderWriter(
149 out, depth, parcelName, blobName, fieldName, offset, isReader);
150 }
151
emitTypeDeclarations(Formatter & out) const152 status_t EnumType::emitTypeDeclarations(Formatter &out) const {
153 const ScalarType *scalarType = mStorageType->resolveToScalarType();
154 CHECK(scalarType != nullptr);
155
156 const std::string storageType = scalarType->getCppStackType();
157
158 out << "enum class "
159 << localName()
160 << " : "
161 << storageType
162 << " {\n";
163
164 out.indent();
165
166 std::vector<const EnumType *> chain;
167 getTypeChain(&chain);
168
169 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
170 const auto &type = *it;
171
172 for (const auto &entry : type->values()) {
173 out << entry->name();
174
175 std::string value = entry->cppValue(scalarType->getKind());
176 CHECK(!value.empty()); // use autofilled values for c++.
177 out << " = " << value;
178
179 out << ",";
180
181 std::string comment = entry->comment();
182 if (!comment.empty() && comment != value) {
183 out << " // " << comment;
184 }
185
186 out << "\n";
187 }
188 }
189
190 out.unindent();
191 out << "};\n\n";
192
193 return OK;
194 }
195
emitEnumBitwiseOperator(Formatter & out,bool lhsIsEnum,bool rhsIsEnum,const std::string & op) const196 void EnumType::emitEnumBitwiseOperator(
197 Formatter &out,
198 bool lhsIsEnum,
199 bool rhsIsEnum,
200 const std::string &op) const {
201 const ScalarType *scalarType = mStorageType->resolveToScalarType();
202 CHECK(scalarType != nullptr);
203
204 const std::string storageType = scalarType->getCppStackType();
205
206 out << "constexpr "
207 << storageType
208 << " operator"
209 << op
210 << "(const "
211 << (lhsIsEnum ? fullName() : storageType)
212 << " lhs, const "
213 << (rhsIsEnum ? fullName() : storageType)
214 << " rhs) {\n";
215
216 out.indent([&] {
217 out << "return static_cast<"
218 << storageType
219 << ">(";
220
221 if (lhsIsEnum) {
222 out << "static_cast<"
223 << storageType
224 << ">(lhs)";
225 } else {
226 out << "lhs";
227 }
228 out << " " << op << " ";
229 if (rhsIsEnum) {
230 out << "static_cast<"
231 << storageType
232 << ">(rhs)";
233 } else {
234 out << "rhs";
235 }
236 out << ");\n";
237 });
238
239 out << "}\n\n";
240 }
241
emitBitFieldBitwiseAssignmentOperator(Formatter & out,const std::string & op) const242 void EnumType::emitBitFieldBitwiseAssignmentOperator(
243 Formatter &out,
244 const std::string &op) const {
245 const ScalarType *scalarType = mStorageType->resolveToScalarType();
246 CHECK(scalarType != nullptr);
247
248 const std::string storageType = scalarType->getCppStackType();
249
250 out << "constexpr " << storageType << " &operator" << op << "=("
251 << storageType << "& v, const " << fullName() << " e) {\n";
252
253 out.indent([&] {
254 out << "v " << op << "= static_cast<" << storageType << ">(e);\n";
255 out << "return v;\n";
256 });
257
258 out << "}\n\n";
259 }
260
emitGlobalTypeDeclarations(Formatter & out) const261 status_t EnumType::emitGlobalTypeDeclarations(Formatter &out) const {
262 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "|");
263 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "|");
264 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "|");
265 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "&");
266 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "&");
267 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "&");
268
269 emitBitFieldBitwiseAssignmentOperator(out, "|");
270 emitBitFieldBitwiseAssignmentOperator(out, "&");
271
272 // toString for bitfields, equivalent to dumpBitfield in Java
273 out << "template<typename>\n"
274 << "std::string toString("
275 << resolveToScalarType()->getCppArgumentType()
276 << " o);\n";
277 out << "template<>\n"
278 << "std::string toString<" << getCppStackType() << ">("
279 << resolveToScalarType()->getCppArgumentType()
280 << " o);\n\n";
281
282 // toString for enum itself
283 out << "std::string toString("
284 << getCppArgumentType()
285 << " o);\n\n";
286
287 return OK;
288 }
289
emitTypeDefinitions(Formatter & out,const std::string) const290 status_t EnumType::emitTypeDefinitions(Formatter &out, const std::string /* prefix */) const {
291
292 const ScalarType *scalarType = mStorageType->resolveToScalarType();
293 CHECK(scalarType != NULL);
294
295 out << "template<>\n"
296 << "std::string toString<" << getCppStackType() << ">("
297 << scalarType->getCppArgumentType()
298 << " o) ";
299 out.block([&] {
300 // include toHexString for scalar types
301 out << "using ::android::hardware::details::toHexString;\n"
302 << "std::string os;\n"
303 << getBitfieldType()->getCppStackType() << " flipped = 0;\n"
304 << "bool first = true;\n";
305 for (EnumValue *value : values()) {
306 std::string valueName = fullName() + "::" + value->name();
307 out.sIf("(o & " + valueName + ")" +
308 " == static_cast<" + scalarType->getCppStackType() +
309 ">(" + valueName + ")", [&] {
310 out << "os += (first ? \"\" : \" | \");\n"
311 << "os += \"" << value->name() << "\";\n"
312 << "first = false;\n"
313 << "flipped |= " << valueName << ";\n";
314 }).endl();
315 }
316 // put remaining bits
317 out.sIf("o != flipped", [&] {
318 out << "os += (first ? \"\" : \" | \");\n";
319 scalarType->emitHexDump(out, "os", "o & (~flipped)");
320 });
321 out << "os += \" (\";\n";
322 scalarType->emitHexDump(out, "os", "o");
323 out << "os += \")\";\n";
324
325 out << "return os;\n";
326 }).endl().endl();
327
328 out << "std::string toString("
329 << getCppArgumentType()
330 << " o) ";
331
332 out.block([&] {
333 out << "using ::android::hardware::details::toHexString;\n";
334 for (EnumValue *value : values()) {
335 out.sIf("o == " + fullName() + "::" + value->name(), [&] {
336 out << "return \"" << value->name() << "\";\n";
337 }).endl();
338 }
339 out << "std::string os;\n";
340 scalarType->emitHexDump(out, "os",
341 "static_cast<" + scalarType->getCppStackType() + ">(o)");
342 out << "return os;\n";
343 }).endl().endl();
344
345 return OK;
346 }
347
emitJavaTypeDeclarations(Formatter & out,bool atTopLevel) const348 status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool atTopLevel) const {
349 const ScalarType *scalarType = mStorageType->resolveToScalarType();
350 CHECK(scalarType != NULL);
351
352 out << "public "
353 << (atTopLevel ? "" : "static ")
354 << "final class "
355 << localName()
356 << " {\n";
357
358 out.indent();
359
360 const std::string typeName =
361 scalarType->getJavaType(false /* forInitializer */);
362
363 std::vector<const EnumType *> chain;
364 getTypeChain(&chain);
365
366 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
367 const auto &type = *it;
368
369 for (const auto &entry : type->values()) {
370 out << "public static final "
371 << typeName
372 << " "
373 << entry->name()
374 << " = ";
375
376 // javaValue will make the number signed.
377 std::string value = entry->javaValue(scalarType->getKind());
378 CHECK(!value.empty()); // use autofilled values for java.
379 out << value;
380
381 out << ";";
382
383 std::string comment = entry->comment();
384 if (!comment.empty() && comment != value) {
385 out << " // " << comment;
386 }
387
388 out << "\n";
389 }
390 }
391
392 out << "public static final String toString("
393 << typeName << " o) ";
394 out.block([&] {
395 for (EnumValue *value : values()) {
396 out.sIf("o == " + value->name(), [&] {
397 out << "return \"" << value->name() << "\";\n";
398 }).endl();
399 }
400 out << "return \"0x\" + ";
401 scalarType->emitConvertToJavaHexString(out, "o");
402 out << ";\n";
403 }).endl();
404
405 auto bitfieldType = getBitfieldType()->getJavaType(false /* forInitializer */);
406 auto bitfieldWrapperType = getBitfieldType()->getJavaWrapperType();
407 out << "\n"
408 << "public static final String dumpBitfield("
409 << bitfieldType << " o) ";
410 out.block([&] {
411 out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n";
412 out << bitfieldType << " flipped = 0;\n";
413 for (EnumValue *value : values()) {
414 if (value->constExpr()->castSizeT() == 0) {
415 out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n";
416 continue;
417 }
418 out.sIf("(o & " + value->name() + ") == " + value->name(), [&] {
419 out << "list.add(\"" << value->name() << "\");\n";
420 out << "flipped |= " << value->name() << ";\n";
421 }).endl();
422 }
423 // put remaining bits
424 out.sIf("o != flipped", [&] {
425 out << "list.add(\"0x\" + ";
426 scalarType->emitConvertToJavaHexString(out, "o & (~flipped)");
427 out << ");\n";
428 }).endl();
429 out << "return String.join(\" | \", list);\n";
430 }).endl().endl();
431
432 out.unindent();
433 out << "};\n\n";
434
435 return OK;
436 }
437
emitVtsTypeDeclarations(Formatter & out) const438 status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
439 const ScalarType *scalarType = mStorageType->resolveToScalarType();
440
441 out << "name: \"" << fullName() << "\"\n";
442 out << "type: " << getVtsType() << "\n";
443 out << "enum_value: {\n";
444 out.indent();
445
446 out << "scalar_type: \""
447 << scalarType->getVtsScalarType()
448 << "\"\n\n";
449 std::vector<const EnumType *> chain;
450 getTypeChain(&chain);
451
452 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
453 const auto &type = *it;
454
455 for (const auto &entry : type->values()) {
456 out << "enumerator: \"" << entry->name() << "\"\n";
457 out << "scalar_value: {\n";
458 out.indent();
459 // use autofilled values for vts.
460 std::string value = entry->value(scalarType->getKind());
461 CHECK(!value.empty());
462 out << mStorageType->resolveToScalarType()->getVtsScalarType()
463 << ": "
464 << value
465 << "\n";
466 out.unindent();
467 out << "}\n";
468 }
469 }
470
471 out.unindent();
472 out << "}\n";
473 return OK;
474 }
475
emitVtsAttributeType(Formatter & out) const476 status_t EnumType::emitVtsAttributeType(Formatter &out) const {
477 out << "type: " << getVtsType() << "\n";
478 out << "predefined_type: \"" << fullName() << "\"\n";
479 return OK;
480 }
481
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const482 void EnumType::emitJavaDump(
483 Formatter &out,
484 const std::string &streamName,
485 const std::string &name) const {
486 out << streamName << ".append(" << fqName().javaName() << ".toString("
487 << name << "));\n";
488 }
489
getTypeChain(std::vector<const EnumType * > * out) const490 void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
491 out->clear();
492 const EnumType *type = this;
493 for (;;) {
494 out->push_back(type);
495
496 const Type *superType = type->storageType();
497 if (superType == NULL || !superType->isEnum()) {
498 break;
499 }
500
501 type = static_cast<const EnumType *>(superType);
502 }
503 }
504
getAlignmentAndSize(size_t * align,size_t * size) const505 void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
506 mStorageType->getAlignmentAndSize(align, size);
507 }
508
findExportAnnotation() const509 const Annotation *EnumType::findExportAnnotation() const {
510 for (const auto &annotation : annotations()) {
511 if (annotation->name() == "export") {
512 return annotation;
513 }
514 }
515
516 return nullptr;
517 }
518
appendToExportedTypesVector(std::vector<const Type * > * exportedTypes) const519 void EnumType::appendToExportedTypesVector(
520 std::vector<const Type *> *exportedTypes) const {
521 if (findExportAnnotation() != nullptr) {
522 exportedTypes->push_back(this);
523 }
524 }
525
emitExportedHeader(Formatter & out,bool forJava) const526 status_t EnumType::emitExportedHeader(Formatter &out, bool forJava) const {
527 const Annotation *annotation = findExportAnnotation();
528 CHECK(annotation != nullptr);
529
530 std::string name = localName();
531
532 const AnnotationParam *nameParam = annotation->getParam("name");
533 if (nameParam != nullptr) {
534 name = nameParam->getSingleString();
535 }
536
537 bool exportParent = true;
538 const AnnotationParam *exportParentParam = annotation->getParam("export_parent");
539 if (exportParentParam != nullptr) {
540 exportParent = exportParentParam->getSingleBool();
541 }
542
543 std::string valuePrefix;
544 const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
545 if (prefixParam != nullptr) {
546 valuePrefix = prefixParam->getSingleString();
547 }
548
549 std::string valueSuffix;
550 const AnnotationParam *suffixParam = annotation->getParam("value_suffix");
551 if (suffixParam != nullptr) {
552 valueSuffix = suffixParam->getSingleString();
553 }
554
555 const ScalarType *scalarType = mStorageType->resolveToScalarType();
556 CHECK(scalarType != nullptr);
557
558 std::vector<const EnumType *> chain;
559 if (exportParent) {
560 getTypeChain(&chain);
561 } else {
562 chain = { this };
563 }
564
565 if (forJava) {
566 if (!name.empty()) {
567 out << "public final class "
568 << name
569 << " {\n";
570
571 out.indent();
572 } else {
573 out << "// Values declared in " << localName() << " follow.\n";
574 }
575
576 const std::string typeName =
577 scalarType->getJavaType(false /* forInitializer */);
578
579 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
580 const auto &type = *it;
581
582 for (const auto &entry : type->values()) {
583 out << "public static final "
584 << typeName
585 << " "
586 << valuePrefix
587 << entry->name()
588 << valueSuffix
589 << " = ";
590
591 // javaValue will make the number signed.
592 std::string value = entry->javaValue(scalarType->getKind());
593 CHECK(!value.empty()); // use autofilled values for java.
594 out << value;
595
596 out << ";";
597
598 std::string comment = entry->comment();
599 if (!comment.empty() && comment != value) {
600 out << " // " << comment;
601 }
602
603 out << "\n";
604 }
605 }
606
607 if (!name.empty()) {
608 out.unindent();
609 out << "};\n";
610 }
611 out << "\n";
612
613 return OK;
614 }
615
616 if (!name.empty()) {
617 out << "typedef ";
618 }
619
620 out << "enum {\n";
621
622 out.indent();
623
624 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
625 const auto &type = *it;
626
627 for (const auto &entry : type->values()) {
628 out << valuePrefix << entry->name() << valueSuffix;
629
630 std::string value = entry->cppValue(scalarType->getKind());
631 CHECK(!value.empty()); // use autofilled values for c++.
632 out << " = " << value;
633
634 out << ",";
635
636 std::string comment = entry->comment();
637 if (!comment.empty() && comment != value) {
638 out << " // " << comment;
639 }
640
641 out << "\n";
642 }
643 }
644
645 out.unindent();
646 out << "}";
647
648 if (!name.empty()) {
649 out << " " << name;
650 }
651
652 out << ";\n\n";
653
654 return OK;
655 }
656
657 ////////////////////////////////////////////////////////////////////////////////
658
EnumValue(const char * name,ConstantExpression * value)659 EnumValue::EnumValue(const char *name, ConstantExpression *value)
660 : mName(name),
661 mValue(value),
662 mIsAutoFill(false) {
663 }
664
name() const665 std::string EnumValue::name() const {
666 return mName;
667 }
668
value(ScalarType::Kind castKind) const669 std::string EnumValue::value(ScalarType::Kind castKind) const {
670 CHECK(mValue != nullptr);
671 return mValue->value(castKind);
672 }
673
cppValue(ScalarType::Kind castKind) const674 std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
675 CHECK(mValue != nullptr);
676 return mValue->cppValue(castKind);
677 }
javaValue(ScalarType::Kind castKind) const678 std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
679 CHECK(mValue != nullptr);
680 return mValue->javaValue(castKind);
681 }
682
comment() const683 std::string EnumValue::comment() const {
684 CHECK(mValue != nullptr);
685 return mValue->description();
686 }
687
constExpr() const688 ConstantExpression *EnumValue::constExpr() const {
689 CHECK(mValue != nullptr);
690 return mValue;
691 }
692
autofill(const EnumValue * prev,const ScalarType * type)693 void EnumValue::autofill(const EnumValue *prev, const ScalarType *type) {
694 if(mValue != nullptr)
695 return;
696 mIsAutoFill = true;
697 ConstantExpression *value = new ConstantExpression();
698 if(prev == nullptr) {
699 *value = ConstantExpression::Zero(type->getKind());
700 } else {
701 CHECK(prev->mValue != nullptr);
702 *value = prev->mValue->addOne();
703 }
704 mValue = value;
705 }
706
isAutoFill() const707 bool EnumValue::isAutoFill() const {
708 return mIsAutoFill;
709 }
710
isEnumValue() const711 bool EnumValue::isEnumValue() const {
712 return true;
713 }
714
715 ////////////////////////////////////////////////////////////////////////////////
716
isBitField() const717 bool BitFieldType::isBitField() const {
718 return true;
719 }
720
typeName() const721 std::string BitFieldType::typeName() const {
722 return "mask" + (mElementType == nullptr ? "" : (" of " + mElementType->typeName()));
723 }
724
isCompatibleElementType(Type * elementType) const725 bool BitFieldType::isCompatibleElementType(Type *elementType) const {
726 return elementType->isEnum();
727 }
728
resolveToScalarType() const729 const ScalarType *BitFieldType::resolveToScalarType() const {
730 return mElementType->resolveToScalarType();
731 }
732
getCppType(StorageMode mode,bool specifyNamespaces) const733 std::string BitFieldType::getCppType(StorageMode mode,
734 bool specifyNamespaces) const {
735 return resolveToScalarType()->getCppType(mode, specifyNamespaces);
736 }
737
getJavaType(bool forInitializer) const738 std::string BitFieldType::getJavaType(bool forInitializer) const {
739 return resolveToScalarType()->getJavaType(forInitializer);
740 }
741
getJavaSuffix() const742 std::string BitFieldType::getJavaSuffix() const {
743 return resolveToScalarType()->getJavaSuffix();
744 }
745
getJavaWrapperType() const746 std::string BitFieldType::getJavaWrapperType() const {
747 return resolveToScalarType()->getJavaWrapperType();
748 }
749
getVtsType() const750 std::string BitFieldType::getVtsType() const {
751 return "TYPE_MASK";
752 }
753
isElidableType() const754 bool BitFieldType::isElidableType() const {
755 return resolveToScalarType()->isElidableType();
756 }
757
canCheckEquality() const758 bool BitFieldType::canCheckEquality() const {
759 return resolveToScalarType()->canCheckEquality();
760 }
761
emitVtsAttributeType(Formatter & out) const762 status_t BitFieldType::emitVtsAttributeType(Formatter &out) const {
763 out << "type: " << getVtsType() << "\n";
764 out << "scalar_type: \""
765 << mElementType->resolveToScalarType()->getVtsScalarType()
766 << "\"\n";
767 out << "predefined_type: \""
768 << static_cast<NamedType *>(mElementType)->fullName() << "\"\n";
769 return OK;
770 }
771
getAlignmentAndSize(size_t * align,size_t * size) const772 void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
773 resolveToScalarType()->getAlignmentAndSize(align, size);
774 }
775
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const776 void BitFieldType::emitReaderWriter(
777 Formatter &out,
778 const std::string &name,
779 const std::string &parcelObj,
780 bool parcelObjIsPointer,
781 bool isReader,
782 ErrorMode mode) const {
783 resolveToScalarType()->emitReaderWriterWithCast(
784 out,
785 name,
786 parcelObj,
787 parcelObjIsPointer,
788 isReader,
789 mode,
790 true /* needsCast */);
791 }
792
getEnumType() const793 EnumType *BitFieldType::getEnumType() const {
794 CHECK(mElementType->isEnum());
795 return static_cast<EnumType *>(mElementType);
796 }
797
798 // a bitfield maps to the underlying scalar type in C++, so operator<< is
799 // already defined. We can still emit useful information if the bitfield is
800 // in a struct / union by overriding emitDump as below.
emitDump(Formatter & out,const std::string & streamName,const std::string & name) const801 void BitFieldType::emitDump(
802 Formatter &out,
803 const std::string &streamName,
804 const std::string &name) const {
805 out << streamName << " += "<< getEnumType()->fqName().cppNamespace()
806 << "::toString<" << getEnumType()->getCppStackType()
807 << ">(" << name << ");\n";
808 }
809
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const810 void BitFieldType::emitJavaDump(
811 Formatter &out,
812 const std::string &streamName,
813 const std::string &name) const {
814 out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield("
815 << name << "));\n";
816 }
817
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const818 void BitFieldType::emitJavaFieldReaderWriter(
819 Formatter &out,
820 size_t depth,
821 const std::string &parcelName,
822 const std::string &blobName,
823 const std::string &fieldName,
824 const std::string &offset,
825 bool isReader) const {
826 return resolveToScalarType()->emitJavaFieldReaderWriter(
827 out, depth, parcelName, blobName, fieldName, offset, isReader);
828 }
829
830 } // namespace android
831
832