blob: fbb8a19a75536ab6873166c55920141f12a7cd94 [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
Andreas Huber881227d2016-08-02 14:20:21 -070055std::string EnumType::getCppType(StorageMode, std::string *extra) const {
56 extra->clear();
57
Andreas Huber0e00de42016-08-03 09:56:02 -070058 return fullName();
Andreas Huber881227d2016-08-02 14:20:21 -070059}
60
Andreas Huber2831d512016-08-15 09:33:47 -070061std::string EnumType::getJavaType() const {
62 return mStorageType->resolveToScalarType()->getJavaType();
63}
64
65std::string EnumType::getJavaSuffix() const {
66 return mStorageType->resolveToScalarType()->getJavaSuffix();
67}
68
Andreas Huber881227d2016-08-02 14:20:21 -070069void EnumType::emitReaderWriter(
70 Formatter &out,
71 const std::string &name,
72 const std::string &parcelObj,
73 bool parcelObjIsPointer,
74 bool isReader,
75 ErrorMode mode) const {
Andreas Huber737080b2016-08-02 15:38:04 -070076 const ScalarType *scalarType = mStorageType->resolveToScalarType();
77 CHECK(scalarType != NULL);
78
79 scalarType->emitReaderWriterWithCast(
80 out,
81 name,
82 parcelObj,
83 parcelObjIsPointer,
84 isReader,
85 mode,
86 true /* needsCast */);
Andreas Huber881227d2016-08-02 14:20:21 -070087}
88
Andreas Huber85eabdb2016-08-25 11:24:49 -070089void EnumType::emitJavaFieldReaderWriter(
90 Formatter &out,
91 const std::string &blobName,
92 const std::string &fieldName,
93 const std::string &offset,
94 bool isReader) const {
95 return mStorageType->emitJavaFieldReaderWriter(
96 out, blobName, fieldName, offset, isReader);
97}
98
Andreas Huber881227d2016-08-02 14:20:21 -070099status_t EnumType::emitTypeDeclarations(Formatter &out) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700100 const ScalarType *scalarType = mStorageType->resolveToScalarType();
101 CHECK(scalarType != NULL);
102
Andreas Huber881227d2016-08-02 14:20:21 -0700103 std::string extra;
104
105 out << "enum class "
Andreas Huber0e00de42016-08-03 09:56:02 -0700106 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700107 << " : "
Andreas Huber737080b2016-08-02 15:38:04 -0700108 << ((Type *)scalarType)->getCppType(&extra)
Andreas Huber881227d2016-08-02 14:20:21 -0700109 << " {\n";
110
111 out.indent();
112
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700113 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700114 getTypeChain(&chain);
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700115
116 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
117 const auto &type = *it;
118
119 for (const auto &entry : type->values()) {
120 out << entry->name();
121
Yifan Hong57886972016-08-17 10:42:15 -0700122 const char *value = entry->cppValue(scalarType->getKind());
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700123 if (value != NULL) {
124 out << " = " << value;
125 }
126
Yifan Hong57886972016-08-17 10:42:15 -0700127 out << ",";
128
129 const char *comment = entry->comment();
130 if (comment != NULL && strcmp(comment, value) != 0) {
131 out << " // " << comment;
132 }
133
134 out << "\n";
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700135 }
Andreas Huber881227d2016-08-02 14:20:21 -0700136 }
137
138 out.unindent();
139 out << "};\n\n";
140
141 return OK;
142}
143
Andreas Huber2831d512016-08-15 09:33:47 -0700144// Attempt to convert enum value literals into their signed equivalents,
145// i.e. if an enum value is stored in typeName 'byte', the value "192"
146// will be converted to the output "-64".
147static bool MakeSignedIntegerValue(
148 const std::string &typeName, const char *value, std::string *output) {
149 output->clear();
150
151 char *end;
152 long long x = strtoll(value, &end, 10);
153
154 if (end > value && *end == '\0' && errno != ERANGE) {
155 char out[32];
156 if (typeName == "byte") {
157 sprintf(out, "%d", (int)(int8_t)x);
158 } else if (typeName == "short") {
159 sprintf(out, "%d", (int)(int16_t)x);
160 } else if (typeName == "int") {
161 sprintf(out, "%d", (int)(int32_t)x);
162 } else {
163 assert(typeName == "long");
Iliyan Malchev1c858082016-08-24 07:40:22 -0700164 sprintf(out, "%" PRId64 "L", (int64_t)x);
Andreas Huber2831d512016-08-15 09:33:47 -0700165 }
166
167 *output = out;
168 return true;
169 }
170
171 return false;
172}
173
Andreas Huber85eabdb2016-08-25 11:24:49 -0700174status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool) const {
Andreas Huber2831d512016-08-15 09:33:47 -0700175 const ScalarType *scalarType = mStorageType->resolveToScalarType();
176 CHECK(scalarType != NULL);
177
178 out << "public final class "
179 << localName()
180 << " {\n";
181
182 out.indent();
183
184 const std::string typeName = scalarType->getJavaType();
185
186 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700187 getTypeChain(&chain);
Andreas Huber2831d512016-08-15 09:33:47 -0700188
189 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
190 const auto &type = *it;
191
192 for (const auto &entry : type->values()) {
193 out << "public static final "
194 << typeName
195 << " "
196 << entry->name();
197
Yifan Hong19ca75a2016-08-31 10:20:03 -0700198 const char *value = entry->javaValue(scalarType->getKind());
Andreas Huber2831d512016-08-15 09:33:47 -0700199 if (value != NULL) {
200 out << " = ";
201
202 std::string convertedValue;
203 if (MakeSignedIntegerValue(typeName, value, &convertedValue)) {
204 out << convertedValue;
205 } else {
206 // The value is not an integer, but some other string,
207 // hopefully referring to some other enum name.
208 out << value;
209 }
210 }
211
Yifan Hong19ca75a2016-08-31 10:20:03 -0700212 out << ";";
213
214 const char *comment = entry->comment();
215 if (comment != NULL && strcmp(comment, value) != 0) {
216 out << " // " << comment;
217 }
218
219 out << "\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700220 }
221 }
222
223 out.unindent();
224 out << "};\n\n";
225
226 return OK;
227}
228
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700229status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700230 out << "name: \"" << localName() << "\"\n"
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700231 << "type: TYPE_ENUM\n"
232 << "enum_value: {\n";
233 out.indent();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700234
235 std::vector<const EnumType *> chain;
236 getTypeChain(&chain);
237
238 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
239 const auto &type = *it;
240
241 for (const auto &entry : type->values()) {
242 out << "enumerator: \"" << entry->name() << "\"\n";
243
244 const char *value = entry->value();
245 if (value != NULL) {
246 out << "value: " << value << "\n";
247 }
248 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700249 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700250
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700251 out.unindent();
252 out << "}\n";
253 return OK;
254}
255
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700256status_t EnumType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang19933522016-08-29 15:06:38 -0700257 out << "type: TYPE_ENUM\n"
258 << "predefined_type: \""
259 << localName()
260 << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700261 return OK;
262}
263
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700264void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
265 out->clear();
266 const EnumType *type = this;
267 for (;;) {
268 out->push_back(type);
269
270 const Type *superType = type->storageType();
271 if (superType == NULL || !superType->isEnum()) {
272 break;
273 }
274
275 type = static_cast<const EnumType *>(superType);
276 }
277}
278
Andreas Huber85eabdb2016-08-25 11:24:49 -0700279void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
280 mStorageType->getAlignmentAndSize(align, size);
281}
282
Andreas Huber31629bc2016-08-03 09:06:40 -0700283////////////////////////////////////////////////////////////////////////////////
284
Yifan Hong57886972016-08-17 10:42:15 -0700285EnumValue::EnumValue(const char *name, const ConstantExpression *value)
Andreas Huber31629bc2016-08-03 09:06:40 -0700286 : mName(name),
287 mValue(value) {
288}
289
290std::string EnumValue::name() const {
291 return mName;
292}
293
294const char *EnumValue::value() const {
Yifan Hong57886972016-08-17 10:42:15 -0700295 return mValue ? mValue->value() : nullptr;
296}
297
298const char *EnumValue::cppValue(ScalarType::Kind castKind) const {
299 return mValue ? mValue->cppValue(castKind) : nullptr;
300}
Yifan Hong19ca75a2016-08-31 10:20:03 -0700301const char *EnumValue::javaValue(ScalarType::Kind castKind) const {
302 return mValue ? mValue->javaValue(castKind) : nullptr;
303}
Yifan Hong57886972016-08-17 10:42:15 -0700304
305const char *EnumValue::comment() const {
306 return mValue ? mValue->description() : nullptr;
Andreas Huber31629bc2016-08-03 09:06:40 -0700307}
308
Andreas Huberc9410c72016-07-28 12:18:40 -0700309} // namespace android
310