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