• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)28 EnumType::EnumType(
29         const char *localName,
30         const Location &location,
31         Type *storageType)
32     : Scope(localName, location),
33       mValues(),
34       mStorageType(storageType) {
35     mBitfieldType = new BitFieldType();
36     mBitfieldType->setElementType(this);
37 }
38 
storageType() const39 const Type *EnumType::storageType() const {
40     return mStorageType;
41 }
42 
values() const43 const std::vector<EnumValue *> &EnumType::values() const {
44     return mValues;
45 }
46 
addValue(EnumValue * value)47 void 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);
63 }
64 
isElidableType() const65 bool EnumType::isElidableType() const {
66     return mStorageType->isElidableType();
67 }
68 
resolveToScalarType() const69 const ScalarType *EnumType::resolveToScalarType() const {
70     return mStorageType->resolveToScalarType();
71 }
72 
typeName() const73 std::string EnumType::typeName() const {
74     return "enum " + localName();
75 }
76 
isEnum() const77 bool EnumType::isEnum() const {
78     return true;
79 }
80 
canCheckEquality() const81 bool EnumType::canCheckEquality() const {
82     return true;
83 }
84 
getCppType(StorageMode,bool specifyNamespaces) const85 std::string EnumType::getCppType(StorageMode,
86                                  bool specifyNamespaces) const {
87     return specifyNamespaces ? fullName() : partialCppName();
88 }
89 
getJavaType(bool forInitializer) const90 std::string EnumType::getJavaType(bool forInitializer) const {
91     return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
92 }
93 
getJavaSuffix() const94 std::string EnumType::getJavaSuffix() const {
95     return mStorageType->resolveToScalarType()->getJavaSuffix();
96 }
97 
getJavaWrapperType() const98 std::string EnumType::getJavaWrapperType() const {
99     return mStorageType->resolveToScalarType()->getJavaWrapperType();
100 }
101 
getVtsType() const102 std::string EnumType::getVtsType() const {
103     return "TYPE_ENUM";
104 }
105 
getBitfieldType() const106 BitFieldType *EnumType::getBitfieldType() const {
107     return mBitfieldType;
108 }
109 
lookupIdentifier(const std::string & name) const110 LocalIdentifier *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 
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const124 void 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 {
131     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 */);
142 }
143 
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const144 void EnumType::emitJavaFieldReaderWriter(
145         Formatter &out,
146         size_t depth,
147         const std::string &parcelName,
148         const std::string &blobName,
149         const std::string &fieldName,
150         const std::string &offset,
151         bool isReader) const {
152     return mStorageType->emitJavaFieldReaderWriter(
153             out, depth, parcelName, blobName, fieldName, offset, isReader);
154 }
155 
emitTypeDeclarations(Formatter & out) const156 status_t EnumType::emitTypeDeclarations(Formatter &out) const {
157     const ScalarType *scalarType = mStorageType->resolveToScalarType();
158     CHECK(scalarType != nullptr);
159 
160     const std::string storageType = scalarType->getCppStackType();
161 
162     out << "enum class "
163         << localName()
164         << " : "
165         << storageType
166         << " {\n";
167 
168     out.indent();
169 
170     std::vector<const EnumType *> chain;
171     getTypeChain(&chain);
172 
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 
179             std::string value = entry->cppValue(scalarType->getKind());
180             CHECK(!value.empty()); // use autofilled values for c++.
181             out << " = " << value;
182 
183             out << ",";
184 
185             std::string comment = entry->comment();
186             if (!comment.empty() && comment != value) {
187                 out << " // " << comment;
188             }
189 
190             out << "\n";
191         }
192     }
193 
194     out.unindent();
195     out << "};\n\n";
196 
197     return OK;
198 }
199 
emitEnumBitwiseOperator(Formatter & out,bool lhsIsEnum,bool rhsIsEnum,const std::string & op) const200 void EnumType::emitEnumBitwiseOperator(
201         Formatter &out,
202         bool lhsIsEnum,
203         bool rhsIsEnum,
204         const std::string &op) const {
205     const ScalarType *scalarType = mStorageType->resolveToScalarType();
206     CHECK(scalarType != nullptr);
207 
208     const std::string storageType = scalarType->getCppStackType();
209 
210     out << "constexpr "
211         << storageType
212         << " operator"
213         << op
214         << "(const "
215         << (lhsIsEnum ? fullName() : storageType)
216         << " lhs, const "
217         << (rhsIsEnum ? fullName() : storageType)
218         << " rhs) {\n";
219 
220     out.indent([&] {
221         out << "return static_cast<"
222             << storageType
223             << ">(";
224 
225         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     });
242 
243     out << "}\n\n";
244 }
245 
emitBitFieldBitwiseAssignmentOperator(Formatter & out,const std::string & op) const246 void 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 
257     out.indent([&] {
258         out << "v " << op << "= static_cast<" << storageType << ">(e);\n";
259         out << "return v;\n";
260     });
261 
262     out << "}\n\n";
263 }
264 
emitGlobalTypeDeclarations(Formatter & out) const265 status_t EnumType::emitGlobalTypeDeclarations(Formatter &out) const {
266     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, "&");
275 
276     // toString for bitfields, equivalent to dumpBitfield in Java
277     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 
286     // toString for enum itself
287     out << "std::string toString("
288         << getCppArgumentType()
289         << " o);\n\n";
290 
291     return OK;
292 }
293 
emitTypeDefinitions(Formatter & out,const std::string) const294 status_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() << ">("
301         << scalarType->getCppArgumentType()
302         << " o) ";
303     out.block([&] {
304         // include toHexString for scalar types
305         out << "using ::android::hardware::details::toHexString;\n"
306             << "std::string os;\n"
307             << getBitfieldType()->getCppStackType() << " flipped = 0;\n"
308             << "bool first = true;\n";
309         for (EnumValue *value : values()) {
310             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"
316                     << "first = false;\n"
317                     << "flipped |= " << valueName << ";\n";
318             }).endl();
319         }
320         // put remaining bits
321         out.sIf("o != flipped", [&] {
322             out << "os += (first ? \"\" : \" | \");\n";
323             scalarType->emitHexDump(out, "os", "o & (~flipped)");
324         });
325         out << "os += \" (\";\n";
326         scalarType->emitHexDump(out, "os", "o");
327         out << "os += \")\";\n";
328 
329         out << "return os;\n";
330     }).endl().endl();
331 
332     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 
349     return OK;
350 }
351 
emitJavaTypeDeclarations(Formatter & out,bool atTopLevel) const352 status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool atTopLevel) const {
353     const ScalarType *scalarType = mStorageType->resolveToScalarType();
354     CHECK(scalarType != NULL);
355 
356     out << "public "
357         << (atTopLevel ? "" : "static ")
358         << "final class "
359         << localName()
360         << " {\n";
361 
362     out.indent();
363 
364     const std::string typeName =
365         scalarType->getJavaType(false /* forInitializer */);
366 
367     std::vector<const EnumType *> chain;
368     getTypeChain(&chain);
369 
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                 << " "
377                 << entry->name()
378                 << " = ";
379 
380             // javaValue will make the number signed.
381             std::string value = entry->javaValue(scalarType->getKind());
382             CHECK(!value.empty()); // use autofilled values for java.
383             out << value;
384 
385             out << ";";
386 
387             std::string comment = entry->comment();
388             if (!comment.empty() && comment != value) {
389                 out << " // " << comment;
390             }
391 
392             out << "\n";
393         }
394     }
395 
396     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()) {
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 
addNamedTypesToSet(std::set<const FQName> &) const725 void BitFieldType::addNamedTypesToSet(std::set<const FQName> &) const {
726 }
727 
isCompatibleElementType(Type * elementType) const728 bool BitFieldType::isCompatibleElementType(Type *elementType) const {
729     return elementType->isEnum();
730 }
731 
resolveToScalarType() const732 const ScalarType *BitFieldType::resolveToScalarType() const {
733     return mElementType->resolveToScalarType();
734 }
735 
getCppType(StorageMode mode,bool specifyNamespaces) const736 std::string BitFieldType::getCppType(StorageMode mode,
737                                  bool specifyNamespaces) const {
738     return resolveToScalarType()->getCppType(mode, specifyNamespaces);
739 }
740 
getJavaType(bool forInitializer) const741 std::string BitFieldType::getJavaType(bool forInitializer) const {
742     return resolveToScalarType()->getJavaType(forInitializer);
743 }
744 
getJavaSuffix() const745 std::string BitFieldType::getJavaSuffix() const {
746     return resolveToScalarType()->getJavaSuffix();
747 }
748 
getJavaWrapperType() const749 std::string BitFieldType::getJavaWrapperType() const {
750     return resolveToScalarType()->getJavaWrapperType();
751 }
752 
getVtsType() const753 std::string BitFieldType::getVtsType() const {
754     return "TYPE_MASK";
755 }
756 
isElidableType() const757 bool BitFieldType::isElidableType() const {
758     return resolveToScalarType()->isElidableType();
759 }
760 
canCheckEquality() const761 bool BitFieldType::canCheckEquality() const {
762     return resolveToScalarType()->canCheckEquality();
763 }
764 
emitVtsAttributeType(Formatter & out) const765 status_t BitFieldType::emitVtsAttributeType(Formatter &out) const {
766     out << "type: " << getVtsType() << "\n";
767     out << "scalar_type: \""
768         << mElementType->resolveToScalarType()->getVtsScalarType()
769         << "\"\n";
770     out << "predefined_type: \""
771         << static_cast<NamedType *>(mElementType)->fullName() << "\"\n";
772     return OK;
773 }
774 
getAlignmentAndSize(size_t * align,size_t * size) const775 void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
776     resolveToScalarType()->getAlignmentAndSize(align, size);
777 }
778 
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const779 void BitFieldType::emitReaderWriter(
780         Formatter &out,
781         const std::string &name,
782         const std::string &parcelObj,
783         bool parcelObjIsPointer,
784         bool isReader,
785         ErrorMode mode) const {
786     resolveToScalarType()->emitReaderWriterWithCast(
787             out,
788             name,
789             parcelObj,
790             parcelObjIsPointer,
791             isReader,
792             mode,
793             true /* needsCast */);
794 }
795 
getEnumType() const796 EnumType *BitFieldType::getEnumType() const {
797     CHECK(mElementType->isEnum());
798     return static_cast<EnumType *>(mElementType);
799 }
800 
801 // a bitfield maps to the underlying scalar type in C++, so operator<< is
802 // already defined. We can still emit useful information if the bitfield is
803 // in a struct / union by overriding emitDump as below.
emitDump(Formatter & out,const std::string & streamName,const std::string & name) const804 void BitFieldType::emitDump(
805         Formatter &out,
806         const std::string &streamName,
807         const std::string &name) const {
808     out << streamName << " += "<< getEnumType()->fqName().cppNamespace()
809         << "::toString<" << getEnumType()->getCppStackType()
810         << ">(" << name << ");\n";
811 }
812 
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const813 void BitFieldType::emitJavaDump(
814         Formatter &out,
815         const std::string &streamName,
816         const std::string &name) const {
817     out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield("
818         << name << "));\n";
819 }
820 
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const821 void BitFieldType::emitJavaFieldReaderWriter(
822         Formatter &out,
823         size_t depth,
824         const std::string &parcelName,
825         const std::string &blobName,
826         const std::string &fieldName,
827         const std::string &offset,
828         bool isReader) const {
829     return resolveToScalarType()->emitJavaFieldReaderWriter(
830             out, depth, parcelName, blobName, fieldName, offset, isReader);
831 }
832 
833 }  // namespace android
834 
835