1 /*
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
17 #include "ScalarType.h"
18
19 #include <hidl-util/Formatter.h>
20
21 namespace android {
22
23 static const char* const hidlIdentifiers[] = {"bool", "int8_t", "uint8_t", "int16_t",
24 "uint16_t", "int32_t", "uint32_t", "int64_t",
25 "uint64_t", "float", "double"};
26
ScalarType(Kind kind,Scope * parent)27 ScalarType::ScalarType(Kind kind, Scope* parent)
28 : Type(parent, hidlIdentifiers[kind]), mKind(kind) {}
29
resolveToScalarType() const30 const ScalarType *ScalarType::resolveToScalarType() const {
31 return this;
32 }
33
isValidEnumStorageType() const34 bool ScalarType::isValidEnumStorageType() const {
35 // Only integer types.
36 return mKind >= KIND_INT8 && mKind <= KIND_UINT64;
37 }
38
isScalar() const39 bool ScalarType::isScalar() const {
40 return true;
41 }
42
isElidableType() const43 bool ScalarType::isElidableType() const {
44 return true;
45 }
46
deepCanCheckEquality(std::unordered_set<const Type * > *) const47 bool ScalarType::deepCanCheckEquality(std::unordered_set<const Type*>* /* visited */) const {
48 return true;
49 }
50
typeName() const51 std::string ScalarType::typeName() const {
52 return getCppStackType();
53 }
54
getCppType(StorageMode,bool) const55 std::string ScalarType::getCppType(StorageMode, bool) const {
56 static const char *const kName[] = {
57 "bool",
58 "int8_t",
59 "uint8_t",
60 "int16_t",
61 "uint16_t",
62 "int32_t",
63 "uint32_t",
64 "int64_t",
65 "uint64_t",
66 "float",
67 "double"
68 };
69
70 return kName[mKind];
71 }
72
getJavaType(bool) const73 std::string ScalarType::getJavaType(bool /* forInitializer */) const {
74 static const char *const kName[] = {
75 "boolean",
76 "byte",
77 "byte",
78 "short",
79 "short",
80 "int",
81 "int",
82 "long",
83 "long",
84 "float",
85 "double"
86 };
87
88 return kName[mKind];
89 }
90
getJavaTypeClass() const91 std::string ScalarType::getJavaTypeClass() const {
92 static const char *const kName[] = {
93 "Boolean",
94 "Byte",
95 "Byte",
96 "Short",
97 "Short",
98 "Integer",
99 "Integer",
100 "Long",
101 "Long",
102 "Float",
103 "Double"
104 };
105
106 return kName[mKind];
107 }
108
getJavaSuffix() const109 std::string ScalarType::getJavaSuffix() const {
110 static const char *const kSuffix[] = {
111 "Bool",
112 "Int8",
113 "Int8",
114 "Int16",
115 "Int16",
116 "Int32",
117 "Int32",
118 "Int64",
119 "Int64",
120 "Float",
121 "Double"
122 };
123
124 return kSuffix[mKind];
125 }
126
getVtsType() const127 std::string ScalarType::getVtsType() const {
128 return "TYPE_SCALAR";
129 }
130
getVtsScalarType() const131 std::string ScalarType::getVtsScalarType() const {
132 static const char * const kName[] = {
133 "bool_t",
134 "int8_t",
135 "uint8_t",
136 "int16_t",
137 "uint16_t",
138 "int32_t",
139 "uint32_t",
140 "int64_t",
141 "uint64_t",
142 "float_t",
143 "double_t"
144 };
145
146 return kName[mKind];
147 }
148
emitJavaFieldInitializer(Formatter & out,const std::string & fieldName) const149 void ScalarType::emitJavaFieldInitializer(Formatter& out, const std::string& fieldName) const {
150 const std::string typeName = getJavaType(false /* forInitializer */);
151 const std::string fieldDeclaration = typeName + " " + fieldName;
152
153 emitJavaFieldDefaultInitialValue(out, fieldDeclaration);
154 }
155
emitJavaFieldDefaultInitialValue(Formatter & out,const std::string & declaredFieldName) const156 void ScalarType::emitJavaFieldDefaultInitialValue(Formatter& out,
157 const std::string& declaredFieldName) const {
158 static const char* const kInitialValue[] = {
159 "false", // boolean
160 "0", // byte
161 "0", // byte
162 "0", // short
163 "0", // short
164 "0", // int
165 "0", // int
166 "0L", // long
167 "0L", // long
168 "0.0f", // float
169 "0.0d" // double
170 };
171
172 out << declaredFieldName << " = " << kInitialValue[mKind] << ";\n";
173 }
174
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const175 void ScalarType::emitReaderWriter(
176 Formatter &out,
177 const std::string &name,
178 const std::string &parcelObj,
179 bool parcelObjIsPointer,
180 bool isReader,
181 ErrorMode mode) const {
182 emitReaderWriterWithCast(
183 out,
184 name,
185 parcelObj,
186 parcelObjIsPointer,
187 isReader,
188 mode,
189 false /* needsCast */);
190 }
191
emitReaderWriterWithCast(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode,bool needsCast) const192 void ScalarType::emitReaderWriterWithCast(
193 Formatter &out,
194 const std::string &name,
195 const std::string &parcelObj,
196 bool parcelObjIsPointer,
197 bool isReader,
198 ErrorMode mode,
199 bool needsCast) const {
200 static const char *const kSuffix[] = {
201 "Bool",
202 "Int8",
203 "Uint8",
204 "Int16",
205 "Uint16",
206 "Int32",
207 "Uint32",
208 "Int64",
209 "Uint64",
210 "Float",
211 "Double"
212 };
213
214 const std::string parcelObjDeref =
215 parcelObj + (parcelObjIsPointer ? "->" : ".");
216
217 out << "_hidl_err = "
218 << parcelObjDeref
219 << (isReader ? "read" : "write")
220 << kSuffix[mKind]
221 << "(";
222
223 if (needsCast) {
224 out << "("
225 << getCppStackType()
226 << (isReader ? " *)" : ")");
227 }
228
229 if (isReader) {
230 out << "&";
231 }
232
233 out << name
234 << ");\n";
235
236 handleError(out, mode);
237 }
238
emitHexDump(Formatter & out,const std::string & streamName,const std::string & name) const239 void ScalarType::emitHexDump(
240 Formatter &out,
241 const std::string &streamName,
242 const std::string &name) const {
243 out << streamName << " += toHexString(" << name << ");\n";
244 }
245
emitConvertToJavaHexString(Formatter & out,const std::string & name) const246 void ScalarType::emitConvertToJavaHexString(
247 Formatter &out,
248 const std::string &name) const {
249 switch(mKind) {
250 case KIND_BOOL: {
251 out << "((" << name << ") ? \"0x1\" : \"0x0\")";
252 break;
253 }
254 case KIND_INT8: // fallthrough
255 case KIND_UINT8: // fallthrough
256 case KIND_INT16: // fallthrough
257 case KIND_UINT16: {
258 // Because Byte and Short doesn't have toHexString, we have to use Integer.toHexString.
259 out << "Integer.toHexString(" << getJavaTypeClass() << ".toUnsignedInt(("
260 << getJavaType(false /* forInitializer */) << ")(" << name << ")))";
261 break;
262 }
263 case KIND_INT32: // fallthrough
264 case KIND_UINT32: // fallthrough
265 case KIND_INT64: // fallthrough
266 case KIND_UINT64: {
267 out << getJavaTypeClass() << ".toHexString(" << name << ")";
268 break;
269 }
270 case KIND_FLOAT: // fallthrough
271 case KIND_DOUBLE: // fallthrough
272 default: {
273 // no hex for floating point numbers.
274 out << name;
275 break;
276 }
277 }
278 }
279
emitJavaFieldReaderWriter(Formatter & out,size_t,const std::string &,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const280 void ScalarType::emitJavaFieldReaderWriter(
281 Formatter &out,
282 size_t /* depth */,
283 const std::string & /* parcelName */,
284 const std::string &blobName,
285 const std::string &fieldName,
286 const std::string &offset,
287 bool isReader) const {
288 if (isReader) {
289 out << fieldName
290 << " = "
291 << blobName
292 << ".get"
293 << getJavaSuffix()
294 << "("
295 << offset
296 << ");\n";
297
298 return;
299 }
300
301 out << blobName
302 << ".put"
303 << getJavaSuffix()
304 << "("
305 << offset
306 << ", "
307 << fieldName
308 << ");\n";
309 }
310
emitVtsTypeDeclarations(Formatter & out) const311 void ScalarType::emitVtsTypeDeclarations(Formatter& out) const {
312 out << "type: " << getVtsType() << "\n";
313 out << "scalar_type: \"" << getVtsScalarType() << "\"\n";
314 }
315
getAlignmentAndSize(size_t * align,size_t * size) const316 void ScalarType::getAlignmentAndSize(size_t *align, size_t *size) const {
317 static const size_t kAlign[] = {
318 1, // bool, this is NOT standardized!
319 1, // int8_t
320 1, // uint8_t
321 2, // int16_t
322 2, // uint16_t
323 4, // int32_t
324 4, // uint32_t
325 8, // int64_t
326 8, // uint64_t
327 4, // float
328 8 // double
329 };
330
331 *align = *size = kAlign[mKind];
332 }
333
getKind() const334 ScalarType::Kind ScalarType::getKind() const {
335 return mKind;
336 }
337
338 } // namespace android
339
340