blob: 154bc67b871d36c35e60dda8f7f99a59186ac79a [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 "CompoundType.h"
18
Yifan Hongec102272016-12-20 18:10:07 -080019#include "ArrayType.h"
Andreas Huberf630bc82016-09-09 14:52:25 -070020#include "VectorType.h"
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070021#include <hidl-util/Formatter.h>
Andreas Huber5a545442016-08-03 10:44:56 -070022#include <android-base/logging.h>
23
Andreas Huberc9410c72016-07-28 12:18:40 -070024namespace android {
25
Yifan Honga4b53d02016-10-31 17:29:10 -070026CompoundType::CompoundType(Style style, const char *localName, const Location &location)
27 : Scope(localName, location),
Andreas Huber9ed827c2016-08-22 12:31:13 -070028 mStyle(style),
Andreas Huberc9410c72016-07-28 12:18:40 -070029 mFields(NULL) {
30}
31
Yifan Hong27e85db2016-11-09 15:45:52 -080032CompoundType::Style CompoundType::style() const {
33 return mStyle;
34}
35
Andreas Huber0d0f9a22016-08-17 10:26:11 -070036bool CompoundType::setFields(
37 std::vector<CompoundField *> *fields, std::string *errorMsg) {
Andreas Huberc9410c72016-07-28 12:18:40 -070038 mFields = fields;
Andreas Huber5a545442016-08-03 10:44:56 -070039
40 for (const auto &field : *fields) {
41 const Type &type = field->type();
42
Andreas Huber86a112b2016-10-19 14:25:16 -070043 if (type.isBinder()
44 || (type.isVector()
45 && static_cast<const VectorType *>(
46 &type)->isVectorOfBinders())) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -070047 *errorMsg =
48 "Structs/Unions must not contain references to interfaces.";
Andreas Huberb95ea8a2016-08-15 15:35:42 -070049
50 return false;
51 }
52
Andreas Huber5a545442016-08-03 10:44:56 -070053 if (mStyle == STYLE_UNION) {
54 if (type.needsEmbeddedReadWrite()) {
55 // Can't have those in a union.
56
Andreas Huber0d0f9a22016-08-17 10:26:11 -070057 *errorMsg =
58 "Unions must not contain any types that need fixup.";
Andreas Huber5a545442016-08-03 10:44:56 -070059
60 return false;
61 }
Andreas Huber5a545442016-08-03 10:44:56 -070062 }
63 }
64
65 return true;
Andreas Huberc9410c72016-07-28 12:18:40 -070066}
67
Andreas Huberf630bc82016-09-09 14:52:25 -070068bool CompoundType::isCompoundType() const {
69 return true;
70}
71
Yifan Hongc6752dc2016-12-20 14:00:14 -080072bool CompoundType::canCheckEquality() const {
73 if (mStyle == STYLE_UNION) {
74 return false;
75 }
76 for (const auto &field : *mFields) {
77 if (!field->type().canCheckEquality()) {
78 return false;
79 }
80 }
81 return true;
82}
83
Andreas Huber881227d2016-08-02 14:20:21 -070084std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -070085 StorageMode mode,
Steven Morelande30ee9b2017-05-09 13:31:01 -070086 bool /* specifyNamespaces */) const {
87 const std::string base = fullName();
Andreas Huber881227d2016-08-02 14:20:21 -070088
89 switch (mode) {
90 case StorageMode_Stack:
91 return base;
92
93 case StorageMode_Argument:
94 return "const " + base + "&";
95
96 case StorageMode_Result:
97 return "const " + base + "*";
98 }
99}
100
Yifan Hong4ed13472016-11-02 10:44:11 -0700101std::string CompoundType::getJavaType(bool /* forInitializer */) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700102 return fullJavaName();
103}
104
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700105std::string CompoundType::getVtsType() const {
106 switch (mStyle) {
107 case STYLE_STRUCT:
108 {
109 return "TYPE_STRUCT";
110 }
111 case STYLE_UNION:
112 {
113 return "TYPE_UNION";
114 }
115 }
116}
117
Andreas Huber881227d2016-08-02 14:20:21 -0700118void CompoundType::emitReaderWriter(
119 Formatter &out,
120 const std::string &name,
121 const std::string &parcelObj,
122 bool parcelObjIsPointer,
123 bool isReader,
124 ErrorMode mode) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700125 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700126
127 out << "size_t " << parentName << ";\n\n";
128
129 const std::string parcelObjDeref =
130 parcelObj + (parcelObjIsPointer ? "->" : ".");
131
132 if (isReader) {
Martijn Coenen6a082c62017-01-11 12:47:02 +0100133 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700134 << parcelObjDeref
135 << "readBuffer("
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700136 << "sizeof(*"
137 << name
138 << "), &"
Andreas Huber881227d2016-08-02 14:20:21 -0700139 << parentName
Martijn Coenen6a082c62017-01-11 12:47:02 +0100140 << ", "
141 << " reinterpret_cast<const void **>("
142 << "&" << name
143 << "));\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700144
Martijn Coenen6a082c62017-01-11 12:47:02 +0100145 handleError(out, mode);
Andreas Huber881227d2016-08-02 14:20:21 -0700146 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700147 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700148 << parcelObjDeref
149 << "writeBuffer(&"
150 << name
151 << ", sizeof("
152 << name
153 << "), &"
154 << parentName
155 << ");\n";
156
157 handleError(out, mode);
158 }
159
160 if (mStyle != STYLE_STRUCT || !needsEmbeddedReadWrite()) {
161 return;
162 }
163
164 emitReaderWriterEmbedded(
165 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700166 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700167 name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700168 name, /* sanitizedName */
Andreas Huber881227d2016-08-02 14:20:21 -0700169 isReader /* nameIsPointer */,
170 parcelObj,
171 parcelObjIsPointer,
172 isReader,
173 mode,
174 parentName,
175 "0 /* parentOffset */");
176}
177
178void CompoundType::emitReaderWriterEmbedded(
179 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700180 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700181 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700182 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700183 bool nameIsPointer,
184 const std::string &parcelObj,
185 bool parcelObjIsPointer,
186 bool isReader,
187 ErrorMode mode,
188 const std::string &parentName,
189 const std::string &offsetText) const {
190 emitReaderWriterEmbeddedForTypeName(
191 out,
192 name,
193 nameIsPointer,
194 parcelObj,
195 parcelObjIsPointer,
196 isReader,
197 mode,
198 parentName,
199 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700200 fullName(),
Yifan Hong244e82d2016-11-11 11:13:57 -0800201 "" /* childName */,
202 "" /* namespace */);
Andreas Huber881227d2016-08-02 14:20:21 -0700203}
204
Andreas Huber85eabdb2016-08-25 11:24:49 -0700205void CompoundType::emitJavaReaderWriter(
206 Formatter &out,
207 const std::string &parcelObj,
208 const std::string &argName,
209 bool isReader) const {
210 if (isReader) {
211 out << "new " << fullJavaName() << "();\n";
212 }
213
214 out << argName
215 << "."
216 << (isReader ? "readFromParcel" : "writeToParcel")
217 << "("
218 << parcelObj
219 << ");\n";
220}
221
222void CompoundType::emitJavaFieldInitializer(
223 Formatter &out, const std::string &fieldName) const {
224 out << "final "
225 << fullJavaName()
226 << " "
227 << fieldName
228 << " = new "
229 << fullJavaName()
230 << "();\n";
231}
232
233void CompoundType::emitJavaFieldReaderWriter(
234 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700235 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700236 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700237 const std::string &blobName,
238 const std::string &fieldName,
239 const std::string &offset,
240 bool isReader) const {
241 if (isReader) {
242 out << fieldName
Andreas Huber709b62d2016-09-19 11:21:18 -0700243 << ".readEmbeddedFromParcel("
244 << parcelName
245 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700246 << blobName
247 << ", "
248 << offset
249 << ");\n";
250
251 return;
252 }
253
254 out << fieldName
255 << ".writeEmbeddedToBlob("
256 << blobName
257 << ", "
258 << offset
259 << ");\n";
260}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700261void CompoundType::emitResolveReferences(
262 Formatter &out,
263 const std::string &name,
264 bool nameIsPointer,
265 const std::string &parcelObj,
266 bool parcelObjIsPointer,
267 bool isReader,
268 ErrorMode mode) const {
269 emitResolveReferencesEmbedded(
270 out,
271 0 /* depth */,
272 name,
273 name /* sanitizedName */,
274 nameIsPointer,
275 parcelObj,
276 parcelObjIsPointer,
277 isReader,
278 mode,
279 "_hidl_" + name + "_parent",
280 "0 /* parentOffset */");
281}
282
283void CompoundType::emitResolveReferencesEmbedded(
284 Formatter &out,
285 size_t /* depth */,
286 const std::string &name,
287 const std::string &/* sanitizedName */,
288 bool nameIsPointer,
289 const std::string &parcelObj,
290 bool parcelObjIsPointer,
291 bool isReader,
292 ErrorMode mode,
293 const std::string &parentName,
294 const std::string &offsetText) const {
295 CHECK(needsResolveReferences());
296
297 const std::string parcelObjDeref =
298 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
299
300 const std::string parcelObjPointer =
301 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
302
Yifan Hong244e82d2016-11-11 11:13:57 -0800303 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700304 const std::string namePointer = nameIsPointer ? name : ("&" + name);
305
306 out << "_hidl_err = ";
307
308 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800309 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700310 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800311 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700312 }
313
Yifan Hong33223ca2016-12-13 15:07:35 -0800314 out.indent(2, [&]{
Yifan Hong244e82d2016-11-11 11:13:57 -0800315 if (isReader) {
316 out << "const_cast<"
317 << fullName()
318 << " *"
319 << ">("
320 << namePointer
321 << "),\n"
322 << parcelObjDeref;
323 } else {
324 out << nameDerefed
325 << ",\n"
326 << parcelObjPointer;
327 }
328
329 out << ",\n"
Yifan Hong0a68a282016-10-21 16:32:34 -0700330 << parentName
331 << ",\n"
332 << offsetText
333 << ");\n\n";
334 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700335
336 handleError(out, mode);
337}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700338
Andreas Huber881227d2016-08-02 14:20:21 -0700339status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
340 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
341 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700342 << localName()
Yifan Hongb1d2ebc2016-12-20 17:18:07 -0800343 << " final {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700344
345 out.indent();
346
347 Scope::emitTypeDeclarations(out);
348
Andreas Huber60d3b222017-03-30 09:10:56 -0700349 if (containsPointer()) {
Andreas Huberca4bc892017-01-09 14:58:12 -0800350 for (const auto &field : *mFields) {
351 out << field->type().getCppStackType()
352 << " "
353 << field->name()
354 << ";\n";
355 }
356
357 out.unindent();
358 out << "};\n\n";
359
360 return OK;
Andreas Huber881227d2016-08-02 14:20:21 -0700361 }
362
Andreas Huberca4bc892017-01-09 14:58:12 -0800363 for (int pass = 0; pass < 2; ++pass) {
364 size_t offset = 0;
365 for (const auto &field : *mFields) {
366 size_t fieldAlign, fieldSize;
367 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
368
369 size_t pad = offset % fieldAlign;
370 if (pad > 0) {
371 offset += fieldAlign - pad;
372 }
373
374 if (pass == 0) {
375 out << field->type().getCppStackType()
376 << " "
377 << field->name()
378 << " __attribute__ ((aligned("
379 << fieldAlign
380 << ")));\n";
381 } else {
382 out << "static_assert(offsetof("
383 << fullName()
384 << ", "
385 << field->name()
386 << ") == "
387 << offset
388 << ", \"wrong offset\");\n";
389 }
390
Andreas Huber60d3b222017-03-30 09:10:56 -0700391 if (mStyle == STYLE_STRUCT) {
392 offset += fieldSize;
393 }
Andreas Huberca4bc892017-01-09 14:58:12 -0800394 }
395
396 if (pass == 0) {
397 out.unindent();
398 out << "};\n\n";
399 }
400 }
401
402 size_t structAlign, structSize;
403 getAlignmentAndSize(&structAlign, &structSize);
404
405 out << "static_assert(sizeof("
406 << fullName()
407 << ") == "
408 << structSize
409 << ", \"wrong size\");\n";
410
411 out << "static_assert(__alignof("
412 << fullName()
413 << ") == "
414 << structAlign
415 << ", \"wrong alignment\");\n\n";
Yifan Hong244e82d2016-11-11 11:13:57 -0800416
417 return OK;
418}
419
420
Yifan Hongc6752dc2016-12-20 14:00:14 -0800421status_t CompoundType::emitGlobalTypeDeclarations(Formatter &out) const {
422 Scope::emitGlobalTypeDeclarations(out);
423
Steven Moreland3d98bc42017-06-23 21:36:41 +0000424 out << "std::string toString("
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800425 << getCppArgumentType()
Steven Moreland3d98bc42017-06-23 21:36:41 +0000426 << ");\n\n";
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800427
Yifan Hong42c68432017-03-13 16:22:03 -0700428 if (canCheckEquality()) {
Steven Morelandf91048a2017-06-23 21:38:35 +0000429 out << "bool operator==("
430 << getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
Yifan Hong42c68432017-03-13 16:22:03 -0700431
Steven Morelandf91048a2017-06-23 21:38:35 +0000432 out << "bool operator!=("
433 << getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
Yifan Hong42c68432017-03-13 16:22:03 -0700434 } else {
Steven Morelandf91048a2017-06-23 21:38:35 +0000435 out << "// operator== and operator!= are not generated for " << localName() << "\n\n";
Yifan Hongc6752dc2016-12-20 14:00:14 -0800436 }
437
Yifan Hongc6752dc2016-12-20 14:00:14 -0800438 return OK;
439}
440
Yifan Hong244e82d2016-11-11 11:13:57 -0800441status_t CompoundType::emitGlobalHwDeclarations(Formatter &out) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700442 if (needsEmbeddedReadWrite()) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800443 out << "::android::status_t readEmbeddedFromParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700444
Yifan Hong0a68a282016-10-21 16:32:34 -0700445 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700446
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700447 out << "const " << fullName() << " &obj,\n"
Yifan Hong244e82d2016-11-11 11:13:57 -0800448 << "const ::android::hardware::Parcel &parcel,\n"
449 << "size_t parentHandle,\n"
450 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700451
Yifan Hong0a68a282016-10-21 16:32:34 -0700452 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700453
454 out << "::android::status_t writeEmbeddedToParcel(\n";
455
Yifan Hong0a68a282016-10-21 16:32:34 -0700456 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700457
Yifan Hong244e82d2016-11-11 11:13:57 -0800458 out << "const " << fullName() << " &obj,\n"
459 << "::android::hardware::Parcel *parcel,\n"
460 << "size_t parentHandle,\n"
461 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700462
Yifan Hong0a68a282016-10-21 16:32:34 -0700463 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700464 }
465
Yifan Hongbf459bc2016-08-23 16:50:37 -0700466 if(needsResolveReferences()) {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700467 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700468 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800469 out << fullName() << " *obj,\n"
470 << "const ::android::hardware::Parcel &parcel,\n"
471 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700472 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700473 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700474 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800475 out << "const " << fullName() << " &obj,\n"
476 << "::android::hardware::Parcel *,\n"
477 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700478 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700479 }
480
Andreas Huber881227d2016-08-02 14:20:21 -0700481 return OK;
482}
483
484status_t CompoundType::emitTypeDefinitions(
485 Formatter &out, const std::string prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -0700486 std::string space = prefix.empty() ? "" : (prefix + "::");
487 status_t err = Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700488
489 if (err != OK) {
490 return err;
491 }
492
Yifan Hongbf459bc2016-08-23 16:50:37 -0700493 if (needsEmbeddedReadWrite()) {
494 emitStructReaderWriter(out, prefix, true /* isReader */);
495 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -0700496 }
497
Yifan Hongbf459bc2016-08-23 16:50:37 -0700498 if (needsResolveReferences()) {
499 emitResolveReferenceDef(out, prefix, true /* isReader */);
500 emitResolveReferenceDef(out, prefix, false /* isReader */);
501 }
Andreas Huber881227d2016-08-02 14:20:21 -0700502
Steven Moreland3d98bc42017-06-23 21:36:41 +0000503 out << "std::string toString("
504 << getCppArgumentType()
505 << (mFields->empty() ? "" : " o")
506 << ") ";
507
508 out.block([&] {
509 // include toString for scalar types
510 out << "using ::android::hardware::toString;\n"
511 << "std::string os;\n";
512 out << "os += \"{\";\n";
513
514 for (const CompoundField *field : *mFields) {
515 out << "os += \"";
516 if (field != *(mFields->begin())) {
517 out << ", ";
518 }
519 out << "." << field->name() << " = \";\n";
520 field->type().emitDump(out, "os", "o." + field->name());
521 }
522
523 out << "os += \"}\"; return os;\n";
524 }).endl().endl();
525
Steven Morelandf91048a2017-06-23 21:38:35 +0000526 if (canCheckEquality()) {
527 out << "bool operator==("
528 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
529 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
530 out.block([&] {
531 for (const auto &field : *mFields) {
532 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
533 out << "return false;\n";
534 }).endl();
535 }
536 out << "return true;\n";
537 }).endl().endl();
538
539 out << "bool operator!=("
540 << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
541 out.block([&] {
542 out << "return !(lhs == rhs);\n";
543 }).endl().endl();
544 } else {
545 out << "// operator== and operator!= are not generated for " << localName() << "\n";
546 }
547
Andreas Huber881227d2016-08-02 14:20:21 -0700548 return OK;
549}
550
Andreas Huber85eabdb2016-08-25 11:24:49 -0700551status_t CompoundType::emitJavaTypeDeclarations(
552 Formatter &out, bool atTopLevel) const {
553 out << "public final ";
554
555 if (!atTopLevel) {
556 out << "static ";
557 }
558
559 out << "class "
560 << localName()
561 << " {\n";
562
563 out.indent();
564
565 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
566
567 for (const auto &field : *mFields) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700568 out << "public ";
569
570 field->type().emitJavaFieldInitializer(out, field->name());
571 }
572
573 if (!mFields->empty()) {
574 out << "\n";
575 }
576
Yifan Hongec102272016-12-20 18:10:07 -0800577 ////////////////////////////////////////////////////////////////////////////
578
579 if (canCheckEquality()) {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800580 out << "@Override\npublic final boolean equals(Object otherObject) ";
Yifan Hongec102272016-12-20 18:10:07 -0800581 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800582 out.sIf("this == otherObject", [&] {
583 out << "return true;\n";
584 }).endl();
585 out.sIf("otherObject == null", [&] {
586 out << "return false;\n";
587 }).endl();
Yifan Hong45b331b2017-03-27 12:59:54 -0700588 // Though class is final, we use getClass instead of instanceof to be explicit.
589 out.sIf("otherObject.getClass() != " + fullJavaName() + ".class", [&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800590 out << "return false;\n";
591 }).endl();
592 out << fullJavaName() << " other = (" << fullJavaName() << ")otherObject;\n";
Yifan Hongec102272016-12-20 18:10:07 -0800593 for (const auto &field : *mFields) {
Yifan Hong45b331b2017-03-27 12:59:54 -0700594 std::string condition = (field->type().isScalar() || field->type().isEnum())
Yifan Hongec102272016-12-20 18:10:07 -0800595 ? "this." + field->name() + " != other." + field->name()
Yifan Hong45b331b2017-03-27 12:59:54 -0700596 : ("!android.os.HidlSupport.deepEquals(this." + field->name()
Yifan Hongec102272016-12-20 18:10:07 -0800597 + ", other." + field->name() + ")");
598 out.sIf(condition, [&] {
599 out << "return false;\n";
600 }).endl();
601 }
602 out << "return true;\n";
603 }).endl().endl();
604
Yifan Hong7d1839f2017-02-22 13:24:29 -0800605 out << "@Override\npublic final int hashCode() ";
Yifan Hongec102272016-12-20 18:10:07 -0800606 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800607 out << "return java.util.Objects.hash(\n";
608 out.indent(2, [&] {
Yifan Hong932464e2017-03-30 15:40:22 -0700609 out.join(mFields->begin(), mFields->end(), ", \n", [&] (const auto &field) {
Yifan Hong45b331b2017-03-27 12:59:54 -0700610 out << "android.os.HidlSupport.deepHashCode(this." << field->name() << ")";
Yifan Hong932464e2017-03-30 15:40:22 -0700611 });
Yifan Hong7d1839f2017-02-22 13:24:29 -0800612 });
Yifan Hongec102272016-12-20 18:10:07 -0800613 out << ");\n";
614 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -0700615 } else {
616 out << "// equals() is not generated for " << localName() << "\n";
Yifan Hongec102272016-12-20 18:10:07 -0800617 }
618
619 ////////////////////////////////////////////////////////////////////////////
620
Yifan Honge45b5302017-02-22 10:49:07 -0800621 out << "@Override\npublic final String toString() ";
622 out.block([&] {
623 out << "java.lang.StringBuilder builder = new java.lang.StringBuilder();\n"
624 << "builder.append(\"{\");\n";
625 for (const auto &field : *mFields) {
626 out << "builder.append(\"";
627 if (field != *(mFields->begin())) {
628 out << ", ";
629 }
630 out << "." << field->name() << " = \");\n";
631 field->type().emitJavaDump(out, "builder", "this." + field->name());
632 }
633 out << "builder.append(\"}\");\nreturn builder.toString();\n";
634 }).endl().endl();
635
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700636 size_t structAlign, structSize;
637 getAlignmentAndSize(&structAlign, &structSize);
638
Yifan Honge45b5302017-02-22 10:49:07 -0800639 ////////////////////////////////////////////////////////////////////////////
640
Yifan Hong1af73532016-11-09 14:32:58 -0800641 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700642 out.indent();
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700643 out << "android.os.HwBlob blob = parcel.readBuffer(";
644 out << structSize << "/* size */);\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700645 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
646 out.unindent();
647 out << "}\n\n";
648
Andreas Huberf630bc82016-09-09 14:52:25 -0700649 ////////////////////////////////////////////////////////////////////////////
650
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700651 size_t vecAlign, vecSize;
652 VectorType::getAlignmentAndSizeStatic(&vecAlign, &vecSize);
653
Yifan Hong1af73532016-11-09 14:32:58 -0800654 out << "public static final java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700655 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800656 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700657 out.indent();
658
Yifan Hong1af73532016-11-09 14:32:58 -0800659 out << "java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700660 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800661 << "> _hidl_vec = new java.util.ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700662
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700663 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer(";
664 out << vecSize << " /* sizeof hidl_vec<T> */);\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700665
666 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700667 out,
668 0 /* depth */,
669 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700670 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700671 "_hidl_blob",
672 "_hidl_vec",
673 "0",
674 true /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700675
Andreas Huber1b6822b2016-10-18 09:28:40 -0700676 out << "\nreturn _hidl_vec;\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700677
678 out.unindent();
679 out << "}\n\n";
680
681 ////////////////////////////////////////////////////////////////////////////
682
Andreas Huber85eabdb2016-08-25 11:24:49 -0700683 out << "public final void readEmbeddedFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700684 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800685 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700686 out.unindent();
687
688 size_t offset = 0;
689 for (const auto &field : *mFields) {
690 size_t fieldAlign, fieldSize;
691 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
692
693 size_t pad = offset % fieldAlign;
694 if (pad > 0) {
695 offset += fieldAlign - pad;
696 }
697
698 field->type().emitJavaFieldReaderWriter(
699 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700700 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700701 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700702 "_hidl_blob",
703 field->name(),
704 "_hidl_offset + " + std::to_string(offset),
705 true /* isReader */);
706
707 offset += fieldSize;
708 }
709
710 out.unindent();
711 out << "}\n\n";
712
Andreas Huberf630bc82016-09-09 14:52:25 -0700713 ////////////////////////////////////////////////////////////////////////////
714
Yifan Hong1af73532016-11-09 14:32:58 -0800715 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700716 out.indent();
717
Yifan Hong1af73532016-11-09 14:32:58 -0800718 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
Andreas Huber85eabdb2016-08-25 11:24:49 -0700719 << structSize
720 << " /* size */);\n";
721
722 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
723 << "parcel.writeBuffer(_hidl_blob);\n";
724
725 out.unindent();
726 out << "}\n\n";
727
Andreas Huberf630bc82016-09-09 14:52:25 -0700728 ////////////////////////////////////////////////////////////////////////////
729
Andreas Huberf630bc82016-09-09 14:52:25 -0700730 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700731 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800732 out << "android.os.HwParcel parcel, java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700733 << localName()
Andreas Huber1b6822b2016-10-18 09:28:40 -0700734 << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700735 out.unindent();
736
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700737 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
738 << vecSize << " /* sizeof(hidl_vec<T>) */);\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700739
740 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700741 out,
742 0 /* depth */,
743 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700744 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700745 "_hidl_blob",
746 "_hidl_vec",
747 "0",
748 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700749
750 out << "\nparcel.writeBuffer(_hidl_blob);\n";
751
752 out.unindent();
753 out << "}\n\n";
754
755 ////////////////////////////////////////////////////////////////////////////
756
Andreas Huber85eabdb2016-08-25 11:24:49 -0700757 out << "public final void writeEmbeddedToBlob(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700758 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800759 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700760 out.unindent();
761
762 offset = 0;
763 for (const auto &field : *mFields) {
764 size_t fieldAlign, fieldSize;
765 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
766
767 size_t pad = offset % fieldAlign;
768 if (pad > 0) {
769 offset += fieldAlign - pad;
770 }
771
772 field->type().emitJavaFieldReaderWriter(
773 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700774 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700775 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700776 "_hidl_blob",
777 field->name(),
778 "_hidl_offset + " + std::to_string(offset),
779 false /* isReader */);
780
781 offset += fieldSize;
782 }
783
784 out.unindent();
785 out << "}\n";
786
787 out.unindent();
788 out << "};\n\n";
789
790 return OK;
791}
792
Andreas Huber881227d2016-08-02 14:20:21 -0700793void CompoundType::emitStructReaderWriter(
794 Formatter &out, const std::string &prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800795
796 std::string space = prefix.empty() ? "" : (prefix + "::");
797
Andreas Huber881227d2016-08-02 14:20:21 -0700798 out << "::android::status_t "
Yifan Hong244e82d2016-11-11 11:13:57 -0800799 << (isReader ? "readEmbeddedFromParcel"
800 : "writeEmbeddedToParcel")
801 << "(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700802
Yifan Hong0a68a282016-10-21 16:32:34 -0700803 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700804
Yifan Hong244e82d2016-11-11 11:13:57 -0800805 bool useName = false;
806 for (const auto &field : *mFields) {
807 if (field->type().useNameInEmitReaderWriterEmbedded(isReader)) {
808 useName = true;
809 break;
810 }
811 }
812 std::string name = useName ? "obj" : "/* obj */";
813 // if not useName, then obj should not be used at all,
814 // then the #error should not be emitted.
815 std::string error = useName ? "" : "\n#error\n";
816
Andreas Huber881227d2016-08-02 14:20:21 -0700817 if (isReader) {
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700818 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700819 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700820 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800821 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700822 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700823 }
824
825 out << "size_t parentHandle,\n"
826 << "size_t parentOffset)";
827
Andreas Huber881227d2016-08-02 14:20:21 -0700828 out << " {\n";
829
Yifan Hong0a68a282016-10-21 16:32:34 -0700830 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700831 out.indent();
832
Iliyan Malchev549e2592016-08-10 08:59:12 -0700833 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700834
835 for (const auto &field : *mFields) {
836 if (!field->type().needsEmbeddedReadWrite()) {
837 continue;
838 }
839
840 field->type().emitReaderWriterEmbedded(
841 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700842 0 /* depth */,
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700843 name + "." + field->name() + error,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700844 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700845 false /* nameIsPointer */,
846 "parcel",
847 !isReader /* parcelObjIsPointer */,
848 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700849 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700850 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700851 "parentOffset + offsetof("
852 + fullName()
853 + ", "
854 + field->name()
855 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700856 }
857
Iliyan Malchev549e2592016-08-10 08:59:12 -0700858 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700859
860 out.unindent();
861 out << "}\n\n";
862}
863
Yifan Hongbf459bc2016-08-23 16:50:37 -0700864void CompoundType::emitResolveReferenceDef(
865 Formatter &out, const std::string prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800866 out << "::android::status_t ";
867 const std::string space(prefix.empty() ? "" : (prefix + "::"));
Yifan Hong00f47172016-09-30 14:40:45 -0700868
869 bool useParent = false;
870 for (const auto &field : *mFields) {
871 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
872 useParent = true;
873 break;
874 }
875 }
876
877 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
878 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
879
Yifan Hongbf459bc2016-08-23 16:50:37 -0700880 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800881 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700882 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800883 out << space + localName() + " *obj,\n"
884 << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700885 << "size_t " << parentHandleName << ", "
886 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700887 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700888 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800889 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700890 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800891 out << "const " << space + localName() + " &obj,\n"
892 << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700893 << "size_t " << parentHandleName << ", "
Yifan Hong244e82d2016-11-11 11:13:57 -0800894 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700895 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700896 }
897
898 out << " {\n";
899
900 out.indent();
901
902 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
903
Yifan Hong244e82d2016-11-11 11:13:57 -0800904 const std::string nameDeref(isReader ? "obj->" : "obj.");
Yifan Hong00f47172016-09-30 14:40:45 -0700905 // if not useParent, then parentName and offsetText
906 // should not be used at all, then the #error should not be emitted.
907 std::string error = useParent ? "" : "\n#error\n";
908
Yifan Hongbf459bc2016-08-23 16:50:37 -0700909 for (const auto &field : *mFields) {
910 if (!field->type().needsResolveReferences()) {
911 continue;
912 }
913
914 field->type().emitResolveReferencesEmbedded(
915 out,
916 0 /* depth */,
Yifan Hong244e82d2016-11-11 11:13:57 -0800917 nameDeref + field->name(),
Yifan Hongbf459bc2016-08-23 16:50:37 -0700918 field->name() /* sanitizedName */,
919 false, // nameIsPointer
920 "parcel", // const std::string &parcelObj,
921 !isReader, // bool parcelObjIsPointer,
922 isReader, // bool isReader,
923 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -0700924 parentHandleName + error,
925 parentOffsetName
926 + " + offsetof("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700927 + fullName()
928 + ", "
929 + field->name()
Yifan Hong00f47172016-09-30 14:40:45 -0700930 + ")"
931 + error);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700932 }
933
Yifan Hongbf459bc2016-08-23 16:50:37 -0700934 out << "return _hidl_err;\n";
935
936 out.unindent();
937 out << "}\n\n";
938}
939
Andreas Huber881227d2016-08-02 14:20:21 -0700940bool CompoundType::needsEmbeddedReadWrite() const {
941 if (mStyle != STYLE_STRUCT) {
942 return false;
943 }
944
945 for (const auto &field : *mFields) {
946 if (field->type().needsEmbeddedReadWrite()) {
947 return true;
948 }
949 }
950
951 return false;
952}
953
Yifan Hongbf459bc2016-08-23 16:50:37 -0700954bool CompoundType::needsResolveReferences() const {
955 if (mStyle != STYLE_STRUCT) {
956 return false;
957 }
958
959 for (const auto &field : *mFields) {
960 if (field->type().needsResolveReferences()) {
961 return true;
962 }
963 }
964
965 return false;
966}
967
Andreas Huber881227d2016-08-02 14:20:21 -0700968bool CompoundType::resultNeedsDeref() const {
969 return true;
970}
971
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700972status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700973 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700974 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700975
976 // Emit declaration for each subtype.
977 for (const auto &type : getSubTypes()) {
978 switch (mStyle) {
979 case STYLE_STRUCT:
980 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700981 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700982 break;
983 }
984 case STYLE_UNION:
985 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700986 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700987 break;
988 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700989 }
990 out.indent();
991 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700992 if (status != OK) {
993 return status;
994 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700995 out.unindent();
996 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700997 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700998
999 // Emit declaration for each field.
1000 for (const auto &field : *mFields) {
1001 switch (mStyle) {
1002 case STYLE_STRUCT:
1003 {
1004 out << "struct_value: {\n";
1005 break;
1006 }
1007 case STYLE_UNION:
1008 {
1009 out << "union_value: {\n";
1010 break;
1011 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001012 }
1013 out.indent();
1014 out << "name: \"" << field->name() << "\"\n";
1015 status_t status = field->type().emitVtsAttributeType(out);
1016 if (status != OK) {
1017 return status;
1018 }
1019 out.unindent();
1020 out << "}\n";
1021 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001022
1023 return OK;
1024}
1025
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001026status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001027 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07001028 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001029 return OK;
1030}
1031
Andreas Huber70a59e12016-08-16 12:57:01 -07001032bool CompoundType::isJavaCompatible() const {
Andreas Huber0fa9e392016-08-31 09:05:44 -07001033 if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
1034 return false;
1035 }
1036
1037 for (const auto &field : *mFields) {
1038 if (!field->type().isJavaCompatible()) {
1039 return false;
1040 }
1041 }
1042
1043 return true;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001044}
1045
Andreas Huber60d3b222017-03-30 09:10:56 -07001046bool CompoundType::containsPointer() const {
1047 if (Scope::containsPointer()) {
1048 return true;
1049 }
1050
1051 for (const auto &field : *mFields) {
1052 if (field->type().containsPointer()) {
1053 return true;
1054 }
1055 }
1056
1057 return false;
1058}
1059
Andreas Huber85eabdb2016-08-25 11:24:49 -07001060void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
1061 *align = 1;
Andreas Huber60d3b222017-03-30 09:10:56 -07001062 *size = 0;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001063
1064 size_t offset = 0;
1065 for (const auto &field : *mFields) {
1066 // Each field is aligned according to its alignment requirement.
1067 // The surrounding structure's alignment is the maximum of its
1068 // fields' aligments.
1069
1070 size_t fieldAlign, fieldSize;
1071 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1072
1073 size_t pad = offset % fieldAlign;
1074 if (pad > 0) {
1075 offset += fieldAlign - pad;
1076 }
1077
Andreas Huber60d3b222017-03-30 09:10:56 -07001078 if (mStyle == STYLE_STRUCT) {
1079 offset += fieldSize;
1080 } else {
1081 *size = std::max(*size, fieldSize);
1082 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001083
1084 if (fieldAlign > (*align)) {
1085 *align = fieldAlign;
1086 }
1087 }
1088
Andreas Huber60d3b222017-03-30 09:10:56 -07001089 if (mStyle == STYLE_STRUCT) {
1090 *size = offset;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001091 }
1092
Andreas Huber60d3b222017-03-30 09:10:56 -07001093 // Final padding to account for the structure's alignment.
1094 size_t pad = (*size) % (*align);
1095 if (pad > 0) {
1096 (*size) += (*align) - pad;
1097 }
Andreas Huberca4bc892017-01-09 14:58:12 -08001098
1099 if (*size == 0) {
1100 // An empty struct still occupies a byte of space in C++.
1101 *size = 1;
1102 }
Andreas Huber70a59e12016-08-16 12:57:01 -07001103}
1104
Andreas Huber31629bc2016-08-03 09:06:40 -07001105////////////////////////////////////////////////////////////////////////////////
1106
1107CompoundField::CompoundField(const char *name, Type *type)
1108 : mName(name),
1109 mType(type) {
1110}
1111
1112std::string CompoundField::name() const {
1113 return mName;
1114}
1115
1116const Type &CompoundField::type() const {
1117 return *mType;
1118}
1119
Andreas Huberc9410c72016-07-28 12:18:40 -07001120} // namespace android
1121