blob: 0ae6215493bc25e766a8badf09b0786bea95299f [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;
87 const EnumType *type = this;
88 for (;;) {
89 chain.push_back(type);
Andreas Huber881227d2016-08-02 14:20:21 -070090
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070091 const Type *superType = type->storageType();
92 if (superType == NULL || !superType->isEnum()) {
93 break;
Andreas Huber881227d2016-08-02 14:20:21 -070094 }
95
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070096 type = static_cast<const EnumType *>(superType);
97 }
98
99 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
100 const auto &type = *it;
101
102 for (const auto &entry : type->values()) {
103 out << entry->name();
104
105 const char *value = entry->value();
106 if (value != NULL) {
107 out << " = " << value;
108 }
109
110 out << ",\n";
111 }
Andreas Huber881227d2016-08-02 14:20:21 -0700112 }
113
114 out.unindent();
115 out << "};\n\n";
116
117 return OK;
118}
119
Andreas Huber2831d512016-08-15 09:33:47 -0700120// Attempt to convert enum value literals into their signed equivalents,
121// i.e. if an enum value is stored in typeName 'byte', the value "192"
122// will be converted to the output "-64".
123static bool MakeSignedIntegerValue(
124 const std::string &typeName, const char *value, std::string *output) {
125 output->clear();
126
127 char *end;
128 long long x = strtoll(value, &end, 10);
129
130 if (end > value && *end == '\0' && errno != ERANGE) {
131 char out[32];
132 if (typeName == "byte") {
133 sprintf(out, "%d", (int)(int8_t)x);
134 } else if (typeName == "short") {
135 sprintf(out, "%d", (int)(int16_t)x);
136 } else if (typeName == "int") {
137 sprintf(out, "%d", (int)(int32_t)x);
138 } else {
139 assert(typeName == "long");
140 sprintf(out, "%lldL", (int64_t)x);
141 }
142
143 *output = out;
144 return true;
145 }
146
147 return false;
148}
149
150status_t EnumType::emitJavaTypeDeclarations(Formatter &out) const {
151 const ScalarType *scalarType = mStorageType->resolveToScalarType();
152 CHECK(scalarType != NULL);
153
154 out << "public final class "
155 << localName()
156 << " {\n";
157
158 out.indent();
159
160 const std::string typeName = scalarType->getJavaType();
161
162 std::vector<const EnumType *> chain;
163 const EnumType *type = this;
164 for (;;) {
165 chain.push_back(type);
166
167 const Type *superType = type->storageType();
168 if (superType == NULL || !superType->isEnum()) {
169 break;
170 }
171
172 type = static_cast<const EnumType *>(superType);
173 }
174
175 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
176 const auto &type = *it;
177
178 for (const auto &entry : type->values()) {
179 out << "public static final "
180 << typeName
181 << " "
182 << entry->name();
183
184 const char *value = entry->value();
185 if (value != NULL) {
186 out << " = ";
187
188 std::string convertedValue;
189 if (MakeSignedIntegerValue(typeName, value, &convertedValue)) {
190 out << convertedValue;
191 } else {
192 // The value is not an integer, but some other string,
193 // hopefully referring to some other enum name.
194 out << value;
195 }
196 }
197
198 out << ";\n";
199 }
200 }
201
202 out.unindent();
203 out << "};\n\n";
204
205 return OK;
206}
207
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700208status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
209 out << "name: \""
210 << localName()
211 << "\"\n"
212 << "type: TYPE_ENUM\n"
213 << "enum_value: {\n";
214 out.indent();
215 for (const auto &entry : values()) {
216 out << "enumerator: \""
217 << entry->name()
218 << "\"\n"
219 << "value: "
220 << entry->value()
221 << "\n";
222 }
223 out.unindent();
224 out << "}\n";
225 return OK;
226}
227
228status_t EnumType::emitVtsArgumentType(Formatter &out) const {
229 out << "type: TYPE_ENUM\n" << "predefined_type:\"" << localName() << "\"\n";
230 return OK;
231}
232
Andreas Huber31629bc2016-08-03 09:06:40 -0700233////////////////////////////////////////////////////////////////////////////////
234
235EnumValue::EnumValue(const char *name, const char *value)
236 : mName(name),
237 mValue(value) {
238}
239
240std::string EnumValue::name() const {
241 return mName;
242}
243
244const char *EnumValue::value() const {
245 return mValue;
246}
247
Andreas Huberc9410c72016-07-28 12:18:40 -0700248} // namespace android
249