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