blob: 4cfe227ff8f64603d4ce417efab1ee5d0d72a2a4 [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
122 const char *value = entry->value();
123 if (value != NULL) {
124 out << " = " << value;
125 }
126
127 out << ",\n";
128 }
Andreas Huber881227d2016-08-02 14:20:21 -0700129 }
130
131 out.unindent();
132 out << "};\n\n";
133
134 return OK;
135}
136
Andreas Huber2831d512016-08-15 09:33:47 -0700137// Attempt to convert enum value literals into their signed equivalents,
138// i.e. if an enum value is stored in typeName 'byte', the value "192"
139// will be converted to the output "-64".
140static bool MakeSignedIntegerValue(
141 const std::string &typeName, const char *value, std::string *output) {
142 output->clear();
143
144 char *end;
145 long long x = strtoll(value, &end, 10);
146
147 if (end > value && *end == '\0' && errno != ERANGE) {
148 char out[32];
149 if (typeName == "byte") {
150 sprintf(out, "%d", (int)(int8_t)x);
151 } else if (typeName == "short") {
152 sprintf(out, "%d", (int)(int16_t)x);
153 } else if (typeName == "int") {
154 sprintf(out, "%d", (int)(int32_t)x);
155 } else {
156 assert(typeName == "long");
Iliyan Malchev1c858082016-08-24 07:40:22 -0700157 sprintf(out, "%" PRId64 "L", (int64_t)x);
Andreas Huber2831d512016-08-15 09:33:47 -0700158 }
159
160 *output = out;
161 return true;
162 }
163
164 return false;
165}
166
Andreas Huber85eabdb2016-08-25 11:24:49 -0700167status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool) const {
Andreas Huber2831d512016-08-15 09:33:47 -0700168 const ScalarType *scalarType = mStorageType->resolveToScalarType();
169 CHECK(scalarType != NULL);
170
171 out << "public final class "
172 << localName()
173 << " {\n";
174
175 out.indent();
176
177 const std::string typeName = scalarType->getJavaType();
178
179 std::vector<const EnumType *> chain;
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700180 getTypeChain(&chain);
Andreas Huber2831d512016-08-15 09:33:47 -0700181
182 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
183 const auto &type = *it;
184
185 for (const auto &entry : type->values()) {
186 out << "public static final "
187 << typeName
188 << " "
189 << entry->name();
190
191 const char *value = entry->value();
192 if (value != NULL) {
193 out << " = ";
194
195 std::string convertedValue;
196 if (MakeSignedIntegerValue(typeName, value, &convertedValue)) {
197 out << convertedValue;
198 } else {
199 // The value is not an integer, but some other string,
200 // hopefully referring to some other enum name.
201 out << value;
202 }
203 }
204
205 out << ";\n";
206 }
207 }
208
209 out.unindent();
210 out << "};\n\n";
211
212 return OK;
213}
214
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700215status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700216 out << "name: \"" << localName() << "\"\n"
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700217 << "type: TYPE_ENUM\n"
218 << "enum_value: {\n";
219 out.indent();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700220
221 std::vector<const EnumType *> chain;
222 getTypeChain(&chain);
223
224 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
225 const auto &type = *it;
226
227 for (const auto &entry : type->values()) {
228 out << "enumerator: \"" << entry->name() << "\"\n";
229
230 const char *value = entry->value();
231 if (value != NULL) {
232 out << "value: " << value << "\n";
233 }
234 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700235 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700236
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700237 out.unindent();
238 out << "}\n";
239 return OK;
240}
241
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700242status_t EnumType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang19933522016-08-29 15:06:38 -0700243 out << "type: TYPE_ENUM\n"
244 << "predefined_type: \""
245 << localName()
246 << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700247 return OK;
248}
249
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700250void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
251 out->clear();
252 const EnumType *type = this;
253 for (;;) {
254 out->push_back(type);
255
256 const Type *superType = type->storageType();
257 if (superType == NULL || !superType->isEnum()) {
258 break;
259 }
260
261 type = static_cast<const EnumType *>(superType);
262 }
263}
264
Andreas Huber85eabdb2016-08-25 11:24:49 -0700265void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
266 mStorageType->getAlignmentAndSize(align, size);
267}
268
Andreas Huber31629bc2016-08-03 09:06:40 -0700269////////////////////////////////////////////////////////////////////////////////
270
271EnumValue::EnumValue(const char *name, const char *value)
272 : mName(name),
273 mValue(value) {
274}
275
276std::string EnumValue::name() const {
277 return mName;
278}
279
280const char *EnumValue::value() const {
281 return mValue;
282}
283
Andreas Huberc9410c72016-07-28 12:18:40 -0700284} // namespace android
285