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