EnumType.cpp revision 3f1d26ed2a4843498c187126f95bed67838e08a4
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 <hidl-util/Formatter.h>
20#include <inttypes.h>
21#include <unordered_map>
22
23#include "Annotation.h"
24#include "Location.h"
25#include "ScalarType.h"
26
27namespace android {
28
29EnumType::EnumType(const char* localName, const Location& location,
30                   const Reference<Type>& storageType, Scope* parent)
31    : Scope(localName, location, parent), mValues(), mStorageType(storageType) {
32    BitFieldType* bitfieldType = new BitFieldType(parent);
33    bitfieldType->setElementType(Reference<Type>(this, Location()));
34    mBitfieldType.set(bitfieldType);
35}
36
37const Type *EnumType::storageType() const {
38    return mStorageType.get();
39}
40
41const std::vector<EnumValue *> &EnumType::values() const {
42    return mValues;
43}
44
45void EnumType::addValue(EnumValue* value) {
46    CHECK(value != nullptr);
47    mValues.push_back(value);
48}
49
50status_t EnumType::resolveInheritance() {
51    const EnumType* prevType = nullptr;
52    EnumValue* prevValue = nullptr;
53
54    for (const auto* type : superTypeChain()) {
55        if (!type->values().empty()) {
56            prevType = type;
57            prevValue = type->values().back();
58            break;
59        }
60    }
61
62    for (auto* value : mValues) {
63        value->autofill(prevType, prevValue, mStorageType->resolveToScalarType());
64        prevType = this;
65        prevValue = value;
66    }
67
68    return Scope::resolveInheritance();
69}
70
71std::vector<const Reference<Type>*> EnumType::getReferences() const {
72    return {&mStorageType};
73}
74
75std::vector<const ConstantExpression*> EnumType::getConstantExpressions() const {
76    std::vector<const ConstantExpression*> ret;
77    for (const auto* value : mValues) {
78        ret.push_back(value->constExpr());
79    }
80    return ret;
81}
82
83status_t EnumType::validate() const {
84    CHECK(getSubTypes().empty());
85
86    if (!isElidableType() || !mStorageType->isValidEnumStorageType()) {
87        std::cerr << "ERROR: Invalid enum storage type (" << (mStorageType)->typeName()
88                  << ") specified at " << mStorageType.location() << "\n";
89        return UNKNOWN_ERROR;
90    }
91
92    status_t err = validateUniqueNames();
93    if (err != OK) return err;
94
95    return Scope::validate();
96}
97
98status_t EnumType::validateUniqueNames() const {
99    std::unordered_map<std::string, const EnumType*> registeredValueNames;
100    for (const auto* type : superTypeChain()) {
101        for (const auto* enumValue : type->mValues) {
102            // No need to check super value uniqueness
103            registeredValueNames[enumValue->name()] = type;
104        }
105    }
106
107    for (const auto* value : mValues) {
108        auto registered = registeredValueNames.find(value->name());
109
110        if (registered != registeredValueNames.end()) {
111            const EnumType* definedInType = registered->second;
112
113            if (definedInType == this) {
114                // Defined in this enum
115                std::cerr << "ERROR: Redefinition of value '" << value->name() << "'";
116            } else {
117                // Defined in super enum
118                std::cerr << "ERROR: Redefinition of value '" << value->name()
119                          << "' defined in enum '" << definedInType->fullName() << "'";
120            }
121            std::cerr << " at " << value->location() << "\n";
122            return UNKNOWN_ERROR;
123        }
124
125        registeredValueNames[value->name()] = this;
126    }
127
128    return OK;
129}
130
131bool EnumType::isElidableType() const {
132    return mStorageType->isElidableType();
133}
134
135const ScalarType *EnumType::resolveToScalarType() const {
136    return mStorageType->resolveToScalarType();
137}
138
139std::string EnumType::typeName() const {
140    return "enum " + localName();
141}
142
143bool EnumType::isEnum() const {
144    return true;
145}
146
147bool EnumType::canCheckEquality() const {
148    return true;
149}
150
151std::string EnumType::getCppType(StorageMode,
152                                 bool /* specifyNamespaces */) const {
153    return fullName();
154}
155
156std::string EnumType::getJavaType(bool forInitializer) const {
157    return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
158}
159
160std::string EnumType::getJavaSuffix() const {
161    return mStorageType->resolveToScalarType()->getJavaSuffix();
162}
163
164std::string EnumType::getJavaWrapperType() const {
165    return mStorageType->resolveToScalarType()->getJavaWrapperType();
166}
167
168std::string EnumType::getVtsType() const {
169    return "TYPE_ENUM";
170}
171
172BitFieldType::BitFieldType(Scope* parent) : TemplatedType(parent) {}
173
174const BitFieldType* EnumType::getBitfieldType() const {
175    return mBitfieldType.get();
176}
177
178LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
179    std::vector<const EnumType*> chain = typeChain();
180    for (auto it = chain.begin(); it != chain.end(); ++it) {
181        const auto &type = *it;
182        for(EnumValue *v : type->values()) {
183            if(v->name() == name) {
184                return v;
185            }
186        }
187    }
188    return nullptr;
189}
190
191void EnumType::emitReaderWriter(
192        Formatter &out,
193        const std::string &name,
194        const std::string &parcelObj,
195        bool parcelObjIsPointer,
196        bool isReader,
197        ErrorMode mode) const {
198    const ScalarType *scalarType = mStorageType->resolveToScalarType();
199    CHECK(scalarType != NULL);
200
201    scalarType->emitReaderWriterWithCast(
202            out,
203            name,
204            parcelObj,
205            parcelObjIsPointer,
206            isReader,
207            mode,
208            true /* needsCast */);
209}
210
211void EnumType::emitJavaFieldReaderWriter(
212        Formatter &out,
213        size_t depth,
214        const std::string &parcelName,
215        const std::string &blobName,
216        const std::string &fieldName,
217        const std::string &offset,
218        bool isReader) const {
219    return mStorageType->emitJavaFieldReaderWriter(
220            out, depth, parcelName, blobName, fieldName, offset, isReader);
221}
222
223status_t EnumType::emitTypeDeclarations(Formatter &out) const {
224    const ScalarType *scalarType = mStorageType->resolveToScalarType();
225    CHECK(scalarType != nullptr);
226
227    const std::string storageType = scalarType->getCppStackType();
228
229    out << "enum class "
230        << localName()
231        << " : "
232        << storageType
233        << " {\n";
234
235    out.indent();
236
237    std::vector<const EnumType*> chain = typeChain();
238
239    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
240        const auto &type = *it;
241
242        for (const auto &entry : type->values()) {
243            out << entry->name();
244
245            std::string value = entry->cppValue(scalarType->getKind());
246            CHECK(!value.empty()); // use autofilled values for c++.
247            out << " = " << value;
248
249            out << ",";
250
251            std::string comment = entry->comment();
252            if (!comment.empty()) {
253                out << " // " << comment;
254            }
255
256            out << "\n";
257        }
258    }
259
260    out.unindent();
261    out << "};\n\n";
262
263    return OK;
264}
265
266void EnumType::emitEnumBitwiseOperator(
267        Formatter &out,
268        bool lhsIsEnum,
269        bool rhsIsEnum,
270        const std::string &op) const {
271    const ScalarType *scalarType = mStorageType->resolveToScalarType();
272    CHECK(scalarType != nullptr);
273
274    const std::string storageType = scalarType->getCppStackType();
275
276    out << "constexpr "
277        << storageType
278        << " operator"
279        << op
280        << "(const "
281        << (lhsIsEnum ? fullName() : storageType)
282        << " lhs, const "
283        << (rhsIsEnum ? fullName() : storageType)
284        << " rhs) {\n";
285
286    out.indent([&] {
287        out << "return static_cast<"
288            << storageType
289            << ">(";
290
291        if (lhsIsEnum) {
292            out << "static_cast<"
293                << storageType
294                << ">(lhs)";
295        } else {
296            out << "lhs";
297        }
298        out << " " << op << " ";
299        if (rhsIsEnum) {
300            out << "static_cast<"
301                << storageType
302                << ">(rhs)";
303        } else {
304            out << "rhs";
305        }
306        out << ");\n";
307    });
308
309    out << "}\n\n";
310}
311
312void EnumType::emitBitFieldBitwiseAssignmentOperator(
313        Formatter &out,
314        const std::string &op) const {
315    const ScalarType *scalarType = mStorageType->resolveToScalarType();
316    CHECK(scalarType != nullptr);
317
318    const std::string storageType = scalarType->getCppStackType();
319
320    out << "constexpr " << storageType << " &operator" << op << "=("
321        << storageType << "& v, const " << fullName() << " e) {\n";
322
323    out.indent([&] {
324        out << "v " << op << "= static_cast<" << storageType << ">(e);\n";
325        out << "return v;\n";
326    });
327
328    out << "}\n\n";
329}
330
331status_t EnumType::emitGlobalTypeDeclarations(Formatter &out) const {
332    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
333    emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
334    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "|");
335    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
336    emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
337    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "&");
338
339    emitBitFieldBitwiseAssignmentOperator(out, "|");
340    emitBitFieldBitwiseAssignmentOperator(out, "&");
341
342    // toString for bitfields, equivalent to dumpBitfield in Java
343    out << "template<typename>\n"
344        << "std::string toString("
345        << resolveToScalarType()->getCppArgumentType()
346        << " o);\n";
347    out << "template<>\n"
348        << "std::string toString<" << getCppStackType() << ">("
349        << resolveToScalarType()->getCppArgumentType()
350        << " o);\n\n";
351
352    // toString for enum itself
353    out << "std::string toString("
354        << getCppArgumentType()
355        << " o);\n\n";
356
357    return OK;
358}
359
360status_t EnumType::emitTypeDefinitions(Formatter& out, const std::string& /* prefix */) const {
361    const ScalarType *scalarType = mStorageType->resolveToScalarType();
362    CHECK(scalarType != NULL);
363
364    out << "template<>\n"
365        << "std::string toString<" << getCppStackType() << ">("
366        << scalarType->getCppArgumentType()
367        << " o) ";
368    out.block([&] {
369        // include toHexString for scalar types
370        out << "using ::android::hardware::details::toHexString;\n"
371            << "std::string os;\n"
372            << getBitfieldType()->getCppStackType() << " flipped = 0;\n"
373            << "bool first = true;\n";
374        for (EnumValue *value : values()) {
375            std::string valueName = fullName() + "::" + value->name();
376            out.sIf("(o & " + valueName + ")" +
377                    " == static_cast<" + scalarType->getCppStackType() +
378                    ">(" + valueName + ")", [&] {
379                out << "os += (first ? \"\" : \" | \");\n"
380                    << "os += \"" << value->name() << "\";\n"
381                    << "first = false;\n"
382                    << "flipped |= " << valueName << ";\n";
383            }).endl();
384        }
385        // put remaining bits
386        out.sIf("o != flipped", [&] {
387            out << "os += (first ? \"\" : \" | \");\n";
388            scalarType->emitHexDump(out, "os", "o & (~flipped)");
389        });
390        out << "os += \" (\";\n";
391        scalarType->emitHexDump(out, "os", "o");
392        out << "os += \")\";\n";
393
394        out << "return os;\n";
395    }).endl().endl();
396
397    out << "std::string toString("
398        << getCppArgumentType()
399        << " o) ";
400
401    out.block([&] {
402        out << "using ::android::hardware::details::toHexString;\n";
403        for (EnumValue *value : values()) {
404            out.sIf("o == " + fullName() + "::" + value->name(), [&] {
405                out << "return \"" << value->name() << "\";\n";
406            }).endl();
407        }
408        out << "std::string os;\n";
409        scalarType->emitHexDump(out, "os",
410            "static_cast<" + scalarType->getCppStackType() + ">(o)");
411        out << "return os;\n";
412    }).endl().endl();
413
414    return OK;
415}
416
417status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool atTopLevel) const {
418    const ScalarType *scalarType = mStorageType->resolveToScalarType();
419    CHECK(scalarType != NULL);
420
421    out << "public "
422        << (atTopLevel ? "" : "static ")
423        << "final class "
424        << localName()
425        << " {\n";
426
427    out.indent();
428
429    const std::string typeName =
430        scalarType->getJavaType(false /* forInitializer */);
431
432    std::vector<const EnumType*> chain = typeChain();
433
434    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
435        const auto &type = *it;
436
437        for (const auto &entry : type->values()) {
438            out << "public static final "
439                << typeName
440                << " "
441                << entry->name()
442                << " = ";
443
444            // javaValue will make the number signed.
445            std::string value = entry->javaValue(scalarType->getKind());
446            CHECK(!value.empty()); // use autofilled values for java.
447            out << value;
448
449            out << ";";
450
451            std::string comment = entry->comment();
452            if (!comment.empty()) {
453                out << " // " << comment;
454            }
455
456            out << "\n";
457        }
458    }
459
460    out << "public static final String toString("
461        << typeName << " o) ";
462    out.block([&] {
463        for (EnumValue *value : values()) {
464            out.sIf("o == " + value->name(), [&] {
465                out << "return \"" << value->name() << "\";\n";
466            }).endl();
467        }
468        out << "return \"0x\" + ";
469        scalarType->emitConvertToJavaHexString(out, "o");
470        out << ";\n";
471    }).endl();
472
473    auto bitfieldType = getBitfieldType()->getJavaType(false /* forInitializer */);
474    auto bitfieldWrapperType = getBitfieldType()->getJavaWrapperType();
475    out << "\n"
476        << "public static final String dumpBitfield("
477        << bitfieldType << " o) ";
478    out.block([&] {
479        out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n";
480        out << bitfieldType << " flipped = 0;\n";
481        for (EnumValue *value : values()) {
482            if (value->constExpr()->castSizeT() == 0) {
483                out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n";
484                continue;
485            }
486            out.sIf("(o & " + value->name() + ") == " + value->name(), [&] {
487                out << "list.add(\"" << value->name() << "\");\n";
488                out << "flipped |= " << value->name() << ";\n";
489            }).endl();
490        }
491        // put remaining bits
492        out.sIf("o != flipped", [&] {
493            out << "list.add(\"0x\" + ";
494            scalarType->emitConvertToJavaHexString(out, "o & (~flipped)");
495            out << ");\n";
496        }).endl();
497        out << "return String.join(\" | \", list);\n";
498    }).endl().endl();
499
500    out.unindent();
501    out << "};\n\n";
502
503    return OK;
504}
505
506status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
507    const ScalarType *scalarType = mStorageType->resolveToScalarType();
508
509    out << "name: \"" << fullName() << "\"\n";
510    out << "type: " << getVtsType() << "\n";
511    out << "enum_value: {\n";
512    out.indent();
513
514    out << "scalar_type: \""
515        << scalarType->getVtsScalarType()
516        << "\"\n\n";
517    std::vector<const EnumType*> chain = typeChain();
518
519    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
520        const auto &type = *it;
521
522        for (const auto &entry : type->values()) {
523            out << "enumerator: \"" << entry->name() << "\"\n";
524            out << "scalar_value: {\n";
525            out.indent();
526            // use autofilled values for vts.
527            std::string value = entry->value(scalarType->getKind());
528            CHECK(!value.empty());
529            out << mStorageType->resolveToScalarType()->getVtsScalarType()
530                << ": "
531                << value
532                << "\n";
533            out.unindent();
534            out << "}\n";
535        }
536    }
537
538    out.unindent();
539    out << "}\n";
540    return OK;
541}
542
543status_t EnumType::emitVtsAttributeType(Formatter &out) const {
544    out << "type: " << getVtsType() << "\n";
545    out << "predefined_type: \"" << fullName() << "\"\n";
546    return OK;
547}
548
549void EnumType::emitJavaDump(
550        Formatter &out,
551        const std::string &streamName,
552        const std::string &name) const {
553    out << streamName << ".append(" << fqName().javaName() << ".toString("
554        << name << "));\n";
555}
556
557std::vector<const EnumType*> EnumType::typeChain() const {
558    std::vector<const EnumType*> types;
559    for (const EnumType* type = this; type != nullptr;) {
560        types.push_back(type);
561
562        const Type* superType = type->storageType();
563        if (superType != nullptr && superType->isEnum()) {
564            type = static_cast<const EnumType*>(superType);
565        } else {
566            type = nullptr;
567        }
568    }
569
570    return types;
571}
572
573std::vector<const EnumType*> EnumType::superTypeChain() const {
574    const Type* superType = storageType();
575    if (superType == nullptr || !superType->isEnum()) {
576        return {};
577    }
578    return static_cast<const EnumType*>(superType)->typeChain();
579}
580
581void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
582    mStorageType->getAlignmentAndSize(align, size);
583}
584
585const Annotation *EnumType::findExportAnnotation() const {
586    for (const auto &annotation : annotations()) {
587        if (annotation->name() == "export") {
588            return annotation;
589        }
590    }
591
592    return nullptr;
593}
594
595void EnumType::appendToExportedTypesVector(
596        std::vector<const Type *> *exportedTypes) const {
597    if (findExportAnnotation() != nullptr) {
598        exportedTypes->push_back(this);
599    }
600}
601
602status_t EnumType::emitExportedHeader(Formatter &out, bool forJava) const {
603    const Annotation *annotation = findExportAnnotation();
604    CHECK(annotation != nullptr);
605
606    std::string name = localName();
607
608    const AnnotationParam *nameParam = annotation->getParam("name");
609    if (nameParam != nullptr) {
610        name = nameParam->getSingleString();
611    }
612
613    bool exportParent = true;
614    const AnnotationParam *exportParentParam = annotation->getParam("export_parent");
615    if (exportParentParam != nullptr) {
616        exportParent = exportParentParam->getSingleBool();
617    }
618
619    std::string valuePrefix;
620    const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
621    if (prefixParam != nullptr) {
622        valuePrefix = prefixParam->getSingleString();
623    }
624
625    std::string valueSuffix;
626    const AnnotationParam *suffixParam = annotation->getParam("value_suffix");
627    if (suffixParam != nullptr) {
628        valueSuffix = suffixParam->getSingleString();
629    }
630
631    const ScalarType *scalarType = mStorageType->resolveToScalarType();
632    CHECK(scalarType != nullptr);
633
634    std::vector<const EnumType *> chain;
635    if (exportParent) {
636        chain = typeChain();
637    } else {
638        chain = { this };
639    }
640
641    if (forJava) {
642        if (!name.empty()) {
643            out << "public final class "
644                << name
645                << " {\n";
646
647            out.indent();
648        } else {
649            out << "// Values declared in " << localName() << " follow.\n";
650        }
651
652        const std::string typeName =
653            scalarType->getJavaType(false /* forInitializer */);
654
655        for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
656            const auto &type = *it;
657
658            for (const auto &entry : type->values()) {
659                out << "public static final "
660                    << typeName
661                    << " "
662                    << valuePrefix
663                    << entry->name()
664                    << valueSuffix
665                    << " = ";
666
667                // javaValue will make the number signed.
668                std::string value = entry->javaValue(scalarType->getKind());
669                CHECK(!value.empty()); // use autofilled values for java.
670                out << value;
671
672                out << ";";
673
674                std::string comment = entry->comment();
675                if (!comment.empty()) {
676                    out << " // " << comment;
677                }
678
679                out << "\n";
680            }
681        }
682
683        if (!name.empty()) {
684            out.unindent();
685            out << "};\n";
686        }
687        out << "\n";
688
689        return OK;
690    }
691
692    if (!name.empty()) {
693        out << "typedef ";
694    }
695
696    out << "enum {\n";
697
698    out.indent();
699
700    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
701        const auto &type = *it;
702
703        for (const auto &entry : type->values()) {
704            out << valuePrefix << entry->name() << valueSuffix;
705
706            std::string value = entry->cppValue(scalarType->getKind());
707            CHECK(!value.empty()); // use autofilled values for c++.
708            out << " = " << value;
709
710            out << ",";
711
712            std::string comment = entry->comment();
713            if (!comment.empty()) {
714                out << " // " << comment;
715            }
716
717            out << "\n";
718        }
719    }
720
721    out.unindent();
722    out << "}";
723
724    if (!name.empty()) {
725        out << " " << name;
726    }
727
728    out << ";\n\n";
729
730    return OK;
731}
732
733////////////////////////////////////////////////////////////////////////////////
734
735EnumValue::EnumValue(const char* name, ConstantExpression* value, const Location& location)
736    : mName(name), mValue(value), mLocation(location), mIsAutoFill(false) {}
737
738std::string EnumValue::name() const {
739    return mName;
740}
741
742std::string EnumValue::value(ScalarType::Kind castKind) const {
743    CHECK(mValue != nullptr);
744    return mValue->value(castKind);
745}
746
747std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
748    CHECK(mValue != nullptr);
749    return mValue->cppValue(castKind);
750}
751std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
752    CHECK(mValue != nullptr);
753    return mValue->javaValue(castKind);
754}
755
756std::string EnumValue::comment() const {
757    CHECK(mValue != nullptr);
758    if (mValue->descriptionIsTrivial()) return "";
759    return mValue->description();
760}
761
762ConstantExpression *EnumValue::constExpr() const {
763    CHECK(mValue != nullptr);
764    return mValue;
765}
766
767void EnumValue::autofill(const EnumType* prevType, EnumValue* prevValue, const ScalarType* type) {
768    // Value is defined explicitly
769    if (mValue != nullptr) return;
770
771    CHECK((prevType == nullptr) == (prevValue == nullptr));
772
773    mIsAutoFill = true;
774    if (prevValue == nullptr) {
775        mValue = ConstantExpression::Zero(type->getKind()).release();
776    } else {
777        std::string description = prevType->fullName() + "." + prevValue->name() + " implicitly";
778        auto* prevReference = new ReferenceConstantExpression(
779            Reference<LocalIdentifier>(prevValue, mLocation), description);
780        mValue = prevReference->addOne(type->getKind()).release();
781    }
782}
783
784bool EnumValue::isAutoFill() const {
785    return mIsAutoFill;
786}
787
788bool EnumValue::isEnumValue() const {
789    return true;
790}
791
792const Location& EnumValue::location() const {
793    return mLocation;
794}
795
796////////////////////////////////////////////////////////////////////////////////
797
798bool BitFieldType::isBitField() const {
799    return true;
800}
801
802std::string BitFieldType::templatedTypeName() const {
803    return "mask";
804}
805
806bool BitFieldType::isCompatibleElementType(const Type* elementType) const {
807    return elementType->isEnum();
808}
809
810const ScalarType *BitFieldType::resolveToScalarType() const {
811    return mElementType->resolveToScalarType();
812}
813
814std::string BitFieldType::getCppType(StorageMode mode,
815                                 bool specifyNamespaces) const {
816    return resolveToScalarType()->getCppType(mode, specifyNamespaces);
817}
818
819std::string BitFieldType::getJavaType(bool forInitializer) const {
820    return resolveToScalarType()->getJavaType(forInitializer);
821}
822
823std::string BitFieldType::getJavaSuffix() const {
824    return resolveToScalarType()->getJavaSuffix();
825}
826
827std::string BitFieldType::getJavaWrapperType() const {
828    return resolveToScalarType()->getJavaWrapperType();
829}
830
831std::string BitFieldType::getVtsType() const {
832    return "TYPE_MASK";
833}
834
835bool BitFieldType::isElidableType() const {
836    return resolveToScalarType()->isElidableType();
837}
838
839bool BitFieldType::canCheckEquality() const {
840    return resolveToScalarType()->canCheckEquality();
841}
842
843status_t BitFieldType::emitVtsAttributeType(Formatter &out) const {
844    out << "type: " << getVtsType() << "\n";
845    out << "scalar_type: \""
846        << mElementType->resolveToScalarType()->getVtsScalarType()
847        << "\"\n";
848    out << "predefined_type: \"" << static_cast<const NamedType*>(mElementType.get())->fullName()
849        << "\"\n";
850    return OK;
851}
852
853void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
854    resolveToScalarType()->getAlignmentAndSize(align, size);
855}
856
857void BitFieldType::emitReaderWriter(
858        Formatter &out,
859        const std::string &name,
860        const std::string &parcelObj,
861        bool parcelObjIsPointer,
862        bool isReader,
863        ErrorMode mode) const {
864    resolveToScalarType()->emitReaderWriterWithCast(
865            out,
866            name,
867            parcelObj,
868            parcelObjIsPointer,
869            isReader,
870            mode,
871            true /* needsCast */);
872}
873
874const EnumType* BitFieldType::getEnumType() const {
875    CHECK(mElementType->isEnum());
876    return static_cast<const EnumType*>(mElementType.get());
877}
878
879// a bitfield maps to the underlying scalar type in C++, so operator<< is
880// already defined. We can still emit useful information if the bitfield is
881// in a struct / union by overriding emitDump as below.
882void BitFieldType::emitDump(
883        Formatter &out,
884        const std::string &streamName,
885        const std::string &name) const {
886    out << streamName << " += "<< getEnumType()->fqName().cppNamespace()
887        << "::toString<" << getEnumType()->getCppStackType()
888        << ">(" << name << ");\n";
889}
890
891void BitFieldType::emitJavaDump(
892        Formatter &out,
893        const std::string &streamName,
894        const std::string &name) const {
895    out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield("
896        << name << "));\n";
897}
898
899void BitFieldType::emitJavaFieldReaderWriter(
900        Formatter &out,
901        size_t depth,
902        const std::string &parcelName,
903        const std::string &blobName,
904        const std::string &fieldName,
905        const std::string &offset,
906        bool isReader) const {
907    return resolveToScalarType()->emitJavaFieldReaderWriter(
908            out, depth, parcelName, blobName, fieldName, offset, isReader);
909}
910
911}  // namespace android
912
913