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