blob: 45f9557cfb96f71d270b264f814e8295e4681e65 [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
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070021#include <inttypes.h>
22#include <hidl-util/Formatter.h>
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
Andreas Huberab647c02016-09-14 09:44:00 -0700194 std::string prevEntryName;
Andreas Huber2831d512016-08-15 09:33:47 -0700195 for (const auto &entry : type->values()) {
196 out << "public static final "
197 << typeName
198 << " "
Andreas Huberab647c02016-09-14 09:44:00 -0700199 << entry->name()
200 << " = ";
Andreas Huber2831d512016-08-15 09:33:47 -0700201
Yifan Hong19ca75a2016-08-31 10:20:03 -0700202 const char *value = entry->javaValue(scalarType->getKind());
Andreas Huber2831d512016-08-15 09:33:47 -0700203 if (value != NULL) {
Andreas Huber2831d512016-08-15 09:33:47 -0700204 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 }
Andreas Huberab647c02016-09-14 09:44:00 -0700212 } else if (prevEntryName.empty()) {
213 out << "0";
214 } else {
215 out << prevEntryName << " + 1";
Andreas Huber2831d512016-08-15 09:33:47 -0700216 }
217
Yifan Hong19ca75a2016-08-31 10:20:03 -0700218 out << ";";
219
220 const char *comment = entry->comment();
221 if (comment != NULL && strcmp(comment, value) != 0) {
222 out << " // " << comment;
223 }
224
225 out << "\n";
Andreas Huberab647c02016-09-14 09:44:00 -0700226
227 prevEntryName = entry->name();
Andreas Huber2831d512016-08-15 09:33:47 -0700228 }
229 }
230
231 out.unindent();
232 out << "};\n\n";
233
234 return OK;
235}
236
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700237status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700238 out << "name: \"" << localName() << "\"\n"
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700239 << "type: TYPE_ENUM\n"
240 << "enum_value: {\n";
241 out.indent();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700242
243 std::vector<const EnumType *> chain;
244 getTypeChain(&chain);
245
246 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
247 const auto &type = *it;
248
249 for (const auto &entry : type->values()) {
250 out << "enumerator: \"" << entry->name() << "\"\n";
251
252 const char *value = entry->value();
253 if (value != NULL) {
254 out << "value: " << value << "\n";
255 }
256 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700257 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700258
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700259 out.unindent();
260 out << "}\n";
261 return OK;
262}
263
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700264status_t EnumType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang19933522016-08-29 15:06:38 -0700265 out << "type: TYPE_ENUM\n"
266 << "predefined_type: \""
267 << localName()
268 << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700269 return OK;
270}
271
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700272void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
273 out->clear();
274 const EnumType *type = this;
275 for (;;) {
276 out->push_back(type);
277
278 const Type *superType = type->storageType();
279 if (superType == NULL || !superType->isEnum()) {
280 break;
281 }
282
283 type = static_cast<const EnumType *>(superType);
284 }
285}
286
Andreas Huber85eabdb2016-08-25 11:24:49 -0700287void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
288 mStorageType->getAlignmentAndSize(align, size);
289}
290
Andreas Huber31629bc2016-08-03 09:06:40 -0700291////////////////////////////////////////////////////////////////////////////////
292
Yifan Hong57886972016-08-17 10:42:15 -0700293EnumValue::EnumValue(const char *name, const ConstantExpression *value)
Andreas Huber31629bc2016-08-03 09:06:40 -0700294 : mName(name),
295 mValue(value) {
296}
297
298std::string EnumValue::name() const {
299 return mName;
300}
301
302const char *EnumValue::value() const {
Yifan Hong57886972016-08-17 10:42:15 -0700303 return mValue ? mValue->value() : nullptr;
304}
305
306const char *EnumValue::cppValue(ScalarType::Kind castKind) const {
307 return mValue ? mValue->cppValue(castKind) : nullptr;
308}
Yifan Hong19ca75a2016-08-31 10:20:03 -0700309const char *EnumValue::javaValue(ScalarType::Kind castKind) const {
310 return mValue ? mValue->javaValue(castKind) : nullptr;
311}
Yifan Hong57886972016-08-17 10:42:15 -0700312
313const char *EnumValue::comment() const {
314 return mValue ? mValue->description() : nullptr;
Andreas Huber31629bc2016-08-03 09:06:40 -0700315}
316
Andreas Huberc9410c72016-07-28 12:18:40 -0700317} // namespace android
318