blob: 6c610ff42c10da6d798d561ca90bbfc89dcfcb3a [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
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
Andreas Huberc9410c72016-07-28 12:18:40 -070017#include "ArrayType.h"
18
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070019#include <hidl-util/Formatter.h>
Andreas Huber881227d2016-08-02 14:20:21 -070020#include <android-base/logging.h>
21
Yifan Hongf24fa852016-09-23 11:03:15 -070022#include "ConstantExpression.h"
23
Andreas Huberc9410c72016-07-28 12:18:40 -070024namespace android {
25
Yifan Hongf24fa852016-09-23 11:03:15 -070026ArrayType::ArrayType(ArrayType *srcArray, ConstantExpression *size)
Andreas Huber709b62d2016-09-19 11:21:18 -070027 : mElementType(srcArray->mElementType),
Yifan Hongf24fa852016-09-23 11:03:15 -070028 mSizes(srcArray->mSizes),
29 mSizeComments(srcArray->mSizeComments) {
Andreas Huber709b62d2016-09-19 11:21:18 -070030 addDimension(size);
31}
32
Yifan Hongf24fa852016-09-23 11:03:15 -070033ArrayType::ArrayType(Type *elementType, ConstantExpression *size)
Andreas Huber709b62d2016-09-19 11:21:18 -070034 : mElementType(elementType) {
35 addDimension(size);
36}
37
Yifan Hongf24fa852016-09-23 11:03:15 -070038void ArrayType::addDimension(ConstantExpression *size) {
Yifan Honge77ca132016-09-27 10:49:05 -070039 mSizes.insert(mSizes.begin(), size->castSizeT());
Yifan Hongf24fa852016-09-23 11:03:15 -070040 mSizeComments.insert(mSizeComments.begin(), size->description());
Andreas Huberc9410c72016-07-28 12:18:40 -070041}
42
Andreas Huberf03332a2016-09-22 15:35:43 -070043size_t ArrayType::countDimensions() const {
44 return mSizes.size();
45}
46
Steven Moreland979e0992016-09-07 09:18:08 -070047void ArrayType::addNamedTypesToSet(std::set<const FQName> &set) const {
48 mElementType->addNamedTypesToSet(set);
49}
50
Andreas Huber709b62d2016-09-19 11:21:18 -070051bool ArrayType::isArray() const {
52 return true;
53}
54
Andreas Huberf03332a2016-09-22 15:35:43 -070055Type *ArrayType::getElementType() const {
56 return mElementType;
57}
58
Steven Moreland979e0992016-09-07 09:18:08 -070059std::string ArrayType::getCppType(StorageMode mode,
60 std::string *extra,
61 bool specifyNamespaces) const {
62 const std::string base = mElementType->getCppType(extra, specifyNamespaces);
Andreas Huber709b62d2016-09-19 11:21:18 -070063 CHECK(extra->empty());
Andreas Huber881227d2016-08-02 14:20:21 -070064
Steven Morelandc46e9842016-11-02 13:21:26 -070065 std::string space = specifyNamespaces ? "::android::hardware::" : "";
66 std::string arrayType = space + "hidl_array<" + base;
Andreas Huberf03332a2016-09-22 15:35:43 -070067
68 for (size_t i = 0; i < mSizes.size(); ++i) {
69 arrayType += ", ";
70 arrayType += std::to_string(mSizes[i]);
71
72 arrayType += " /* ";
73 arrayType += mSizeComments[i];
74 arrayType += " */";
Andreas Huber709b62d2016-09-19 11:21:18 -070075 }
76
Andreas Huberf03332a2016-09-22 15:35:43 -070077 arrayType += ">";
Andreas Huber881227d2016-08-02 14:20:21 -070078
79 switch (mode) {
80 case StorageMode_Stack:
Andreas Huberf03332a2016-09-22 15:35:43 -070081 return arrayType;
Andreas Huber881227d2016-08-02 14:20:21 -070082
83 case StorageMode_Argument:
Andreas Huberf03332a2016-09-22 15:35:43 -070084 return "const " + arrayType + "&";
85
Andreas Huber881227d2016-08-02 14:20:21 -070086 case StorageMode_Result:
Andreas Huberf03332a2016-09-22 15:35:43 -070087 return "const " + arrayType + "*";
Andreas Huber881227d2016-08-02 14:20:21 -070088 }
Andreas Huberf03332a2016-09-22 15:35:43 -070089
90 CHECK(!"Should not be here");
Andreas Huber881227d2016-08-02 14:20:21 -070091}
92
Andreas Huber4c865b72016-09-14 15:26:27 -070093std::string ArrayType::getJavaType(
94 std::string *extra, bool forInitializer) const {
95 std::string baseExtra;
96 const std::string base =
97 mElementType->getJavaType(&baseExtra, forInitializer);
98
Andreas Huber709b62d2016-09-19 11:21:18 -070099 CHECK(baseExtra.empty());
100
101 extra->clear();
102
Yifan Hongf24fa852016-09-23 11:03:15 -0700103 CHECK(mSizes.size() == mSizeComments.size());
104 for (size_t i = 0; i < mSizes.size(); ++i) {
Andreas Huber709b62d2016-09-19 11:21:18 -0700105 *extra += "[";
106
107 if (forInitializer) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700108 *extra += std::to_string(mSizes[i]);
109 *extra += " ";
Andreas Huber709b62d2016-09-19 11:21:18 -0700110 }
111
Yifan Hongf24fa852016-09-23 11:03:15 -0700112 *extra += "/* " + mSizeComments[i] + " */";
113
Andreas Huber709b62d2016-09-19 11:21:18 -0700114 *extra += "]";
Andreas Huber4c865b72016-09-14 15:26:27 -0700115 }
Andreas Huber4c865b72016-09-14 15:26:27 -0700116
117 return base;
Andreas Huber2831d512016-08-15 09:33:47 -0700118}
119
Andreas Huberf03332a2016-09-22 15:35:43 -0700120std::string ArrayType::getJavaWrapperType() const {
121 return mElementType->getJavaWrapperType();
122}
123
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700124std::string ArrayType::getVtsType() const {
125 return "TYPE_ARRAY";
126}
127
Andreas Huber881227d2016-08-02 14:20:21 -0700128void ArrayType::emitReaderWriter(
129 Formatter &out,
130 const std::string &name,
131 const std::string &parcelObj,
132 bool parcelObjIsPointer,
133 bool isReader,
134 ErrorMode mode) const {
135 std::string baseExtra;
136 std::string baseType = mElementType->getCppType(&baseExtra);
Andreas Huber709b62d2016-09-19 11:21:18 -0700137 CHECK(baseExtra.empty());
Andreas Huber881227d2016-08-02 14:20:21 -0700138
Iliyan Malchev549e2592016-08-10 08:59:12 -0700139 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700140
141 out << "size_t " << parentName << ";\n\n";
142
143 const std::string parcelObjDeref =
144 parcelObj + (parcelObjIsPointer ? "->" : ".");
145
146 if (isReader) {
Andreas Huberf03332a2016-09-22 15:35:43 -0700147 std::string extra;
148
Andreas Huber881227d2016-08-02 14:20:21 -0700149 out << name
Andreas Huberf03332a2016-09-22 15:35:43 -0700150 << " = ("
151 << getCppResultType(&extra)
152 << ")"
Andreas Huber881227d2016-08-02 14:20:21 -0700153 << parcelObjDeref
154 << "readBuffer(&"
155 << parentName
156 << ");\n\n";
157
158 out << "if (" << name << " == nullptr) {\n";
159
160 out.indent();
161
Iliyan Malchev549e2592016-08-10 08:59:12 -0700162 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700163 handleError2(out, mode);
164
165 out.unindent();
166 out << "}\n\n";
167 } else {
Andreas Huberf03332a2016-09-22 15:35:43 -0700168 size_t numArrayElements = 1;
169 for (auto size : mSizes) {
170 numArrayElements *= size;
171 }
172
Iliyan Malchev549e2592016-08-10 08:59:12 -0700173 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700174 << parcelObjDeref
175 << "writeBuffer("
176 << name
Andreas Huberf03332a2016-09-22 15:35:43 -0700177 << ".data(), "
178 << numArrayElements
179 << " * sizeof("
Andreas Huber881227d2016-08-02 14:20:21 -0700180 << baseType
181 << "), &"
182 << parentName
183 << ");\n";
184
185 handleError(out, mode);
186 }
187
188 emitReaderWriterEmbedded(
189 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700190 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700191 name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700192 name /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700193 isReader /* nameIsPointer */,
194 parcelObj,
195 parcelObjIsPointer,
196 isReader,
197 mode,
198 parentName,
199 "0 /* parentOffset */");
200}
201
202void ArrayType::emitReaderWriterEmbedded(
203 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700204 size_t depth,
Andreas Huber881227d2016-08-02 14:20:21 -0700205 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700206 const std::string &sanitizedName,
Andreas Huber881227d2016-08-02 14:20:21 -0700207 bool nameIsPointer,
208 const std::string &parcelObj,
209 bool parcelObjIsPointer,
210 bool isReader,
211 ErrorMode mode,
212 const std::string &parentName,
213 const std::string &offsetText) const {
214 if (!mElementType->needsEmbeddedReadWrite()) {
215 return;
216 }
217
218 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
219
220 std::string baseExtra;
221 std::string baseType = mElementType->getCppType(&baseExtra);
Andreas Huber709b62d2016-09-19 11:21:18 -0700222 CHECK(baseExtra.empty());
Andreas Huber881227d2016-08-02 14:20:21 -0700223
Andreas Huberf9d49f12016-09-12 14:58:36 -0700224 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
225
226 out << "for (size_t "
227 << iteratorName
228 << " = 0; "
229 << iteratorName
230 << " < "
Yifan Hongbf459bc2016-08-23 16:50:37 -0700231 << dimension()
Andreas Huberf9d49f12016-09-12 14:58:36 -0700232 << "; ++"
233 << iteratorName
234 << ") {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700235
236 out.indent();
237
238 mElementType->emitReaderWriterEmbedded(
239 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700240 depth + 1,
Andreas Huberf03332a2016-09-22 15:35:43 -0700241 nameDeref + "data()[" + iteratorName + "]",
Yifan Hongbe2a3732016-10-05 13:33:41 -0700242 sanitizedName + "_indexed",
Andreas Huber881227d2016-08-02 14:20:21 -0700243 false /* nameIsPointer */,
244 parcelObj,
245 parcelObjIsPointer,
246 isReader,
247 mode,
248 parentName,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700249 offsetText
250 + " + " + iteratorName + " * sizeof("
251 + baseType
Andreas Huberf9d49f12016-09-12 14:58:36 -0700252 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700253
254 out.unindent();
255
256 out << "}\n\n";
257}
258
Yifan Hongbf459bc2016-08-23 16:50:37 -0700259void ArrayType::emitResolveReferences(
260 Formatter &out,
261 const std::string &name,
262 bool nameIsPointer,
263 const std::string &parcelObj,
264 bool parcelObjIsPointer,
265 bool isReader,
266 ErrorMode mode) const {
267 emitResolveReferencesEmbedded(
268 out,
269 0 /* depth */,
270 name,
271 name /* sanitizedName */,
272 nameIsPointer,
273 parcelObj,
274 parcelObjIsPointer,
275 isReader,
276 mode,
277 "_hidl_" + name + "_parent",
278 "0 /* parentOffset */");
279}
280
281void ArrayType::emitResolveReferencesEmbedded(
282 Formatter &out,
283 size_t depth,
284 const std::string &name,
285 const std::string &sanitizedName,
286 bool nameIsPointer,
287 const std::string &parcelObj,
288 bool parcelObjIsPointer,
289 bool isReader,
290 ErrorMode mode,
291 const std::string &parentName,
292 const std::string &offsetText) const {
293 CHECK(needsResolveReferences() && mElementType->needsResolveReferences());
294
295 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
296
297 std::string baseExtra;
298 std::string baseType = mElementType->getCppType(&baseExtra);
299
300 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
301
302 out << "for (size_t "
303 << iteratorName
304 << " = 0; "
305 << iteratorName
306 << " < "
307 << dimension()
308 << "; ++"
309 << iteratorName
310 << ") {\n";
311
312 out.indent();
313
314 mElementType->emitResolveReferencesEmbedded(
315 out,
316 depth + 1,
317 nameDeref + "data()[" + iteratorName + "]",
318 sanitizedName + "_indexed",
319 false /* nameIsPointer */,
320 parcelObj,
321 parcelObjIsPointer,
322 isReader,
323 mode,
324 parentName,
325 offsetText + " + " + iteratorName + " * sizeof("
326 + baseType
327 + ")");
328
329 out.unindent();
330
331 out << "}\n\n";
332}
333
334
Andreas Huber881227d2016-08-02 14:20:21 -0700335bool ArrayType::needsEmbeddedReadWrite() const {
336 return mElementType->needsEmbeddedReadWrite();
337}
338
Yifan Hongbf459bc2016-08-23 16:50:37 -0700339bool ArrayType::needsResolveReferences() const {
340 return mElementType->needsResolveReferences();
341}
342
Andreas Huberf03332a2016-09-22 15:35:43 -0700343bool ArrayType::resultNeedsDeref() const {
344 return true;
345}
346
Andreas Huber2831d512016-08-15 09:33:47 -0700347void ArrayType::emitJavaReaderWriter(
348 Formatter &out,
349 const std::string &parcelObj,
350 const std::string &argName,
351 bool isReader) const {
Andreas Huber709b62d2016-09-19 11:21:18 -0700352 if (isReader) {
353 std::string extra;
354 out << "new "
355 << getJavaType(&extra, true /* forInitializer */)
356 << extra
357 << ";\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700358 }
359
Andreas Huber709b62d2016-09-19 11:21:18 -0700360 out << "{\n";
361 out.indent();
362
363 out << "HwBlob _hidl_blob = ";
364
365 if (isReader) {
366 out << parcelObj
367 << ".readBuffer();\n";
368 } else {
369 size_t align, size;
370 getAlignmentAndSize(&align, &size);
371
372 out << "new HwBlob("
373 << size
374 << " /* size */);\n";
375 }
376
377 emitJavaFieldReaderWriter(
Andreas Huber2831d512016-08-15 09:33:47 -0700378 out,
Andreas Huber709b62d2016-09-19 11:21:18 -0700379 0 /* depth */,
Andreas Huber2831d512016-08-15 09:33:47 -0700380 parcelObj,
Andreas Huber709b62d2016-09-19 11:21:18 -0700381 "_hidl_blob",
Andreas Huber2831d512016-08-15 09:33:47 -0700382 argName,
Andreas Huber709b62d2016-09-19 11:21:18 -0700383 "0 /* offset */",
384 isReader);
385
386 if (!isReader) {
387 out << parcelObj << ".writeBuffer(_hidl_blob);\n";
388 }
389
390 out.unindent();
391 out << "}\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700392}
393
Andreas Huber85eabdb2016-08-25 11:24:49 -0700394void ArrayType::emitJavaFieldInitializer(
395 Formatter &out, const std::string &fieldName) const {
Andreas Huber4c865b72016-09-14 15:26:27 -0700396 std::string extra;
397 std::string typeName = getJavaType(&extra, false /* forInitializer */);
398
399 std::string extraInit;
400 getJavaType(&extraInit, true /* forInitializer */);
401
Andreas Hubercd5e6662016-08-30 15:02:59 -0700402 out << "final "
Andreas Huber4c865b72016-09-14 15:26:27 -0700403 << typeName
404 << extra
405 << " "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700406 << fieldName
407 << " = new "
Andreas Huber4c865b72016-09-14 15:26:27 -0700408 << typeName
409 << extraInit
410 << ";\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700411}
412
413void ArrayType::emitJavaFieldReaderWriter(
414 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700415 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700416 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700417 const std::string &blobName,
418 const std::string &fieldName,
419 const std::string &offset,
420 bool isReader) const {
Andreas Huber90e8fc22016-09-21 16:36:15 -0700421 out << "{\n";
422 out.indent();
423
Andreas Huber709b62d2016-09-19 11:21:18 -0700424 std::string offsetName = "_hidl_array_offset_" + std::to_string(depth);
425 out << "long " << offsetName << " = " << offset << ";\n";
Andreas Huber4c865b72016-09-14 15:26:27 -0700426
Andreas Huber709b62d2016-09-19 11:21:18 -0700427 std::string indexString;
428 for (size_t dim = 0; dim < mSizes.size(); ++dim) {
429 std::string iteratorName =
430 "_hidl_index_" + std::to_string(depth) + "_" + std::to_string(dim);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700431
Andreas Huber709b62d2016-09-19 11:21:18 -0700432 out << "for (int "
433 << iteratorName
434 << " = 0; "
435 << iteratorName
436 << " < "
437 << mSizes[dim]
438 << "; ++"
439 << iteratorName
440 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700441
Andreas Huber709b62d2016-09-19 11:21:18 -0700442 out.indent();
443
444 indexString += "[" + iteratorName + "]";
445 }
446
447 if (isReader && mElementType->isCompoundType()) {
448 std::string extra;
449 std::string typeName =
450 mElementType->getJavaType(&extra, false /* forInitializer */);
451
452 CHECK(extra.empty());
453
454 out << fieldName
455 << indexString
456 << " = new "
457 << typeName
458 << "();\n";
459 }
Andreas Huber85eabdb2016-08-25 11:24:49 -0700460
461 mElementType->emitJavaFieldReaderWriter(
462 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700463 depth + 1,
Andreas Huber709b62d2016-09-19 11:21:18 -0700464 parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700465 blobName,
Andreas Huber709b62d2016-09-19 11:21:18 -0700466 fieldName + indexString,
467 offsetName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700468 isReader);
469
Andreas Huber709b62d2016-09-19 11:21:18 -0700470 size_t elementAlign, elementSize;
471 mElementType->getAlignmentAndSize(&elementAlign, &elementSize);
472
473 out << offsetName << " += " << std::to_string(elementSize) << ";\n";
474
475 for (size_t dim = 0; dim < mSizes.size(); ++dim) {
476 out.unindent();
477 out << "}\n";
478 }
Andreas Huber90e8fc22016-09-21 16:36:15 -0700479
480 out.unindent();
481 out << "}\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700482}
483
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700484status_t ArrayType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700485 out << "type: " << getVtsType() << "\n";
486 out << "vector_value: {\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700487 out.indent();
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700488 out << "vector_size: " << mSizes[0] << "\n";
Zhuoyao Zhangeb355ee2016-10-20 16:00:40 -0700489 // Simple array case.
490 if (mSizes.size() == 1) {
491 status_t err = mElementType->emitVtsTypeDeclarations(out);
492 if (err != OK) {
493 return err;
494 }
495 } else { // Multi-dimension array case.
496 for (size_t index = 1; index < mSizes.size(); index++) {
497 out << "type: " << getVtsType() << "\n";
498 out << "vector_value: {\n";
499 out.indent();
500 out << "vector_size: " << mSizes[index] << "\n";
501 if (index == mSizes.size() - 1) {
502 status_t err = mElementType->emitVtsTypeDeclarations(out);
503 if (err != OK) {
504 return err;
505 }
506 }
507 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700508 }
Zhuoyao Zhangeb355ee2016-10-20 16:00:40 -0700509 for (size_t index = 0; index < mSizes.size(); index++) {
510 out.unindent();
511 out << "}\n";
512 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700513 return OK;
514}
515
Andreas Huber70a59e12016-08-16 12:57:01 -0700516bool ArrayType::isJavaCompatible() const {
517 return mElementType->isJavaCompatible();
518}
519
Andreas Huber85eabdb2016-08-25 11:24:49 -0700520void ArrayType::getAlignmentAndSize(size_t *align, size_t *size) const {
521 mElementType->getAlignmentAndSize(align, size);
522
Andreas Huber709b62d2016-09-19 11:21:18 -0700523 for (auto sizeInDimension : mSizes) {
524 (*size) *= sizeInDimension;
525 }
Andreas Huber85eabdb2016-08-25 11:24:49 -0700526}
527
Yifan Hongbf459bc2016-08-23 16:50:37 -0700528size_t ArrayType::dimension() const {
529 size_t numArrayElements = 1;
530 for (auto size : mSizes) {
531 numArrayElements *= size;
532 }
533 return numArrayElements;
534}
535
Andreas Huberc9410c72016-07-28 12:18:40 -0700536} // namespace android
537