blob: 3a9a3c205a260f5a4472ad43e868ac6429521485 [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 Huber31629bc2016-08-03 09:06:40 -070011 std::vector<EnumValue *> *values, Type *storageType)
12 : mValues(values),
Andreas Huber881227d2016-08-02 14:20:21 -070013 mStorageType(
14 storageType != NULL
15 ? storageType
16 : new ScalarType(ScalarType::KIND_INT32)) {
Andreas Huberc9410c72016-07-28 12:18:40 -070017}
18
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070019const Type *EnumType::storageType() const {
20 return mStorageType;
21}
22
23const std::vector<EnumValue *> &EnumType::values() const {
24 return *mValues;
25}
26
Andreas Huber737080b2016-08-02 15:38:04 -070027const ScalarType *EnumType::resolveToScalarType() const {
28 return mStorageType->resolveToScalarType();
29}
30
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070031bool EnumType::isEnum() const {
32 return true;
33}
34
Andreas Huber881227d2016-08-02 14:20:21 -070035std::string EnumType::getCppType(StorageMode, std::string *extra) const {
36 extra->clear();
37
Andreas Huber0e00de42016-08-03 09:56:02 -070038 return fullName();
Andreas Huber881227d2016-08-02 14:20:21 -070039}
40
Andreas Huber2831d512016-08-15 09:33:47 -070041std::string EnumType::getJavaType() const {
42 return mStorageType->resolveToScalarType()->getJavaType();
43}
44
45std::string EnumType::getJavaSuffix() const {
46 return mStorageType->resolveToScalarType()->getJavaSuffix();
47}
48
Andreas Huber881227d2016-08-02 14:20:21 -070049void EnumType::emitReaderWriter(
50 Formatter &out,
51 const std::string &name,
52 const std::string &parcelObj,
53 bool parcelObjIsPointer,
54 bool isReader,
55 ErrorMode mode) const {
Andreas Huber737080b2016-08-02 15:38:04 -070056 const ScalarType *scalarType = mStorageType->resolveToScalarType();
57 CHECK(scalarType != NULL);
58
59 scalarType->emitReaderWriterWithCast(
60 out,
61 name,
62 parcelObj,
63 parcelObjIsPointer,
64 isReader,
65 mode,
66 true /* needsCast */);
Andreas Huber881227d2016-08-02 14:20:21 -070067}
68
69status_t EnumType::emitTypeDeclarations(Formatter &out) const {
Andreas Huber737080b2016-08-02 15:38:04 -070070 const ScalarType *scalarType = mStorageType->resolveToScalarType();
71 CHECK(scalarType != NULL);
72
Andreas Huber881227d2016-08-02 14:20:21 -070073 std::string extra;
74
75 out << "enum class "
Andreas Huber0e00de42016-08-03 09:56:02 -070076 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -070077 << " : "
Andreas Huber737080b2016-08-02 15:38:04 -070078 << ((Type *)scalarType)->getCppType(&extra)
Andreas Huber881227d2016-08-02 14:20:21 -070079 << " {\n";
80
81 out.indent();
82
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070083 std::vector<const EnumType *> chain;
84 const EnumType *type = this;
85 for (;;) {
86 chain.push_back(type);
Andreas Huber881227d2016-08-02 14:20:21 -070087
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070088 const Type *superType = type->storageType();
89 if (superType == NULL || !superType->isEnum()) {
90 break;
Andreas Huber881227d2016-08-02 14:20:21 -070091 }
92
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070093 type = static_cast<const EnumType *>(superType);
94 }
95
96 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
97 const auto &type = *it;
98
99 for (const auto &entry : type->values()) {
100 out << entry->name();
101
102 const char *value = entry->value();
103 if (value != NULL) {
104 out << " = " << value;
105 }
106
107 out << ",\n";
108 }
Andreas Huber881227d2016-08-02 14:20:21 -0700109 }
110
111 out.unindent();
112 out << "};\n\n";
113
114 return OK;
115}
116
Andreas Huber2831d512016-08-15 09:33:47 -0700117// Attempt to convert enum value literals into their signed equivalents,
118// i.e. if an enum value is stored in typeName 'byte', the value "192"
119// will be converted to the output "-64".
120static bool MakeSignedIntegerValue(
121 const std::string &typeName, const char *value, std::string *output) {
122 output->clear();
123
124 char *end;
125 long long x = strtoll(value, &end, 10);
126
127 if (end > value && *end == '\0' && errno != ERANGE) {
128 char out[32];
129 if (typeName == "byte") {
130 sprintf(out, "%d", (int)(int8_t)x);
131 } else if (typeName == "short") {
132 sprintf(out, "%d", (int)(int16_t)x);
133 } else if (typeName == "int") {
134 sprintf(out, "%d", (int)(int32_t)x);
135 } else {
136 assert(typeName == "long");
137 sprintf(out, "%lldL", (int64_t)x);
138 }
139
140 *output = out;
141 return true;
142 }
143
144 return false;
145}
146
147status_t EnumType::emitJavaTypeDeclarations(Formatter &out) const {
148 const ScalarType *scalarType = mStorageType->resolveToScalarType();
149 CHECK(scalarType != NULL);
150
151 out << "public final class "
152 << localName()
153 << " {\n";
154
155 out.indent();
156
157 const std::string typeName = scalarType->getJavaType();
158
159 std::vector<const EnumType *> chain;
160 const EnumType *type = this;
161 for (;;) {
162 chain.push_back(type);
163
164 const Type *superType = type->storageType();
165 if (superType == NULL || !superType->isEnum()) {
166 break;
167 }
168
169 type = static_cast<const EnumType *>(superType);
170 }
171
172 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
173 const auto &type = *it;
174
175 for (const auto &entry : type->values()) {
176 out << "public static final "
177 << typeName
178 << " "
179 << entry->name();
180
181 const char *value = entry->value();
182 if (value != NULL) {
183 out << " = ";
184
185 std::string convertedValue;
186 if (MakeSignedIntegerValue(typeName, value, &convertedValue)) {
187 out << convertedValue;
188 } else {
189 // The value is not an integer, but some other string,
190 // hopefully referring to some other enum name.
191 out << value;
192 }
193 }
194
195 out << ";\n";
196 }
197 }
198
199 out.unindent();
200 out << "};\n\n";
201
202 return OK;
203}
204
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700205status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
206 out << "name: \""
207 << localName()
208 << "\"\n"
209 << "type: TYPE_ENUM\n"
210 << "enum_value: {\n";
211 out.indent();
212 for (const auto &entry : values()) {
213 out << "enumerator: \""
214 << entry->name()
215 << "\"\n"
216 << "value: "
217 << entry->value()
218 << "\n";
219 }
220 out.unindent();
221 out << "}\n";
222 return OK;
223}
224
225status_t EnumType::emitVtsArgumentType(Formatter &out) const {
226 out << "type: TYPE_ENUM\n" << "predefined_type:\"" << localName() << "\"\n";
227 return OK;
228}
229
Andreas Huber31629bc2016-08-03 09:06:40 -0700230////////////////////////////////////////////////////////////////////////////////
231
232EnumValue::EnumValue(const char *name, const char *value)
233 : mName(name),
234 mValue(value) {
235}
236
237std::string EnumValue::name() const {
238 return mName;
239}
240
241const char *EnumValue::value() const {
242 return mValue;
243}
244
Andreas Huberc9410c72016-07-28 12:18:40 -0700245} // namespace android
246