Home | History | Annotate | Download | only in hidl
      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 
     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 
     35 const Type *EnumType::storageType() const {
     36     return mStorageType;
     37 }
     38 
     39 const std::vector<EnumValue *> &EnumType::values() const {
     40     return mValues;
     41 }
     42 
     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 
     61 bool EnumType::isElidableType() const {
     62     return mStorageType->isElidableType();
     63 }
     64 
     65 const ScalarType *EnumType::resolveToScalarType() const {
     66     return mStorageType->resolveToScalarType();
     67 }
     68 
     69 std::string EnumType::typeName() const {
     70     return "enum " + localName();
     71 }
     72 
     73 bool EnumType::isEnum() const {
     74     return true;
     75 }
     76 
     77 bool EnumType::canCheckEquality() const {
     78     return true;
     79 }
     80 
     81 std::string EnumType::getCppType(StorageMode,
     82                                  bool /* specifyNamespaces */) const {
     83     return fullName();
     84 }
     85 
     86 std::string EnumType::getJavaType(bool forInitializer) const {
     87     return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
     88 }
     89 
     90 std::string EnumType::getJavaSuffix() const {
     91     return mStorageType->resolveToScalarType()->getJavaSuffix();
     92 }
     93 
     94 std::string EnumType::getJavaWrapperType() const {
     95     return mStorageType->resolveToScalarType()->getJavaWrapperType();
     96 }
     97 
     98 std::string EnumType::getVtsType() const {
     99     return "TYPE_ENUM";
    100 }
    101 
    102 BitFieldType *EnumType::getBitfieldType() const {
    103     return mBitfieldType;
    104 }
    105 
    106 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 
    120 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 
    140 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 
    152 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 
    196 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 
    242 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 
    261 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 
    290 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 
    348 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 
    438 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 
    476 status_t EnumType::emitVtsAttributeType(Formatter &out) const {
    477     out << "type: " << getVtsType() << "\n";
    478     out << "predefined_type: \"" << fullName() << "\"\n";
    479     return OK;
    480 }
    481 
    482 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 
    490 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 
    505 void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
    506     mStorageType->getAlignmentAndSize(align, size);
    507 }
    508 
    509 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 
    519 void EnumType::appendToExportedTypesVector(
    520         std::vector<const Type *> *exportedTypes) const {
    521     if (findExportAnnotation() != nullptr) {
    522         exportedTypes->push_back(this);
    523     }
    524 }
    525 
    526 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 
    659 EnumValue::EnumValue(const char *name, ConstantExpression *value)
    660     : mName(name),
    661       mValue(value),
    662       mIsAutoFill(false) {
    663 }
    664 
    665 std::string EnumValue::name() const {
    666     return mName;
    667 }
    668 
    669 std::string EnumValue::value(ScalarType::Kind castKind) const {
    670     CHECK(mValue != nullptr);
    671     return mValue->value(castKind);
    672 }
    673 
    674 std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
    675     CHECK(mValue != nullptr);
    676     return mValue->cppValue(castKind);
    677 }
    678 std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
    679     CHECK(mValue != nullptr);
    680     return mValue->javaValue(castKind);
    681 }
    682 
    683 std::string EnumValue::comment() const {
    684     CHECK(mValue != nullptr);
    685     return mValue->description();
    686 }
    687 
    688 ConstantExpression *EnumValue::constExpr() const {
    689     CHECK(mValue != nullptr);
    690     return mValue;
    691 }
    692 
    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 
    707 bool EnumValue::isAutoFill() const {
    708     return mIsAutoFill;
    709 }
    710 
    711 bool EnumValue::isEnumValue() const {
    712     return true;
    713 }
    714 
    715 ////////////////////////////////////////////////////////////////////////////////
    716 
    717 bool BitFieldType::isBitField() const {
    718     return true;
    719 }
    720 
    721 std::string BitFieldType::typeName() const {
    722     return "mask" + (mElementType == nullptr ? "" : (" of " + mElementType->typeName()));
    723 }
    724 
    725 bool BitFieldType::isCompatibleElementType(Type *elementType) const {
    726     return elementType->isEnum();
    727 }
    728 
    729 const ScalarType *BitFieldType::resolveToScalarType() const {
    730     return mElementType->resolveToScalarType();
    731 }
    732 
    733 std::string BitFieldType::getCppType(StorageMode mode,
    734                                  bool specifyNamespaces) const {
    735     return resolveToScalarType()->getCppType(mode, specifyNamespaces);
    736 }
    737 
    738 std::string BitFieldType::getJavaType(bool forInitializer) const {
    739     return resolveToScalarType()->getJavaType(forInitializer);
    740 }
    741 
    742 std::string BitFieldType::getJavaSuffix() const {
    743     return resolveToScalarType()->getJavaSuffix();
    744 }
    745 
    746 std::string BitFieldType::getJavaWrapperType() const {
    747     return resolveToScalarType()->getJavaWrapperType();
    748 }
    749 
    750 std::string BitFieldType::getVtsType() const {
    751     return "TYPE_MASK";
    752 }
    753 
    754 bool BitFieldType::isElidableType() const {
    755     return resolveToScalarType()->isElidableType();
    756 }
    757 
    758 bool BitFieldType::canCheckEquality() const {
    759     return resolveToScalarType()->canCheckEquality();
    760 }
    761 
    762 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 
    772 void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
    773     resolveToScalarType()->getAlignmentAndSize(align, size);
    774 }
    775 
    776 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 
    793 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.
    801 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 
    810 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 
    818 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