blob: 9db7cf19268ca8c3aeb1ec8f6440755baf5ec312 [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Huberc9410c72016-07-28 12:18:40 -070017#include "EnumType.h"
18
19#include "Formatter.h"
Iliyan Malchev1c858082016-08-24 07:40:22 -070020#include <inttypes.h>
Andreas Huber881227d2016-08-02 14:20:21 -070021#include "ScalarType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070022
Andreas Huber737080b2016-08-02 15:38:04 -070023#include <android-base/logging.h>
24
Andreas Huberc9410c72016-07-28 12:18:40 -070025namespace android {
26
Andreas Huberc9410c72016-07-28 12:18:40 -070027EnumType::EnumType(
Andreas Huber9ed827c2016-08-22 12:31:13 -070028 const char *localName,
29 std::vector<EnumValue *> *values,
30 Type *storageType)
31 : NamedType(localName),
32 mValues(values),
Andreas Huber881227d2016-08-02 14:20:21 -070033 mStorageType(
34 storageType != NULL
35 ? storageType
36 : new ScalarType(ScalarType::KIND_INT32)) {
Andreas Huberc9410c72016-07-28 12:18:40 -070037}
38
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070039const Type *EnumType::storageType() const {
40 return mStorageType;
41}
42
43const std::vector<EnumValue *> &EnumType::values() const {
44 return *mValues;
45}
46
Andreas Huber737080b2016-08-02 15:38:04 -070047const ScalarType *EnumType::resolveToScalarType() const {
48 return mStorageType->resolveToScalarType();
49}
50
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070051bool EnumType::isEnum() const {
52 return true;
53}
54
Steven Moreland979e0992016-09-07 09:18:08 -070055std::string EnumType::getCppType(StorageMode,
56 std::string *extra,
57 bool specifyNamespaces) const {
Andreas Huber881227d2016-08-02 14:20:21 -070058 extra->clear();
59
Steven Moreland979e0992016-09-07 09:18:08 -070060 return specifyNamespaces ? fullName() : partialCppName();
Andreas Huber881227d2016-08-02 14:20:21 -070061}
62
Andreas Huber2831d512016-08-15 09:33:47 -070063std::string EnumType::getJavaType() const {
64 return mStorageType->resolveToScalarType()->getJavaType();
65}
66
67std::string EnumType::getJavaSuffix() const {
68 return mStorageType->resolveToScalarType()->getJavaSuffix();
69}
70
Andreas Huber881227d2016-08-02 14:20:21 -070071void EnumType::emitReaderWriter(
72 Formatter &out,
73 const std::string &name,
74 const std::string &parcelObj,
75 bool parcelObjIsPointer,
76 bool isReader,
77 ErrorMode mode) const {
Andreas Huber737080b2016-08-02 15:38:04 -070078 const ScalarType *scalarType = mStorageType->resolveToScalarType();
79 CHECK(scalarType != NULL);
80
81 scalarType->emitReaderWriterWithCast(
82 out,
83 name,
84 parcelObj,
85 parcelObjIsPointer,
86 isReader,
87 mode,
88 true /* needsCast */);
Andreas Huber881227d2016-08-02 14:20:21 -070089}
90
Andreas Huber85eabdb2016-08-25 11:24:49 -070091void EnumType::emitJavaFieldReaderWriter(
92 Formatter &out,
93 const std::string &blobName,
94 const std::string &fieldName,
95 const std::string &offset,
96 bool isReader) const {
97 return mStorageType->emitJavaFieldReaderWriter(
98 out, blobName, fieldName, offset, isReader);
99}
100
Andreas Huber881227d2016-08-02 14:20:21 -0700101status_t EnumType::emitTypeDeclarations(Formatter &out) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700102 const ScalarType *scalarType = mStorageType->resolveToScalarType();
103 CHECK(scalarType != NULL);
104
Andreas Huber881227d2016-08-02 14:20:21 -0700105 std::string extra;
106
107 out << "enum class "
Andreas Huber0e00de42016-08-03 09:56:02 -0700108 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700109 << " : "
Andreas Huber737080b2016-08-02 15:38:04 -0700110 << ((Type *)scalarType)->getCppType(&extra)
Andreas Huber881227d2016-08-02 14:20:21 -0700111 << " {\n";
112
113 out.indent();
114
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700115 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700116 getTypeChain(&chain);
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700117
118 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
119 const auto &type = *it;
120
121 for (const auto &entry : type->values()) {
122 out << entry->name();
123
Yifan Hong57886972016-08-17 10:42:15 -0700124 const char *value = entry->cppValue(scalarType->getKind());
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700125 if (value != NULL) {
126 out << " = " << value;
127 }
128
Yifan Hong57886972016-08-17 10:42:15 -0700129 out << ",";
130
131 const char *comment = entry->comment();
132 if (comment != NULL && strcmp(comment, value) != 0) {
133 out << " // " << comment;
134 }
135
136 out << "\n";
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700137 }
Andreas Huber881227d2016-08-02 14:20:21 -0700138 }
139
140 out.unindent();
141 out << "};\n\n";
142
143 return OK;
144}
145
Andreas Huber2831d512016-08-15 09:33:47 -0700146// Attempt to convert enum value literals into their signed equivalents,
147// i.e. if an enum value is stored in typeName 'byte', the value "192"
148// will be converted to the output "-64".
149static bool MakeSignedIntegerValue(
150 const std::string &typeName, const char *value, std::string *output) {
151 output->clear();
152
153 char *end;
154 long long x = strtoll(value, &end, 10);
155
156 if (end > value && *end == '\0' && errno != ERANGE) {
157 char out[32];
158 if (typeName == "byte") {
159 sprintf(out, "%d", (int)(int8_t)x);
160 } else if (typeName == "short") {
161 sprintf(out, "%d", (int)(int16_t)x);
162 } else if (typeName == "int") {
163 sprintf(out, "%d", (int)(int32_t)x);
164 } else {
165 assert(typeName == "long");
Iliyan Malchev1c858082016-08-24 07:40:22 -0700166 sprintf(out, "%" PRId64 "L", (int64_t)x);
Andreas Huber2831d512016-08-15 09:33:47 -0700167 }
168
169 *output = out;
170 return true;
171 }
172
173 return false;
174}
175
Andreas Huber85eabdb2016-08-25 11:24:49 -0700176status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool) const {
Andreas Huber2831d512016-08-15 09:33:47 -0700177 const ScalarType *scalarType = mStorageType->resolveToScalarType();
178 CHECK(scalarType != NULL);
179
180 out << "public final class "
181 << localName()
182 << " {\n";
183
184 out.indent();
185
186 const std::string typeName = scalarType->getJavaType();
187
188 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700189 getTypeChain(&chain);
Andreas Huber2831d512016-08-15 09:33:47 -0700190
191 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
192 const auto &type = *it;
193
194 for (const auto &entry : type->values()) {
195 out << "public static final "
196 << typeName
197 << " "
198 << entry->name();
199
Yifan Hong19ca75a2016-08-31 10:20:03 -0700200 const char *value = entry->javaValue(scalarType->getKind());
Andreas Huber2831d512016-08-15 09:33:47 -0700201 if (value != NULL) {
202 out << " = ";
203
204 std::string convertedValue;
205 if (MakeSignedIntegerValue(typeName, value, &convertedValue)) {
206 out << convertedValue;
207 } else {
208 // The value is not an integer, but some other string,
209 // hopefully referring to some other enum name.
210 out << value;
211 }
212 }
213
Yifan Hong19ca75a2016-08-31 10:20:03 -0700214 out << ";";
215
216 const char *comment = entry->comment();
217 if (comment != NULL && strcmp(comment, value) != 0) {
218 out << " // " << comment;
219 }
220
221 out << "\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700222 }
223 }
224
225 out.unindent();
226 out << "};\n\n";
227
228 return OK;
229}
230
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700231status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700232 out << "name: \"" << localName() << "\"\n"
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700233 << "type: TYPE_ENUM\n"
234 << "enum_value: {\n";
235 out.indent();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700236
237 std::vector<const EnumType *> chain;
238 getTypeChain(&chain);
239
240 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
241 const auto &type = *it;
242
243 for (const auto &entry : type->values()) {
244 out << "enumerator: \"" << entry->name() << "\"\n";
245
246 const char *value = entry->value();
247 if (value != NULL) {
248 out << "value: " << value << "\n";
249 }
250 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700251 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700252
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700253 out.unindent();
254 out << "}\n";
255 return OK;
256}
257
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700258status_t EnumType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang19933522016-08-29 15:06:38 -0700259 out << "type: TYPE_ENUM\n"
260 << "predefined_type: \""
261 << localName()
262 << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700263 return OK;
264}
265
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700266void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
267 out->clear();
268 const EnumType *type = this;
269 for (;;) {
270 out->push_back(type);
271
272 const Type *superType = type->storageType();
273 if (superType == NULL || !superType->isEnum()) {
274 break;
275 }
276
277 type = static_cast<const EnumType *>(superType);
278 }
279}
280
Andreas Huber85eabdb2016-08-25 11:24:49 -0700281void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
282 mStorageType->getAlignmentAndSize(align, size);
283}
284
Andreas Huber31629bc2016-08-03 09:06:40 -0700285////////////////////////////////////////////////////////////////////////////////
286
Yifan Hong57886972016-08-17 10:42:15 -0700287EnumValue::EnumValue(const char *name, const ConstantExpression *value)
Andreas Huber31629bc2016-08-03 09:06:40 -0700288 : mName(name),
289 mValue(value) {
290}
291
292std::string EnumValue::name() const {
293 return mName;
294}
295
296const char *EnumValue::value() const {
Yifan Hong57886972016-08-17 10:42:15 -0700297 return mValue ? mValue->value() : nullptr;
298}
299
300const char *EnumValue::cppValue(ScalarType::Kind castKind) const {
301 return mValue ? mValue->cppValue(castKind) : nullptr;
302}
Yifan Hong19ca75a2016-08-31 10:20:03 -0700303const char *EnumValue::javaValue(ScalarType::Kind castKind) const {
304 return mValue ? mValue->javaValue(castKind) : nullptr;
305}
Yifan Hong57886972016-08-17 10:42:15 -0700306
307const char *EnumValue::comment() const {
308 return mValue ? mValue->description() : nullptr;
Andreas Huber31629bc2016-08-03 09:06:40 -0700309}
310
Andreas Huberc9410c72016-07-28 12:18:40 -0700311} // namespace android
312