blob: 5f68ca8a3118e053affa4944c591c3e0417bfea1 [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
Andreas Huber881227d2016-08-02 14:20:21 -070019#include "ScalarType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070020
Dan Albert1df126d2016-09-21 13:56:02 -070021#include <assert.h>
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070022#include <inttypes.h>
23#include <hidl-util/Formatter.h>
Andreas Huber737080b2016-08-02 15:38:04 -070024#include <android-base/logging.h>
25
Andreas Huberc9410c72016-07-28 12:18:40 -070026namespace android {
27
Andreas Huberc9410c72016-07-28 12:18:40 -070028EnumType::EnumType(
Andreas Huber9ed827c2016-08-22 12:31:13 -070029 const char *localName,
30 std::vector<EnumValue *> *values,
31 Type *storageType)
32 : NamedType(localName),
33 mValues(values),
Andreas Huber881227d2016-08-02 14:20:21 -070034 mStorageType(
35 storageType != NULL
36 ? storageType
37 : new ScalarType(ScalarType::KIND_INT32)) {
Andreas Huberc9410c72016-07-28 12:18:40 -070038}
39
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070040const Type *EnumType::storageType() const {
41 return mStorageType;
42}
43
44const std::vector<EnumValue *> &EnumType::values() const {
45 return *mValues;
46}
47
Andreas Huber737080b2016-08-02 15:38:04 -070048const ScalarType *EnumType::resolveToScalarType() const {
49 return mStorageType->resolveToScalarType();
50}
51
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070052bool EnumType::isEnum() const {
53 return true;
54}
55
Steven Moreland979e0992016-09-07 09:18:08 -070056std::string EnumType::getCppType(StorageMode,
57 std::string *extra,
58 bool specifyNamespaces) const {
Andreas Huber881227d2016-08-02 14:20:21 -070059 extra->clear();
60
Steven Moreland979e0992016-09-07 09:18:08 -070061 return specifyNamespaces ? fullName() : partialCppName();
Andreas Huber881227d2016-08-02 14:20:21 -070062}
63
Andreas Huber4c865b72016-09-14 15:26:27 -070064std::string EnumType::getJavaType(
65 std::string *extra, bool forInitializer) const {
66 return mStorageType->resolveToScalarType()->getJavaType(
67 extra, forInitializer);
Andreas Huber2831d512016-08-15 09:33:47 -070068}
69
70std::string EnumType::getJavaSuffix() const {
71 return mStorageType->resolveToScalarType()->getJavaSuffix();
72}
73
Andreas Hubera3558b32016-09-14 09:12:42 -070074std::string EnumType::getJavaWrapperType() const {
75 return mStorageType->resolveToScalarType()->getJavaWrapperType();
76}
77
Andreas Huber881227d2016-08-02 14:20:21 -070078void EnumType::emitReaderWriter(
79 Formatter &out,
80 const std::string &name,
81 const std::string &parcelObj,
82 bool parcelObjIsPointer,
83 bool isReader,
84 ErrorMode mode) const {
Andreas Huber737080b2016-08-02 15:38:04 -070085 const ScalarType *scalarType = mStorageType->resolveToScalarType();
86 CHECK(scalarType != NULL);
87
88 scalarType->emitReaderWriterWithCast(
89 out,
90 name,
91 parcelObj,
92 parcelObjIsPointer,
93 isReader,
94 mode,
95 true /* needsCast */);
Andreas Huber881227d2016-08-02 14:20:21 -070096}
97
Andreas Huber85eabdb2016-08-25 11:24:49 -070098void EnumType::emitJavaFieldReaderWriter(
99 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700100 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700101 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700102 const std::string &blobName,
103 const std::string &fieldName,
104 const std::string &offset,
105 bool isReader) const {
106 return mStorageType->emitJavaFieldReaderWriter(
Andreas Huber709b62d2016-09-19 11:21:18 -0700107 out, depth, parcelName, blobName, fieldName, offset, isReader);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700108}
109
Andreas Huber881227d2016-08-02 14:20:21 -0700110status_t EnumType::emitTypeDeclarations(Formatter &out) const {
Andreas Huber737080b2016-08-02 15:38:04 -0700111 const ScalarType *scalarType = mStorageType->resolveToScalarType();
112 CHECK(scalarType != NULL);
113
Andreas Huber881227d2016-08-02 14:20:21 -0700114 std::string extra;
115
116 out << "enum class "
Andreas Huber0e00de42016-08-03 09:56:02 -0700117 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700118 << " : "
Andreas Huber737080b2016-08-02 15:38:04 -0700119 << ((Type *)scalarType)->getCppType(&extra)
Andreas Huber881227d2016-08-02 14:20:21 -0700120 << " {\n";
121
122 out.indent();
123
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700124 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700125 getTypeChain(&chain);
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700126
127 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
128 const auto &type = *it;
129
130 for (const auto &entry : type->values()) {
131 out << entry->name();
132
Yifan Hong57886972016-08-17 10:42:15 -0700133 const char *value = entry->cppValue(scalarType->getKind());
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700134 if (value != NULL) {
135 out << " = " << value;
136 }
137
Yifan Hong57886972016-08-17 10:42:15 -0700138 out << ",";
139
140 const char *comment = entry->comment();
141 if (comment != NULL && strcmp(comment, value) != 0) {
142 out << " // " << comment;
143 }
144
145 out << "\n";
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700146 }
Andreas Huber881227d2016-08-02 14:20:21 -0700147 }
148
149 out.unindent();
150 out << "};\n\n";
151
152 return OK;
153}
154
Andreas Huber2831d512016-08-15 09:33:47 -0700155// Attempt to convert enum value literals into their signed equivalents,
156// i.e. if an enum value is stored in typeName 'byte', the value "192"
157// will be converted to the output "-64".
158static bool MakeSignedIntegerValue(
159 const std::string &typeName, const char *value, std::string *output) {
160 output->clear();
161
162 char *end;
163 long long x = strtoll(value, &end, 10);
164
165 if (end > value && *end == '\0' && errno != ERANGE) {
166 char out[32];
167 if (typeName == "byte") {
168 sprintf(out, "%d", (int)(int8_t)x);
169 } else if (typeName == "short") {
170 sprintf(out, "%d", (int)(int16_t)x);
171 } else if (typeName == "int") {
172 sprintf(out, "%d", (int)(int32_t)x);
173 } else {
174 assert(typeName == "long");
Iliyan Malchev1c858082016-08-24 07:40:22 -0700175 sprintf(out, "%" PRId64 "L", (int64_t)x);
Andreas Huber2831d512016-08-15 09:33:47 -0700176 }
177
178 *output = out;
179 return true;
180 }
181
182 return false;
183}
184
Andreas Huber85eabdb2016-08-25 11:24:49 -0700185status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool) const {
Andreas Huber2831d512016-08-15 09:33:47 -0700186 const ScalarType *scalarType = mStorageType->resolveToScalarType();
187 CHECK(scalarType != NULL);
188
189 out << "public final class "
190 << localName()
191 << " {\n";
192
193 out.indent();
194
Andreas Huber4c865b72016-09-14 15:26:27 -0700195 std::string extra; // unused, because ScalarType leaves this empty.
196 const std::string typeName =
197 scalarType->getJavaType(&extra, false /* forInitializer */);
Andreas Huber2831d512016-08-15 09:33:47 -0700198
199 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700200 getTypeChain(&chain);
Andreas Huber2831d512016-08-15 09:33:47 -0700201
202 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
203 const auto &type = *it;
204
Andreas Huberab647c02016-09-14 09:44:00 -0700205 std::string prevEntryName;
Andreas Huber2831d512016-08-15 09:33:47 -0700206 for (const auto &entry : type->values()) {
207 out << "public static final "
208 << typeName
209 << " "
Andreas Huberab647c02016-09-14 09:44:00 -0700210 << entry->name()
211 << " = ";
Andreas Huber2831d512016-08-15 09:33:47 -0700212
Yifan Hong19ca75a2016-08-31 10:20:03 -0700213 const char *value = entry->javaValue(scalarType->getKind());
Andreas Huber2831d512016-08-15 09:33:47 -0700214 if (value != NULL) {
Andreas Huber2831d512016-08-15 09:33:47 -0700215 std::string convertedValue;
216 if (MakeSignedIntegerValue(typeName, value, &convertedValue)) {
217 out << convertedValue;
218 } else {
219 // The value is not an integer, but some other string,
220 // hopefully referring to some other enum name.
221 out << value;
222 }
Andreas Huberab647c02016-09-14 09:44:00 -0700223 } else if (prevEntryName.empty()) {
224 out << "0";
225 } else {
226 out << prevEntryName << " + 1";
Andreas Huber2831d512016-08-15 09:33:47 -0700227 }
228
Yifan Hong19ca75a2016-08-31 10:20:03 -0700229 out << ";";
230
231 const char *comment = entry->comment();
232 if (comment != NULL && strcmp(comment, value) != 0) {
233 out << " // " << comment;
234 }
235
236 out << "\n";
Andreas Huberab647c02016-09-14 09:44:00 -0700237
238 prevEntryName = entry->name();
Andreas Huber2831d512016-08-15 09:33:47 -0700239 }
240 }
241
242 out.unindent();
243 out << "};\n\n";
244
245 return OK;
246}
247
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700248status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700249 out << "name: \"" << localName() << "\"\n"
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700250 << "type: TYPE_ENUM\n"
251 << "enum_value: {\n";
252 out.indent();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700253
254 std::vector<const EnumType *> chain;
255 getTypeChain(&chain);
256
257 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
258 const auto &type = *it;
259
260 for (const auto &entry : type->values()) {
261 out << "enumerator: \"" << entry->name() << "\"\n";
262
263 const char *value = entry->value();
264 if (value != NULL) {
265 out << "value: " << value << "\n";
266 }
267 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700268 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700269
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700270 out.unindent();
271 out << "}\n";
272 return OK;
273}
274
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700275status_t EnumType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang19933522016-08-29 15:06:38 -0700276 out << "type: TYPE_ENUM\n"
277 << "predefined_type: \""
278 << localName()
279 << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700280 return OK;
281}
282
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700283void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
284 out->clear();
285 const EnumType *type = this;
286 for (;;) {
287 out->push_back(type);
288
289 const Type *superType = type->storageType();
290 if (superType == NULL || !superType->isEnum()) {
291 break;
292 }
293
294 type = static_cast<const EnumType *>(superType);
295 }
296}
297
Andreas Huber85eabdb2016-08-25 11:24:49 -0700298void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
299 mStorageType->getAlignmentAndSize(align, size);
300}
301
Andreas Huber31629bc2016-08-03 09:06:40 -0700302////////////////////////////////////////////////////////////////////////////////
303
Yifan Hong57886972016-08-17 10:42:15 -0700304EnumValue::EnumValue(const char *name, const ConstantExpression *value)
Andreas Huber31629bc2016-08-03 09:06:40 -0700305 : mName(name),
306 mValue(value) {
307}
308
309std::string EnumValue::name() const {
310 return mName;
311}
312
313const char *EnumValue::value() const {
Yifan Hong57886972016-08-17 10:42:15 -0700314 return mValue ? mValue->value() : nullptr;
315}
316
317const char *EnumValue::cppValue(ScalarType::Kind castKind) const {
318 return mValue ? mValue->cppValue(castKind) : nullptr;
319}
Yifan Hong19ca75a2016-08-31 10:20:03 -0700320const char *EnumValue::javaValue(ScalarType::Kind castKind) const {
321 return mValue ? mValue->javaValue(castKind) : nullptr;
322}
Yifan Hong57886972016-08-17 10:42:15 -0700323
324const char *EnumValue::comment() const {
325 return mValue ? mValue->description() : nullptr;
Andreas Huber31629bc2016-08-03 09:06:40 -0700326}
327
Andreas Huberc9410c72016-07-28 12:18:40 -0700328} // namespace android
329