• 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,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