blob: 3f9b3dd28335017c1ce4c151231e01c631525edd [file] [log] [blame]
Andreas Huberc9410c72016-07-28 12:18:40 -07001#include "EnumType.h"
2
3#include "Formatter.h"
Andreas Huber881227d2016-08-02 14:20:21 -07004#include "ScalarType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -07005
Andreas Huber737080b2016-08-02 15:38:04 -07006#include <android-base/logging.h>
7
Andreas Huberc9410c72016-07-28 12:18:40 -07008namespace android {
9
Andreas Huberc9410c72016-07-28 12:18:40 -070010EnumType::EnumType(
Andreas Huber9ed827c2016-08-22 12:31:13 -070011 const char *localName,
12 std::vector<EnumValue *> *values,
13 Type *storageType)
14 : NamedType(localName),
15 mValues(values),
Andreas Huber881227d2016-08-02 14:20:21 -070016 mStorageType(
17 storageType != NULL
18 ? storageType
19 : new ScalarType(ScalarType::KIND_INT32)) {
Andreas Huberc9410c72016-07-28 12:18:40 -070020}
21
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070022const Type *EnumType::storageType() const {
23 return mStorageType;
24}
25
26const std::vector<EnumValue *> &EnumType::values() const {
27 return *mValues;
28}
29
Andreas Huber737080b2016-08-02 15:38:04 -070030const ScalarType *EnumType::resolveToScalarType() const {
31 return mStorageType->resolveToScalarType();
32}
33
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070034bool EnumType::isEnum() const {
35 return true;
36}
37
Andreas Huber881227d2016-08-02 14:20:21 -070038std::string EnumType::getCppType(StorageMode, std::string *extra) const {
39 extra->clear();
40
Andreas Huber0e00de42016-08-03 09:56:02 -070041 return fullName();
Andreas Huber881227d2016-08-02 14:20:21 -070042}
43
Andreas Huber2831d512016-08-15 09:33:47 -070044std::string EnumType::getJavaType() const {
45 return mStorageType->resolveToScalarType()->getJavaType();
46}
47
48std::string EnumType::getJavaSuffix() const {
49 return mStorageType->resolveToScalarType()->getJavaSuffix();
50}
51
Andreas Huber881227d2016-08-02 14:20:21 -070052void EnumType::emitReaderWriter(
53 Formatter &out,
54 const std::string &name,
55 const std::string &parcelObj,
56 bool parcelObjIsPointer,
57 bool isReader,
58 ErrorMode mode) const {
Andreas Huber737080b2016-08-02 15:38:04 -070059 const ScalarType *scalarType = mStorageType->resolveToScalarType();
60 CHECK(scalarType != NULL);
61
62 scalarType->emitReaderWriterWithCast(
63 out,
64 name,
65 parcelObj,
66 parcelObjIsPointer,
67 isReader,
68 mode,
69 true /* needsCast */);
Andreas Huber881227d2016-08-02 14:20:21 -070070}
71
72status_t EnumType::emitTypeDeclarations(Formatter &out) const {
Andreas Huber737080b2016-08-02 15:38:04 -070073 const ScalarType *scalarType = mStorageType->resolveToScalarType();
74 CHECK(scalarType != NULL);
75
Andreas Huber881227d2016-08-02 14:20:21 -070076 std::string extra;
77
78 out << "enum class "
Andreas Huber0e00de42016-08-03 09:56:02 -070079 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -070080 << " : "
Andreas Huber737080b2016-08-02 15:38:04 -070081 << ((Type *)scalarType)->getCppType(&extra)
Andreas Huber881227d2016-08-02 14:20:21 -070082 << " {\n";
83
84 out.indent();
85
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070086 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -070087 getTypeChain(&chain);
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070088
89 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
90 const auto &type = *it;
91
92 for (const auto &entry : type->values()) {
93 out << entry->name();
94
95 const char *value = entry->value();
96 if (value != NULL) {
97 out << " = " << value;
98 }
99
100 out << ",\n";
101 }
Andreas Huber881227d2016-08-02 14:20:21 -0700102 }
103
104 out.unindent();
105 out << "};\n\n";
106
107 return OK;
108}
109
Andreas Huber2831d512016-08-15 09:33:47 -0700110// Attempt to convert enum value literals into their signed equivalents,
111// i.e. if an enum value is stored in typeName 'byte', the value "192"
112// will be converted to the output "-64".
113static bool MakeSignedIntegerValue(
114 const std::string &typeName, const char *value, std::string *output) {
115 output->clear();
116
117 char *end;
118 long long x = strtoll(value, &end, 10);
119
120 if (end > value && *end == '\0' && errno != ERANGE) {
121 char out[32];
122 if (typeName == "byte") {
123 sprintf(out, "%d", (int)(int8_t)x);
124 } else if (typeName == "short") {
125 sprintf(out, "%d", (int)(int16_t)x);
126 } else if (typeName == "int") {
127 sprintf(out, "%d", (int)(int32_t)x);
128 } else {
129 assert(typeName == "long");
130 sprintf(out, "%lldL", (int64_t)x);
131 }
132
133 *output = out;
134 return true;
135 }
136
137 return false;
138}
139
140status_t EnumType::emitJavaTypeDeclarations(Formatter &out) const {
141 const ScalarType *scalarType = mStorageType->resolveToScalarType();
142 CHECK(scalarType != NULL);
143
144 out << "public final class "
145 << localName()
146 << " {\n";
147
148 out.indent();
149
150 const std::string typeName = scalarType->getJavaType();
151
152 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700153 getTypeChain(&chain);
Andreas Huber2831d512016-08-15 09:33:47 -0700154
155 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
156 const auto &type = *it;
157
158 for (const auto &entry : type->values()) {
159 out << "public static final "
160 << typeName
161 << " "
162 << entry->name();
163
164 const char *value = entry->value();
165 if (value != NULL) {
166 out << " = ";
167
168 std::string convertedValue;
169 if (MakeSignedIntegerValue(typeName, value, &convertedValue)) {
170 out << convertedValue;
171 } else {
172 // The value is not an integer, but some other string,
173 // hopefully referring to some other enum name.
174 out << value;
175 }
176 }
177
178 out << ";\n";
179 }
180 }
181
182 out.unindent();
183 out << "};\n\n";
184
185 return OK;
186}
187
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700188status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700189 out << "name: \"" << localName() << "\"\n"
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700190 << "type: TYPE_ENUM\n"
191 << "enum_value: {\n";
192 out.indent();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700193
194 std::vector<const EnumType *> chain;
195 getTypeChain(&chain);
196
197 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
198 const auto &type = *it;
199
200 for (const auto &entry : type->values()) {
201 out << "enumerator: \"" << entry->name() << "\"\n";
202
203 const char *value = entry->value();
204 if (value != NULL) {
205 out << "value: " << value << "\n";
206 }
207 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700208 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700209
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700210 out.unindent();
211 out << "}\n";
212 return OK;
213}
214
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700215status_t EnumType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700216 out << "type: TYPE_ENUM\n" << "predefined_type:\"" << localName() << "\"\n";
217 return OK;
218}
219
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700220void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
221 out->clear();
222 const EnumType *type = this;
223 for (;;) {
224 out->push_back(type);
225
226 const Type *superType = type->storageType();
227 if (superType == NULL || !superType->isEnum()) {
228 break;
229 }
230
231 type = static_cast<const EnumType *>(superType);
232 }
233}
234
Andreas Huber31629bc2016-08-03 09:06:40 -0700235////////////////////////////////////////////////////////////////////////////////
236
237EnumValue::EnumValue(const char *name, const char *value)
238 : mName(name),
239 mValue(value) {
240}
241
242std::string EnumValue::name() const {
243 return mName;
244}
245
246const char *EnumValue::value() const {
247 return mValue;
248}
249
Andreas Huberc9410c72016-07-28 12:18:40 -0700250} // namespace android
251