blob: 843a946a03b798e3c7030418a7146afc28e8ba47 [file] [log] [blame]
Andreas Huberc9410c72016-07-28 12:18:40 -07001#include "EnumType.h"
2
3#include "Formatter.h"
Iliyan Malchev1c858082016-08-24 07:40:22 -07004#include <inttypes.h>
Andreas Huber881227d2016-08-02 14:20:21 -07005#include "ScalarType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -07006
Andreas Huber737080b2016-08-02 15:38:04 -07007#include <android-base/logging.h>
8
Andreas Huberc9410c72016-07-28 12:18:40 -07009namespace android {
10
Andreas Huberc9410c72016-07-28 12:18:40 -070011EnumType::EnumType(
Andreas Huber9ed827c2016-08-22 12:31:13 -070012 const char *localName,
13 std::vector<EnumValue *> *values,
14 Type *storageType)
15 : NamedType(localName),
16 mValues(values),
Andreas Huber881227d2016-08-02 14:20:21 -070017 mStorageType(
18 storageType != NULL
19 ? storageType
20 : new ScalarType(ScalarType::KIND_INT32)) {
Andreas Huberc9410c72016-07-28 12:18:40 -070021}
22
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070023const Type *EnumType::storageType() const {
24 return mStorageType;
25}
26
27const std::vector<EnumValue *> &EnumType::values() const {
28 return *mValues;
29}
30
Andreas Huber737080b2016-08-02 15:38:04 -070031const ScalarType *EnumType::resolveToScalarType() const {
32 return mStorageType->resolveToScalarType();
33}
34
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070035bool EnumType::isEnum() const {
36 return true;
37}
38
Andreas Huber881227d2016-08-02 14:20:21 -070039std::string EnumType::getCppType(StorageMode, std::string *extra) const {
40 extra->clear();
41
Andreas Huber0e00de42016-08-03 09:56:02 -070042 return fullName();
Andreas Huber881227d2016-08-02 14:20:21 -070043}
44
Andreas Huber2831d512016-08-15 09:33:47 -070045std::string EnumType::getJavaType() const {
46 return mStorageType->resolveToScalarType()->getJavaType();
47}
48
49std::string EnumType::getJavaSuffix() const {
50 return mStorageType->resolveToScalarType()->getJavaSuffix();
51}
52
Andreas Huber881227d2016-08-02 14:20:21 -070053void 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 {
Andreas Huber737080b2016-08-02 15:38:04 -070060 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 */);
Andreas Huber881227d2016-08-02 14:20:21 -070071}
72
73status_t EnumType::emitTypeDeclarations(Formatter &out) const {
Andreas Huber737080b2016-08-02 15:38:04 -070074 const ScalarType *scalarType = mStorageType->resolveToScalarType();
75 CHECK(scalarType != NULL);
76
Andreas Huber881227d2016-08-02 14:20:21 -070077 std::string extra;
78
79 out << "enum class "
Andreas Huber0e00de42016-08-03 09:56:02 -070080 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -070081 << " : "
Andreas Huber737080b2016-08-02 15:38:04 -070082 << ((Type *)scalarType)->getCppType(&extra)
Andreas Huber881227d2016-08-02 14:20:21 -070083 << " {\n";
84
85 out.indent();
86
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070087 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -070088 getTypeChain(&chain);
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070089
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 }
Andreas Huber881227d2016-08-02 14:20:21 -0700103 }
104
105 out.unindent();
106 out << "};\n\n";
107
108 return OK;
109}
110
Andreas Huber2831d512016-08-15 09:33:47 -0700111// 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");
Iliyan Malchev1c858082016-08-24 07:40:22 -0700131 sprintf(out, "%" PRId64 "L", (int64_t)x);
Andreas Huber2831d512016-08-15 09:33:47 -0700132 }
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;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700154 getTypeChain(&chain);
Andreas Huber2831d512016-08-15 09:33:47 -0700155
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
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700189status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700190 out << "name: \"" << localName() << "\"\n"
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700191 << "type: TYPE_ENUM\n"
192 << "enum_value: {\n";
193 out.indent();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700194
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 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700209 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700210
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700211 out.unindent();
212 out << "}\n";
213 return OK;
214}
215
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700216status_t EnumType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700217 out << "type: TYPE_ENUM\n" << "predefined_type:\"" << localName() << "\"\n";
218 return OK;
219}
220
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700221void 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
Andreas Huber31629bc2016-08-03 09:06:40 -0700236////////////////////////////////////////////////////////////////////////////////
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
Andreas Huberc9410c72016-07-28 12:18:40 -0700251} // namespace android
252