blob: 1bd9aefe15e204dd94f25a1dfb6ced8afa751904 [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 Moreland979e0992016-09-07 09:18:08 -070086 bool specifyNamespaces) const {
Steven Moreland979e0992016-09-07 09:18:08 -070087 const std::string base =
88 specifyNamespaces ? fullName() : partialCppName();
Andreas Huber881227d2016-08-02 14:20:21 -070089
90 switch (mode) {
91 case StorageMode_Stack:
92 return base;
93
94 case StorageMode_Argument:
95 return "const " + base + "&";
96
97 case StorageMode_Result:
98 return "const " + base + "*";
99 }
100}
101
Yifan Hong4ed13472016-11-02 10:44:11 -0700102std::string CompoundType::getJavaType(bool /* forInitializer */) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700103 return fullJavaName();
104}
105
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700106std::string CompoundType::getVtsType() const {
107 switch (mStyle) {
108 case STYLE_STRUCT:
109 {
110 return "TYPE_STRUCT";
111 }
112 case STYLE_UNION:
113 {
114 return "TYPE_UNION";
115 }
116 }
117}
118
Andreas Huber881227d2016-08-02 14:20:21 -0700119void CompoundType::emitReaderWriter(
120 Formatter &out,
121 const std::string &name,
122 const std::string &parcelObj,
123 bool parcelObjIsPointer,
124 bool isReader,
125 ErrorMode mode) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700126 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700127
128 out << "size_t " << parentName << ";\n\n";
129
130 const std::string parcelObjDeref =
131 parcelObj + (parcelObjIsPointer ? "->" : ".");
132
133 if (isReader) {
Martijn Coenen6a082c62017-01-11 12:47:02 +0100134 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700135 << parcelObjDeref
136 << "readBuffer("
137 << "&"
138 << parentName
Martijn Coenen6a082c62017-01-11 12:47:02 +0100139 << ", "
140 << " reinterpret_cast<const void **>("
141 << "&" << name
142 << "));\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700143
Martijn Coenen6a082c62017-01-11 12:47:02 +0100144 handleError(out, mode);
Andreas Huber881227d2016-08-02 14:20:21 -0700145 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700146 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700147 << parcelObjDeref
148 << "writeBuffer(&"
149 << name
150 << ", sizeof("
151 << name
152 << "), &"
153 << parentName
154 << ");\n";
155
156 handleError(out, mode);
157 }
158
159 if (mStyle != STYLE_STRUCT || !needsEmbeddedReadWrite()) {
160 return;
161 }
162
163 emitReaderWriterEmbedded(
164 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700165 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700166 name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700167 name, /* sanitizedName */
Andreas Huber881227d2016-08-02 14:20:21 -0700168 isReader /* nameIsPointer */,
169 parcelObj,
170 parcelObjIsPointer,
171 isReader,
172 mode,
173 parentName,
174 "0 /* parentOffset */");
175}
176
177void CompoundType::emitReaderWriterEmbedded(
178 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700179 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700180 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700181 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700182 bool nameIsPointer,
183 const std::string &parcelObj,
184 bool parcelObjIsPointer,
185 bool isReader,
186 ErrorMode mode,
187 const std::string &parentName,
188 const std::string &offsetText) const {
189 emitReaderWriterEmbeddedForTypeName(
190 out,
191 name,
192 nameIsPointer,
193 parcelObj,
194 parcelObjIsPointer,
195 isReader,
196 mode,
197 parentName,
198 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700199 fullName(),
Yifan Hong244e82d2016-11-11 11:13:57 -0800200 "" /* childName */,
201 "" /* namespace */);
Andreas Huber881227d2016-08-02 14:20:21 -0700202}
203
Andreas Huber85eabdb2016-08-25 11:24:49 -0700204void CompoundType::emitJavaReaderWriter(
205 Formatter &out,
206 const std::string &parcelObj,
207 const std::string &argName,
208 bool isReader) const {
209 if (isReader) {
210 out << "new " << fullJavaName() << "();\n";
211 }
212
213 out << argName
214 << "."
215 << (isReader ? "readFromParcel" : "writeToParcel")
216 << "("
217 << parcelObj
218 << ");\n";
219}
220
221void CompoundType::emitJavaFieldInitializer(
222 Formatter &out, const std::string &fieldName) const {
223 out << "final "
224 << fullJavaName()
225 << " "
226 << fieldName
227 << " = new "
228 << fullJavaName()
229 << "();\n";
230}
231
232void CompoundType::emitJavaFieldReaderWriter(
233 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700234 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700235 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700236 const std::string &blobName,
237 const std::string &fieldName,
238 const std::string &offset,
239 bool isReader) const {
240 if (isReader) {
241 out << fieldName
Andreas Huber709b62d2016-09-19 11:21:18 -0700242 << ".readEmbeddedFromParcel("
243 << parcelName
244 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700245 << blobName
246 << ", "
247 << offset
248 << ");\n";
249
250 return;
251 }
252
253 out << fieldName
254 << ".writeEmbeddedToBlob("
255 << blobName
256 << ", "
257 << offset
258 << ");\n";
259}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700260void CompoundType::emitResolveReferences(
261 Formatter &out,
262 const std::string &name,
263 bool nameIsPointer,
264 const std::string &parcelObj,
265 bool parcelObjIsPointer,
266 bool isReader,
267 ErrorMode mode) const {
268 emitResolveReferencesEmbedded(
269 out,
270 0 /* depth */,
271 name,
272 name /* sanitizedName */,
273 nameIsPointer,
274 parcelObj,
275 parcelObjIsPointer,
276 isReader,
277 mode,
278 "_hidl_" + name + "_parent",
279 "0 /* parentOffset */");
280}
281
282void CompoundType::emitResolveReferencesEmbedded(
283 Formatter &out,
284 size_t /* depth */,
285 const std::string &name,
286 const std::string &/* sanitizedName */,
287 bool nameIsPointer,
288 const std::string &parcelObj,
289 bool parcelObjIsPointer,
290 bool isReader,
291 ErrorMode mode,
292 const std::string &parentName,
293 const std::string &offsetText) const {
294 CHECK(needsResolveReferences());
295
296 const std::string parcelObjDeref =
297 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
298
299 const std::string parcelObjPointer =
300 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
301
Yifan Hong244e82d2016-11-11 11:13:57 -0800302 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700303 const std::string namePointer = nameIsPointer ? name : ("&" + name);
304
305 out << "_hidl_err = ";
306
307 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800308 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700309 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800310 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700311 }
312
Yifan Hong33223ca2016-12-13 15:07:35 -0800313 out.indent(2, [&]{
Yifan Hong244e82d2016-11-11 11:13:57 -0800314 if (isReader) {
315 out << "const_cast<"
316 << fullName()
317 << " *"
318 << ">("
319 << namePointer
320 << "),\n"
321 << parcelObjDeref;
322 } else {
323 out << nameDerefed
324 << ",\n"
325 << parcelObjPointer;
326 }
327
328 out << ",\n"
Yifan Hong0a68a282016-10-21 16:32:34 -0700329 << parentName
330 << ",\n"
331 << offsetText
332 << ");\n\n";
333 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700334
335 handleError(out, mode);
336}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700337
Andreas Huber881227d2016-08-02 14:20:21 -0700338status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
339 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
340 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700341 << localName()
Yifan Hongb1d2ebc2016-12-20 17:18:07 -0800342 << " final {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700343
344 out.indent();
345
346 Scope::emitTypeDeclarations(out);
347
Andreas Huber2639fa32017-03-30 09:10:56 -0700348 if (containsPointer()) {
Andreas Huberca4bc892017-01-09 14:58:12 -0800349 for (const auto &field : *mFields) {
350 out << field->type().getCppStackType()
351 << " "
352 << field->name()
353 << ";\n";
354 }
355
356 out.unindent();
357 out << "};\n\n";
358
359 return OK;
Andreas Huber881227d2016-08-02 14:20:21 -0700360 }
361
Andreas Huberca4bc892017-01-09 14:58:12 -0800362 for (int pass = 0; pass < 2; ++pass) {
363 size_t offset = 0;
364 for (const auto &field : *mFields) {
365 size_t fieldAlign, fieldSize;
366 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
367
368 size_t pad = offset % fieldAlign;
369 if (pad > 0) {
370 offset += fieldAlign - pad;
371 }
372
373 if (pass == 0) {
374 out << field->type().getCppStackType()
375 << " "
376 << field->name()
377 << " __attribute__ ((aligned("
378 << fieldAlign
379 << ")));\n";
380 } else {
381 out << "static_assert(offsetof("
382 << fullName()
383 << ", "
384 << field->name()
385 << ") == "
386 << offset
387 << ", \"wrong offset\");\n";
388 }
389
Andreas Huber2639fa32017-03-30 09:10:56 -0700390 if (mStyle == STYLE_STRUCT) {
391 offset += fieldSize;
392 }
Andreas Huberca4bc892017-01-09 14:58:12 -0800393 }
394
395 if (pass == 0) {
396 out.unindent();
397 out << "};\n\n";
398 }
399 }
400
401 size_t structAlign, structSize;
402 getAlignmentAndSize(&structAlign, &structSize);
403
404 out << "static_assert(sizeof("
405 << fullName()
406 << ") == "
407 << structSize
408 << ", \"wrong size\");\n";
409
410 out << "static_assert(__alignof("
411 << fullName()
412 << ") == "
413 << structAlign
414 << ", \"wrong alignment\");\n\n";
Yifan Hong244e82d2016-11-11 11:13:57 -0800415
416 return OK;
417}
418
419
Yifan Hongc6752dc2016-12-20 14:00:14 -0800420status_t CompoundType::emitGlobalTypeDeclarations(Formatter &out) const {
421 Scope::emitGlobalTypeDeclarations(out);
422
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800423 out << "std::string toString("
424 << getCppArgumentType()
Yifan Hong42c68432017-03-13 16:22:03 -0700425 << ");\n\n";
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800426
Yifan Hong42c68432017-03-13 16:22:03 -0700427 if (canCheckEquality()) {
428 out << "bool operator==("
429 << getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
430
431 out << "bool operator!=("
432 << getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
433 } else {
434 out << "// operator== and operator!= are not generated for " << localName() << "\n\n";
Yifan Hongc6752dc2016-12-20 14:00:14 -0800435 }
436
Yifan Hongc6752dc2016-12-20 14:00:14 -0800437 return OK;
438}
439
Yifan Hong244e82d2016-11-11 11:13:57 -0800440status_t CompoundType::emitGlobalHwDeclarations(Formatter &out) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700441 if (needsEmbeddedReadWrite()) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800442 out << "::android::status_t readEmbeddedFromParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700443
Yifan Hong0a68a282016-10-21 16:32:34 -0700444 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700445
Yifan Hong244e82d2016-11-11 11:13:57 -0800446 out << fullName() << " *obj,\n"
447 << "const ::android::hardware::Parcel &parcel,\n"
448 << "size_t parentHandle,\n"
449 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700450
Yifan Hong0a68a282016-10-21 16:32:34 -0700451 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700452
453 out << "::android::status_t writeEmbeddedToParcel(\n";
454
Yifan Hong0a68a282016-10-21 16:32:34 -0700455 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700456
Yifan Hong244e82d2016-11-11 11:13:57 -0800457 out << "const " << fullName() << " &obj,\n"
458 << "::android::hardware::Parcel *parcel,\n"
459 << "size_t parentHandle,\n"
460 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700461
Yifan Hong0a68a282016-10-21 16:32:34 -0700462 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700463 }
464
Yifan Hongbf459bc2016-08-23 16:50:37 -0700465 if(needsResolveReferences()) {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700466 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700467 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800468 out << fullName() << " *obj,\n"
469 << "const ::android::hardware::Parcel &parcel,\n"
470 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700471 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700472 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700473 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800474 out << "const " << fullName() << " &obj,\n"
475 << "::android::hardware::Parcel *,\n"
476 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700477 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700478 }
479
Andreas Huber881227d2016-08-02 14:20:21 -0700480 return OK;
481}
482
483status_t CompoundType::emitTypeDefinitions(
484 Formatter &out, const std::string prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -0700485 std::string space = prefix.empty() ? "" : (prefix + "::");
486 status_t err = Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700487
488 if (err != OK) {
489 return err;
490 }
491
Yifan Hongbf459bc2016-08-23 16:50:37 -0700492 if (needsEmbeddedReadWrite()) {
493 emitStructReaderWriter(out, prefix, true /* isReader */);
494 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -0700495 }
496
Yifan Hongbf459bc2016-08-23 16:50:37 -0700497 if (needsResolveReferences()) {
498 emitResolveReferenceDef(out, prefix, true /* isReader */);
499 emitResolveReferenceDef(out, prefix, false /* isReader */);
500 }
Andreas Huber881227d2016-08-02 14:20:21 -0700501
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800502 out << "std::string toString("
503 << getCppArgumentType()
504 << (mFields->empty() ? "" : " o")
505 << ") ";
506
507 out.block([&] {
508 // include toString for scalar types
Hridya Valsaraju9ab1e9e2017-03-10 07:52:23 -0800509 out << "using ::android::hardware::toString;\n"
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800510 << "std::string os;\n";
511 out << "os += \"{\";\n";
512
513 for (const CompoundField *field : *mFields) {
514 out << "os += \"";
515 if (field != *(mFields->begin())) {
516 out << ", ";
517 }
518 out << "." << field->name() << " = \";\n";
519 field->type().emitDump(out, "os", "o." + field->name());
520 }
521
522 out << "os += \"}\"; return os;\n";
523 }).endl().endl();
524
Yifan Hong42c68432017-03-13 16:22:03 -0700525 if (canCheckEquality()) {
526 out << "bool operator==("
527 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
528 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
529 out.block([&] {
530 for (const auto &field : *mFields) {
531 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
532 out << "return false;\n";
533 }).endl();
534 }
535 out << "return true;\n";
536 }).endl().endl();
537
538 out << "bool operator!=("
539 << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
540 out.block([&] {
541 out << "return !(lhs == rhs);\n";
542 }).endl().endl();
543 } else {
544 out << "// operator== and operator!= are not generated for " << localName() << "\n";
545 }
546
Andreas Huber881227d2016-08-02 14:20:21 -0700547 return OK;
548}
549
Andreas Huber85eabdb2016-08-25 11:24:49 -0700550status_t CompoundType::emitJavaTypeDeclarations(
551 Formatter &out, bool atTopLevel) const {
552 out << "public final ";
553
554 if (!atTopLevel) {
555 out << "static ";
556 }
557
558 out << "class "
559 << localName()
560 << " {\n";
561
562 out.indent();
563
564 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
565
566 for (const auto &field : *mFields) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700567 out << "public ";
568
569 field->type().emitJavaFieldInitializer(out, field->name());
570 }
571
572 if (!mFields->empty()) {
573 out << "\n";
574 }
575
Yifan Hongec102272016-12-20 18:10:07 -0800576 ////////////////////////////////////////////////////////////////////////////
577
578 if (canCheckEquality()) {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800579 out << "@Override\npublic final boolean equals(Object otherObject) ";
Yifan Hongec102272016-12-20 18:10:07 -0800580 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800581 out.sIf("this == otherObject", [&] {
582 out << "return true;\n";
583 }).endl();
584 out.sIf("otherObject == null", [&] {
585 out << "return false;\n";
586 }).endl();
Yifan Hong2593f182017-03-27 12:59:54 -0700587 // Though class is final, we use getClass instead of instanceof to be explicit.
588 out.sIf("otherObject.getClass() != " + fullJavaName() + ".class", [&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800589 out << "return false;\n";
590 }).endl();
591 out << fullJavaName() << " other = (" << fullJavaName() << ")otherObject;\n";
Yifan Hongec102272016-12-20 18:10:07 -0800592 for (const auto &field : *mFields) {
Yifan Hong2593f182017-03-27 12:59:54 -0700593 std::string condition = (field->type().isScalar() || field->type().isEnum())
Yifan Hongec102272016-12-20 18:10:07 -0800594 ? "this." + field->name() + " != other." + field->name()
Yifan Hong2593f182017-03-27 12:59:54 -0700595 : ("!android.os.HidlSupport.deepEquals(this." + field->name()
Yifan Hongec102272016-12-20 18:10:07 -0800596 + ", other." + field->name() + ")");
597 out.sIf(condition, [&] {
598 out << "return false;\n";
599 }).endl();
600 }
601 out << "return true;\n";
602 }).endl().endl();
603
Yifan Hong7d1839f2017-02-22 13:24:29 -0800604 out << "@Override\npublic final int hashCode() ";
Yifan Hongec102272016-12-20 18:10:07 -0800605 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800606 out << "return java.util.Objects.hash(\n";
607 out.indent(2, [&] {
Yifan Hong7d234ea2017-03-30 15:40:22 -0700608 out.join(mFields->begin(), mFields->end(), ", \n", [&] (const auto &field) {
Yifan Hong2593f182017-03-27 12:59:54 -0700609 out << "android.os.HidlSupport.deepHashCode(this." << field->name() << ")";
Yifan Hong7d234ea2017-03-30 15:40:22 -0700610 });
Yifan Hong7d1839f2017-02-22 13:24:29 -0800611 });
Yifan Hongec102272016-12-20 18:10:07 -0800612 out << ");\n";
613 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -0700614 } else {
615 out << "// equals() is not generated for " << localName() << "\n";
Yifan Hongec102272016-12-20 18:10:07 -0800616 }
617
618 ////////////////////////////////////////////////////////////////////////////
619
Yifan Honge45b5302017-02-22 10:49:07 -0800620 out << "@Override\npublic final String toString() ";
621 out.block([&] {
622 out << "java.lang.StringBuilder builder = new java.lang.StringBuilder();\n"
623 << "builder.append(\"{\");\n";
624 for (const auto &field : *mFields) {
625 out << "builder.append(\"";
626 if (field != *(mFields->begin())) {
627 out << ", ";
628 }
629 out << "." << field->name() << " = \");\n";
630 field->type().emitJavaDump(out, "builder", "this." + field->name());
631 }
632 out << "builder.append(\"}\");\nreturn builder.toString();\n";
633 }).endl().endl();
634
635 ////////////////////////////////////////////////////////////////////////////
636
Yifan Hong1af73532016-11-09 14:32:58 -0800637 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700638 out.indent();
Yifan Hong1af73532016-11-09 14:32:58 -0800639 out << "android.os.HwBlob blob = parcel.readBuffer();\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700640 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
641 out.unindent();
642 out << "}\n\n";
643
Andreas Huberf630bc82016-09-09 14:52:25 -0700644 ////////////////////////////////////////////////////////////////////////////
645
Yifan Hong1af73532016-11-09 14:32:58 -0800646 out << "public static final java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700647 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800648 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700649 out.indent();
650
Yifan Hong1af73532016-11-09 14:32:58 -0800651 out << "java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700652 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800653 << "> _hidl_vec = new java.util.ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700654
Yifan Hong1af73532016-11-09 14:32:58 -0800655 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer();\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700656
657 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700658 out,
659 0 /* depth */,
660 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700661 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700662 "_hidl_blob",
663 "_hidl_vec",
664 "0",
665 true /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700666
Andreas Huber1b6822b2016-10-18 09:28:40 -0700667 out << "\nreturn _hidl_vec;\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700668
669 out.unindent();
670 out << "}\n\n";
671
672 ////////////////////////////////////////////////////////////////////////////
673
Andreas Huber85eabdb2016-08-25 11:24:49 -0700674 out << "public final void readEmbeddedFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700675 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800676 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700677 out.unindent();
678
679 size_t offset = 0;
680 for (const auto &field : *mFields) {
681 size_t fieldAlign, fieldSize;
682 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
683
684 size_t pad = offset % fieldAlign;
685 if (pad > 0) {
686 offset += fieldAlign - pad;
687 }
688
689 field->type().emitJavaFieldReaderWriter(
690 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700691 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700692 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700693 "_hidl_blob",
694 field->name(),
695 "_hidl_offset + " + std::to_string(offset),
696 true /* isReader */);
697
698 offset += fieldSize;
699 }
700
701 out.unindent();
702 out << "}\n\n";
703
Andreas Huberf630bc82016-09-09 14:52:25 -0700704 ////////////////////////////////////////////////////////////////////////////
705
Andreas Huber709b62d2016-09-19 11:21:18 -0700706 size_t structAlign, structSize;
707 getAlignmentAndSize(&structAlign, &structSize);
708
Yifan Hong1af73532016-11-09 14:32:58 -0800709 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700710 out.indent();
711
Yifan Hong1af73532016-11-09 14:32:58 -0800712 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
Andreas Huber85eabdb2016-08-25 11:24:49 -0700713 << structSize
714 << " /* size */);\n";
715
716 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
717 << "parcel.writeBuffer(_hidl_blob);\n";
718
719 out.unindent();
720 out << "}\n\n";
721
Andreas Huberf630bc82016-09-09 14:52:25 -0700722 ////////////////////////////////////////////////////////////////////////////
723
Andreas Huberf630bc82016-09-09 14:52:25 -0700724 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700725 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800726 out << "android.os.HwParcel parcel, java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700727 << localName()
Andreas Huber1b6822b2016-10-18 09:28:40 -0700728 << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700729 out.unindent();
730
Yifan Hong1af73532016-11-09 14:32:58 -0800731 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700732
733 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700734 out,
735 0 /* depth */,
736 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700737 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700738 "_hidl_blob",
739 "_hidl_vec",
740 "0",
741 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700742
743 out << "\nparcel.writeBuffer(_hidl_blob);\n";
744
745 out.unindent();
746 out << "}\n\n";
747
748 ////////////////////////////////////////////////////////////////////////////
749
Andreas Huber85eabdb2016-08-25 11:24:49 -0700750 out << "public final void writeEmbeddedToBlob(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700751 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800752 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700753 out.unindent();
754
755 offset = 0;
756 for (const auto &field : *mFields) {
757 size_t fieldAlign, fieldSize;
758 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
759
760 size_t pad = offset % fieldAlign;
761 if (pad > 0) {
762 offset += fieldAlign - pad;
763 }
764
765 field->type().emitJavaFieldReaderWriter(
766 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700767 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700768 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700769 "_hidl_blob",
770 field->name(),
771 "_hidl_offset + " + std::to_string(offset),
772 false /* isReader */);
773
774 offset += fieldSize;
775 }
776
777 out.unindent();
778 out << "}\n";
779
780 out.unindent();
781 out << "};\n\n";
782
783 return OK;
784}
785
Andreas Huber881227d2016-08-02 14:20:21 -0700786void CompoundType::emitStructReaderWriter(
787 Formatter &out, const std::string &prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800788
789 std::string space = prefix.empty() ? "" : (prefix + "::");
790
Andreas Huber881227d2016-08-02 14:20:21 -0700791 out << "::android::status_t "
Yifan Hong244e82d2016-11-11 11:13:57 -0800792 << (isReader ? "readEmbeddedFromParcel"
793 : "writeEmbeddedToParcel")
794 << "(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700795
Yifan Hong0a68a282016-10-21 16:32:34 -0700796 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700797
Yifan Hong244e82d2016-11-11 11:13:57 -0800798 bool useName = false;
799 for (const auto &field : *mFields) {
800 if (field->type().useNameInEmitReaderWriterEmbedded(isReader)) {
801 useName = true;
802 break;
803 }
804 }
805 std::string name = useName ? "obj" : "/* obj */";
806 // if not useName, then obj should not be used at all,
807 // then the #error should not be emitted.
808 std::string error = useName ? "" : "\n#error\n";
809
Andreas Huber881227d2016-08-02 14:20:21 -0700810 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800811 out << space << localName() << " *" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700812 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700813 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800814 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700815 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700816 }
817
818 out << "size_t parentHandle,\n"
819 << "size_t parentOffset)";
820
Andreas Huber881227d2016-08-02 14:20:21 -0700821 out << " {\n";
822
Yifan Hong0a68a282016-10-21 16:32:34 -0700823 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700824 out.indent();
825
Iliyan Malchev549e2592016-08-10 08:59:12 -0700826 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700827
828 for (const auto &field : *mFields) {
829 if (!field->type().needsEmbeddedReadWrite()) {
830 continue;
831 }
832
833 field->type().emitReaderWriterEmbedded(
834 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700835 0 /* depth */,
Yifan Hong244e82d2016-11-11 11:13:57 -0800836 name + (isReader ? "->" : ".") + field->name() + error,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700837 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700838 false /* nameIsPointer */,
839 "parcel",
840 !isReader /* parcelObjIsPointer */,
841 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700842 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700843 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700844 "parentOffset + offsetof("
845 + fullName()
846 + ", "
847 + field->name()
848 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700849 }
850
Iliyan Malchev549e2592016-08-10 08:59:12 -0700851 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700852
853 out.unindent();
854 out << "}\n\n";
855}
856
Yifan Hongbf459bc2016-08-23 16:50:37 -0700857void CompoundType::emitResolveReferenceDef(
858 Formatter &out, const std::string prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800859 out << "::android::status_t ";
860 const std::string space(prefix.empty() ? "" : (prefix + "::"));
Yifan Hong00f47172016-09-30 14:40:45 -0700861
862 bool useParent = false;
863 for (const auto &field : *mFields) {
864 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
865 useParent = true;
866 break;
867 }
868 }
869
870 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
871 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
872
Yifan Hongbf459bc2016-08-23 16:50:37 -0700873 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800874 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700875 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800876 out << space + localName() + " *obj,\n"
877 << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700878 << "size_t " << parentHandleName << ", "
879 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700880 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700881 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800882 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700883 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800884 out << "const " << space + localName() + " &obj,\n"
885 << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700886 << "size_t " << parentHandleName << ", "
Yifan Hong244e82d2016-11-11 11:13:57 -0800887 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700888 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700889 }
890
891 out << " {\n";
892
893 out.indent();
894
895 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
896
Yifan Hong244e82d2016-11-11 11:13:57 -0800897 const std::string nameDeref(isReader ? "obj->" : "obj.");
Yifan Hong00f47172016-09-30 14:40:45 -0700898 // if not useParent, then parentName and offsetText
899 // should not be used at all, then the #error should not be emitted.
900 std::string error = useParent ? "" : "\n#error\n";
901
Yifan Hongbf459bc2016-08-23 16:50:37 -0700902 for (const auto &field : *mFields) {
903 if (!field->type().needsResolveReferences()) {
904 continue;
905 }
906
907 field->type().emitResolveReferencesEmbedded(
908 out,
909 0 /* depth */,
Yifan Hong244e82d2016-11-11 11:13:57 -0800910 nameDeref + field->name(),
Yifan Hongbf459bc2016-08-23 16:50:37 -0700911 field->name() /* sanitizedName */,
912 false, // nameIsPointer
913 "parcel", // const std::string &parcelObj,
914 !isReader, // bool parcelObjIsPointer,
915 isReader, // bool isReader,
916 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -0700917 parentHandleName + error,
918 parentOffsetName
919 + " + offsetof("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700920 + fullName()
921 + ", "
922 + field->name()
Yifan Hong00f47172016-09-30 14:40:45 -0700923 + ")"
924 + error);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700925 }
926
Yifan Hongbf459bc2016-08-23 16:50:37 -0700927 out << "return _hidl_err;\n";
928
929 out.unindent();
930 out << "}\n\n";
931}
932
Andreas Huber881227d2016-08-02 14:20:21 -0700933bool CompoundType::needsEmbeddedReadWrite() const {
934 if (mStyle != STYLE_STRUCT) {
935 return false;
936 }
937
938 for (const auto &field : *mFields) {
939 if (field->type().needsEmbeddedReadWrite()) {
940 return true;
941 }
942 }
943
944 return false;
945}
946
Yifan Hongbf459bc2016-08-23 16:50:37 -0700947bool CompoundType::needsResolveReferences() const {
948 if (mStyle != STYLE_STRUCT) {
949 return false;
950 }
951
952 for (const auto &field : *mFields) {
953 if (field->type().needsResolveReferences()) {
954 return true;
955 }
956 }
957
958 return false;
959}
960
Andreas Huber881227d2016-08-02 14:20:21 -0700961bool CompoundType::resultNeedsDeref() const {
962 return true;
963}
964
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700965status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700966 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700967 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700968
969 // Emit declaration for each subtype.
970 for (const auto &type : getSubTypes()) {
971 switch (mStyle) {
972 case STYLE_STRUCT:
973 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700974 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700975 break;
976 }
977 case STYLE_UNION:
978 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700979 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700980 break;
981 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700982 }
983 out.indent();
984 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700985 if (status != OK) {
986 return status;
987 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700988 out.unindent();
989 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700990 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700991
992 // Emit declaration for each field.
993 for (const auto &field : *mFields) {
994 switch (mStyle) {
995 case STYLE_STRUCT:
996 {
997 out << "struct_value: {\n";
998 break;
999 }
1000 case STYLE_UNION:
1001 {
1002 out << "union_value: {\n";
1003 break;
1004 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001005 }
1006 out.indent();
1007 out << "name: \"" << field->name() << "\"\n";
1008 status_t status = field->type().emitVtsAttributeType(out);
1009 if (status != OK) {
1010 return status;
1011 }
1012 out.unindent();
1013 out << "}\n";
1014 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001015
1016 return OK;
1017}
1018
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001019status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001020 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07001021 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001022 return OK;
1023}
1024
Andreas Huber70a59e12016-08-16 12:57:01 -07001025bool CompoundType::isJavaCompatible() const {
Andreas Huber0fa9e392016-08-31 09:05:44 -07001026 if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
1027 return false;
1028 }
1029
1030 for (const auto &field : *mFields) {
1031 if (!field->type().isJavaCompatible()) {
1032 return false;
1033 }
1034 }
1035
1036 return true;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001037}
1038
Andreas Huber2639fa32017-03-30 09:10:56 -07001039bool CompoundType::containsPointer() const {
1040 if (Scope::containsPointer()) {
1041 return true;
1042 }
1043
1044 for (const auto &field : *mFields) {
1045 if (field->type().containsPointer()) {
1046 return true;
1047 }
1048 }
1049
1050 return false;
1051}
1052
Andreas Huber85eabdb2016-08-25 11:24:49 -07001053void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
1054 *align = 1;
Andreas Huber2639fa32017-03-30 09:10:56 -07001055 *size = 0;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001056
1057 size_t offset = 0;
1058 for (const auto &field : *mFields) {
1059 // Each field is aligned according to its alignment requirement.
1060 // The surrounding structure's alignment is the maximum of its
1061 // fields' aligments.
1062
1063 size_t fieldAlign, fieldSize;
1064 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1065
1066 size_t pad = offset % fieldAlign;
1067 if (pad > 0) {
1068 offset += fieldAlign - pad;
1069 }
1070
Andreas Huber2639fa32017-03-30 09:10:56 -07001071 if (mStyle == STYLE_STRUCT) {
1072 offset += fieldSize;
1073 } else {
1074 *size = std::max(*size, fieldSize);
1075 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001076
1077 if (fieldAlign > (*align)) {
1078 *align = fieldAlign;
1079 }
1080 }
1081
Andreas Huber2639fa32017-03-30 09:10:56 -07001082 if (mStyle == STYLE_STRUCT) {
1083 *size = offset;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001084 }
1085
Andreas Huber2639fa32017-03-30 09:10:56 -07001086 // Final padding to account for the structure's alignment.
1087 size_t pad = (*size) % (*align);
1088 if (pad > 0) {
1089 (*size) += (*align) - pad;
1090 }
Andreas Huberca4bc892017-01-09 14:58:12 -08001091
1092 if (*size == 0) {
1093 // An empty struct still occupies a byte of space in C++.
1094 *size = 1;
1095 }
Andreas Huber70a59e12016-08-16 12:57:01 -07001096}
1097
Andreas Huber31629bc2016-08-03 09:06:40 -07001098////////////////////////////////////////////////////////////////////////////////
1099
1100CompoundField::CompoundField(const char *name, Type *type)
1101 : mName(name),
1102 mType(type) {
1103}
1104
1105std::string CompoundField::name() const {
1106 return mName;
1107}
1108
1109const Type &CompoundField::type() const {
1110 return *mType;
1111}
1112
Andreas Huberc9410c72016-07-28 12:18:40 -07001113} // namespace android
1114