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
ScalarType(Kind kind)23 ScalarType::ScalarType(Kind kind)
24 : mKind(kind) {
25 }
26
resolveToScalarType() const27 const ScalarType *ScalarType::resolveToScalarType() const {
28 return this;
29 }
30
isValidEnumStorageType() const31 bool ScalarType::isValidEnumStorageType() const {
32 // Only integer types.
33 return mKind >= KIND_INT8 && mKind <= KIND_UINT64;
34 }
35
isScalar() const36 bool ScalarType::isScalar() const {
37 return true;
38 }
39
isElidableType() const40 bool ScalarType::isElidableType() const {
41 return true;
42 }
43
canCheckEquality() const44 bool ScalarType::canCheckEquality() const {
45 return true;
46 }
47
typeName() const48 std::string ScalarType::typeName() const {
49 return getCppStackType();
50 }
51
getCppType(StorageMode,bool) const52 std::string ScalarType::getCppType(StorageMode, bool) const {
53 static const char *const kName[] = {
54 "bool",
55 "int8_t",
56 "uint8_t",
57 "int16_t",
58 "uint16_t",
59 "int32_t",
60 "uint32_t",
61 "int64_t",
62 "uint64_t",
63 "float",
64 "double"
65 };
66
67 return kName[mKind];
68 }
69
getJavaType(bool) const70 std::string ScalarType::getJavaType(bool /* forInitializer */) const {
71 static const char *const kName[] = {
72 "boolean",
73 "byte",
74 "byte",
75 "short",
76 "short",
77 "int",
78 "int",
79 "long",
80 "long",
81 "float",
82 "double"
83 };
84
85 return kName[mKind];
86 }
87
getJavaWrapperType() const88 std::string ScalarType::getJavaWrapperType() const {
89 static const char *const kName[] = {
90 "Boolean",
91 "Byte",
92 "Byte",
93 "Short",
94 "Short",
95 "Integer",
96 "Integer",
97 "Long",
98 "Long",
99 "Float",
100 "Double"
101 };
102
103 return kName[mKind];
104 }
105
getJavaSuffix() const106 std::string ScalarType::getJavaSuffix() const {
107 static const char *const kSuffix[] = {
108 "Bool",
109 "Int8",
110 "Int8",
111 "Int16",
112 "Int16",
113 "Int32",
114 "Int32",
115 "Int64",
116 "Int64",
117 "Float",
118 "Double"
119 };
120
121 return kSuffix[mKind];
122 }
123
getVtsType() const124 std::string ScalarType::getVtsType() const {
125 return "TYPE_SCALAR";
126 }
127
getVtsScalarType() const128 std::string ScalarType::getVtsScalarType() const {
129 static const char * const kName[] = {
130 "bool_t",
131 "int8_t",
132 "uint8_t",
133 "int16_t",
134 "uint16_t",
135 "int32_t",
136 "uint32_t",
137 "int64_t",
138 "uint64_t",
139 "float_t",
140 "double_t"
141 };
142
143 return kName[mKind];
144 }
145
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const146 void ScalarType::emitReaderWriter(
147 Formatter &out,
148 const std::string &name,
149 const std::string &parcelObj,
150 bool parcelObjIsPointer,
151 bool isReader,
152 ErrorMode mode) const {
153 emitReaderWriterWithCast(
154 out,
155 name,
156 parcelObj,
157 parcelObjIsPointer,
158 isReader,
159 mode,
160 false /* needsCast */);
161 }
162
emitReaderWriterWithCast(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode,bool needsCast) const163 void ScalarType::emitReaderWriterWithCast(
164 Formatter &out,
165 const std::string &name,
166 const std::string &parcelObj,
167 bool parcelObjIsPointer,
168 bool isReader,
169 ErrorMode mode,
170 bool needsCast) const {
171 static const char *const kSuffix[] = {
172 "Bool",
173 "Int8",
174 "Uint8",
175 "Int16",
176 "Uint16",
177 "Int32",
178 "Uint32",
179 "Int64",
180 "Uint64",
181 "Float",
182 "Double"
183 };
184
185 const std::string parcelObjDeref =
186 parcelObj + (parcelObjIsPointer ? "->" : ".");
187
188 out << "_hidl_err = "
189 << parcelObjDeref
190 << (isReader ? "read" : "write")
191 << kSuffix[mKind]
192 << "(";
193
194 if (needsCast) {
195 out << "("
196 << getCppStackType()
197 << (isReader ? " *)" : ")");
198 }
199
200 if (isReader) {
201 out << "&";
202 }
203
204 out << name
205 << ");\n";
206
207 handleError(out, mode);
208 }
209
emitHexDump(Formatter & out,const std::string & streamName,const std::string & name) const210 void ScalarType::emitHexDump(
211 Formatter &out,
212 const std::string &streamName,
213 const std::string &name) const {
214 out << streamName << " += toHexString(" << name << ");\n";
215 }
216
emitConvertToJavaHexString(Formatter & out,const std::string & name) const217 void ScalarType::emitConvertToJavaHexString(
218 Formatter &out,
219 const std::string &name) const {
220 switch(mKind) {
221 case KIND_BOOL: {
222 out << "((" << name << ") ? \"0x1\" : \"0x0\")";
223 break;
224 }
225 case KIND_INT8: // fallthrough
226 case KIND_UINT8: // fallthrough
227 case KIND_INT16: // fallthrough
228 case KIND_UINT16: {
229 // Because Byte and Short doesn't have toHexString, we have to use Integer.toHexString.
230 out << "Integer.toHexString(" << getJavaWrapperType() << ".toUnsignedInt(("
231 << getJavaType(false /* forInitializer */) << ")(" << name << ")))";
232 break;
233 }
234 case KIND_INT32: // fallthrough
235 case KIND_UINT32: // fallthrough
236 case KIND_INT64: // fallthrough
237 case KIND_UINT64: {
238 out << getJavaWrapperType() << ".toHexString(" << name << ")";
239 break;
240 }
241 case KIND_FLOAT: // fallthrough
242 case KIND_DOUBLE: // fallthrough
243 default: {
244 // no hex for floating point numbers.
245 out << name;
246 break;
247 }
248 }
249 }
250
emitJavaFieldReaderWriter(Formatter & out,size_t,const std::string &,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const251 void ScalarType::emitJavaFieldReaderWriter(
252 Formatter &out,
253 size_t /* depth */,
254 const std::string & /* parcelName */,
255 const std::string &blobName,
256 const std::string &fieldName,
257 const std::string &offset,
258 bool isReader) const {
259 if (isReader) {
260 out << fieldName
261 << " = "
262 << blobName
263 << ".get"
264 << getJavaSuffix()
265 << "("
266 << offset
267 << ");\n";
268
269 return;
270 }
271
272 out << blobName
273 << ".put"
274 << getJavaSuffix()
275 << "("
276 << offset
277 << ", "
278 << fieldName
279 << ");\n";
280 }
281
emitVtsTypeDeclarations(Formatter & out) const282 status_t ScalarType::emitVtsTypeDeclarations(Formatter &out) const {
283 out << "type: " << getVtsType() << "\n";
284 out << "scalar_type: \"" << getVtsScalarType() << "\"\n";
285 return OK;
286 }
287
getAlignmentAndSize(size_t * align,size_t * size) const288 void ScalarType::getAlignmentAndSize(size_t *align, size_t *size) const {
289 static const size_t kAlign[] = {
290 1, // bool, this is NOT standardized!
291 1, // int8_t
292 1, // uint8_t
293 2, // int16_t
294 2, // uint16_t
295 4, // int32_t
296 4, // uint32_t
297 8, // int64_t
298 8, // uint64_t
299 4, // float
300 8 // double
301 };
302
303 *align = *size = kAlign[mKind];
304 }
305
getKind() const306 ScalarType::Kind ScalarType::getKind() const {
307 return mKind;
308 }
309
310 } // namespace android
311
312