EnumType.cpp revision 1c8580863620f425188e86ec60b90cf269b5201c
1#include "EnumType.h"
2
3#include "Formatter.h"
4#include <inttypes.h>
5#include "ScalarType.h"
6
7#include <android-base/logging.h>
8
9namespace android {
10
11EnumType::EnumType(
12        const char *localName,
13        std::vector<EnumValue *> *values,
14        Type *storageType)
15    : NamedType(localName),
16      mValues(values),
17      mStorageType(
18              storageType != NULL
19                ? storageType
20                : new ScalarType(ScalarType::KIND_INT32)) {
21}
22
23const Type *EnumType::storageType() const {
24    return mStorageType;
25}
26
27const std::vector<EnumValue *> &EnumType::values() const {
28    return *mValues;
29}
30
31const ScalarType *EnumType::resolveToScalarType() const {
32    return mStorageType->resolveToScalarType();
33}
34
35bool EnumType::isEnum() const {
36    return true;
37}
38
39std::string EnumType::getCppType(StorageMode, std::string *extra) const {
40    extra->clear();
41
42    return fullName();
43}
44
45std::string EnumType::getJavaType() const {
46    return mStorageType->resolveToScalarType()->getJavaType();
47}
48
49std::string EnumType::getJavaSuffix() const {
50    return mStorageType->resolveToScalarType()->getJavaSuffix();
51}
52
53void EnumType::emitReaderWriter(
54        Formatter &out,
55        const std::string &name,
56        const std::string &parcelObj,
57        bool parcelObjIsPointer,
58        bool isReader,
59        ErrorMode mode) const {
60    const ScalarType *scalarType = mStorageType->resolveToScalarType();
61    CHECK(scalarType != NULL);
62
63    scalarType->emitReaderWriterWithCast(
64            out,
65            name,
66            parcelObj,
67            parcelObjIsPointer,
68            isReader,
69            mode,
70            true /* needsCast */);
71}
72
73status_t EnumType::emitTypeDeclarations(Formatter &out) const {
74    const ScalarType *scalarType = mStorageType->resolveToScalarType();
75    CHECK(scalarType != NULL);
76
77    std::string extra;
78
79    out << "enum class "
80        << localName()
81        << " : "
82        << ((Type *)scalarType)->getCppType(&extra)
83        << " {\n";
84
85    out.indent();
86
87    std::vector<const EnumType *> chain;
88    getTypeChain(&chain);
89
90    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
91        const auto &type = *it;
92
93        for (const auto &entry : type->values()) {
94            out << entry->name();
95
96            const char *value = entry->value();
97            if (value != NULL) {
98                out << " = " << value;
99            }
100
101            out << ",\n";
102        }
103    }
104
105    out.unindent();
106    out << "};\n\n";
107
108    return OK;
109}
110
111// Attempt to convert enum value literals into their signed equivalents,
112// i.e. if an enum value is stored in typeName 'byte', the value "192"
113// will be converted to the output "-64".
114static bool MakeSignedIntegerValue(
115        const std::string &typeName, const char *value, std::string *output) {
116    output->clear();
117
118    char *end;
119    long long x = strtoll(value, &end, 10);
120
121    if (end > value && *end == '\0' && errno != ERANGE) {
122        char out[32];
123        if (typeName == "byte") {
124            sprintf(out, "%d", (int)(int8_t)x);
125        } else if (typeName == "short") {
126            sprintf(out, "%d", (int)(int16_t)x);
127        } else if (typeName == "int") {
128            sprintf(out, "%d", (int)(int32_t)x);
129        } else {
130            assert(typeName == "long");
131            sprintf(out, "%" PRId64 "L", (int64_t)x);
132        }
133
134        *output = out;
135        return true;
136    }
137
138    return false;
139}
140
141status_t EnumType::emitJavaTypeDeclarations(Formatter &out) const {
142    const ScalarType *scalarType = mStorageType->resolveToScalarType();
143    CHECK(scalarType != NULL);
144
145    out << "public final class "
146        << localName()
147        << " {\n";
148
149    out.indent();
150
151    const std::string typeName = scalarType->getJavaType();
152
153    std::vector<const EnumType *> chain;
154    getTypeChain(&chain);
155
156    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
157        const auto &type = *it;
158
159        for (const auto &entry : type->values()) {
160            out << "public static final "
161                << typeName
162                << " "
163                << entry->name();
164
165            const char *value = entry->value();
166            if (value != NULL) {
167                out << " = ";
168
169                std::string convertedValue;
170                if (MakeSignedIntegerValue(typeName, value, &convertedValue)) {
171                    out << convertedValue;
172                } else {
173                    // The value is not an integer, but some other string,
174                    // hopefully referring to some other enum name.
175                    out << value;
176                }
177            }
178
179            out << ";\n";
180        }
181    }
182
183    out.unindent();
184    out << "};\n\n";
185
186    return OK;
187}
188
189status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
190    out << "name: \"" << localName() << "\"\n"
191        << "type: TYPE_ENUM\n"
192        << "enum_value: {\n";
193    out.indent();
194
195    std::vector<const EnumType *> chain;
196    getTypeChain(&chain);
197
198    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
199        const auto &type = *it;
200
201        for (const auto &entry : type->values()) {
202            out << "enumerator: \"" << entry->name() << "\"\n";
203
204            const char *value = entry->value();
205            if (value != NULL) {
206                out << "value: " << value << "\n";
207            }
208        }
209    }
210
211    out.unindent();
212    out << "}\n";
213    return OK;
214}
215
216status_t EnumType::emitVtsAttributeType(Formatter &out) const {
217    out << "type: TYPE_ENUM\n" << "predefined_type:\"" << localName() << "\"\n";
218    return OK;
219}
220
221void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
222    out->clear();
223    const EnumType *type = this;
224    for (;;) {
225        out->push_back(type);
226
227        const Type *superType = type->storageType();
228        if (superType == NULL || !superType->isEnum()) {
229            break;
230        }
231
232        type = static_cast<const EnumType *>(superType);
233    }
234}
235
236////////////////////////////////////////////////////////////////////////////////
237
238EnumValue::EnumValue(const char *name, const char *value)
239    : mName(name),
240      mValue(value) {
241}
242
243std::string EnumValue::name() const {
244    return mName;
245}
246
247const char *EnumValue::value() const {
248    return mValue;
249}
250
251}  // namespace android
252
253