blob: b3f4269622163eec2541c180aba6609e242f19c5 [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
Andreas Huberf630bc82016-09-09 14:52:25 -070019#include "VectorType.h"
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070020#include <hidl-util/Formatter.h>
Andreas Huber5a545442016-08-03 10:44:56 -070021#include <android-base/logging.h>
22
Andreas Huberc9410c72016-07-28 12:18:40 -070023namespace android {
24
Andreas Huber9ed827c2016-08-22 12:31:13 -070025CompoundType::CompoundType(Style style, const char *localName)
26 : Scope(localName),
27 mStyle(style),
Andreas Huberc9410c72016-07-28 12:18:40 -070028 mFields(NULL) {
29}
30
Andreas Huber0d0f9a22016-08-17 10:26:11 -070031bool CompoundType::setFields(
32 std::vector<CompoundField *> *fields, std::string *errorMsg) {
Andreas Huberc9410c72016-07-28 12:18:40 -070033 mFields = fields;
Andreas Huber5a545442016-08-03 10:44:56 -070034
35 for (const auto &field : *fields) {
36 const Type &type = field->type();
37
Andreas Huber295ad302016-08-16 11:35:00 -070038 if (type.isBinder()) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -070039 *errorMsg =
40 "Structs/Unions must not contain references to interfaces.";
Andreas Huberb95ea8a2016-08-15 15:35:42 -070041
42 return false;
43 }
44
Andreas Huber5a545442016-08-03 10:44:56 -070045 if (mStyle == STYLE_UNION) {
46 if (type.needsEmbeddedReadWrite()) {
47 // Can't have those in a union.
48
Andreas Huber0d0f9a22016-08-17 10:26:11 -070049 *errorMsg =
50 "Unions must not contain any types that need fixup.";
Andreas Huber5a545442016-08-03 10:44:56 -070051
52 return false;
53 }
Andreas Huber5a545442016-08-03 10:44:56 -070054 }
55 }
56
57 return true;
Andreas Huberc9410c72016-07-28 12:18:40 -070058}
59
Andreas Huberf630bc82016-09-09 14:52:25 -070060bool CompoundType::isCompoundType() const {
61 return true;
62}
63
Andreas Huber881227d2016-08-02 14:20:21 -070064std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -070065 StorageMode mode,
66 std::string *extra,
67 bool specifyNamespaces) const {
68
Andreas Huber881227d2016-08-02 14:20:21 -070069 extra->clear();
Steven Moreland979e0992016-09-07 09:18:08 -070070 const std::string base =
71 specifyNamespaces ? fullName() : partialCppName();
Andreas Huber881227d2016-08-02 14:20:21 -070072
73 switch (mode) {
74 case StorageMode_Stack:
75 return base;
76
77 case StorageMode_Argument:
78 return "const " + base + "&";
79
80 case StorageMode_Result:
81 return "const " + base + "*";
82 }
83}
84
Andreas Huber85eabdb2016-08-25 11:24:49 -070085std::string CompoundType::getJavaType() const {
86 return fullJavaName();
87}
88
Andreas Huber881227d2016-08-02 14:20:21 -070089void CompoundType::emitReaderWriter(
90 Formatter &out,
91 const std::string &name,
92 const std::string &parcelObj,
93 bool parcelObjIsPointer,
94 bool isReader,
95 ErrorMode mode) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -070096 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -070097
98 out << "size_t " << parentName << ";\n\n";
99
100 const std::string parcelObjDeref =
101 parcelObj + (parcelObjIsPointer ? "->" : ".");
102
103 if (isReader) {
104 out << name
105 << " = (const "
Andreas Huber0e00de42016-08-03 09:56:02 -0700106 << fullName()
Andreas Huber881227d2016-08-02 14:20:21 -0700107 << " *)"
108 << parcelObjDeref
109 << "readBuffer("
110 << "&"
111 << parentName
112 << ");\n";
113
114 out << "if ("
115 << name
116 << " == nullptr) {\n";
117
118 out.indent();
119
Iliyan Malchev549e2592016-08-10 08:59:12 -0700120 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700121 handleError2(out, mode);
122
123 out.unindent();
124 out << "}\n\n";
125 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700126 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700127 << parcelObjDeref
128 << "writeBuffer(&"
129 << name
130 << ", sizeof("
131 << name
132 << "), &"
133 << parentName
134 << ");\n";
135
136 handleError(out, mode);
137 }
138
139 if (mStyle != STYLE_STRUCT || !needsEmbeddedReadWrite()) {
140 return;
141 }
142
143 emitReaderWriterEmbedded(
144 out,
145 name,
146 isReader /* nameIsPointer */,
147 parcelObj,
148 parcelObjIsPointer,
149 isReader,
150 mode,
151 parentName,
152 "0 /* parentOffset */");
153}
154
155void CompoundType::emitReaderWriterEmbedded(
156 Formatter &out,
157 const std::string &name,
158 bool nameIsPointer,
159 const std::string &parcelObj,
160 bool parcelObjIsPointer,
161 bool isReader,
162 ErrorMode mode,
163 const std::string &parentName,
164 const std::string &offsetText) const {
165 emitReaderWriterEmbeddedForTypeName(
166 out,
167 name,
168 nameIsPointer,
169 parcelObj,
170 parcelObjIsPointer,
171 isReader,
172 mode,
173 parentName,
174 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700175 fullName(),
Andreas Huber881227d2016-08-02 14:20:21 -0700176 "" /* childName */);
177}
178
Andreas Huber85eabdb2016-08-25 11:24:49 -0700179void CompoundType::emitJavaReaderWriter(
180 Formatter &out,
181 const std::string &parcelObj,
182 const std::string &argName,
183 bool isReader) const {
184 if (isReader) {
185 out << "new " << fullJavaName() << "();\n";
186 }
187
188 out << argName
189 << "."
190 << (isReader ? "readFromParcel" : "writeToParcel")
191 << "("
192 << parcelObj
193 << ");\n";
194}
195
196void CompoundType::emitJavaFieldInitializer(
197 Formatter &out, const std::string &fieldName) const {
198 out << "final "
199 << fullJavaName()
200 << " "
201 << fieldName
202 << " = new "
203 << fullJavaName()
204 << "();\n";
205}
206
207void CompoundType::emitJavaFieldReaderWriter(
208 Formatter &out,
209 const std::string &blobName,
210 const std::string &fieldName,
211 const std::string &offset,
212 bool isReader) const {
213 if (isReader) {
214 out << fieldName
215 << ".readEmbeddedFromParcel(parcel, "
216 << blobName
217 << ", "
218 << offset
219 << ");\n";
220
221 return;
222 }
223
224 out << fieldName
225 << ".writeEmbeddedToBlob("
226 << blobName
227 << ", "
228 << offset
229 << ");\n";
230}
231
Andreas Huber881227d2016-08-02 14:20:21 -0700232status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
233 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
234 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700235 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700236 << " {\n";
237
238 out.indent();
239
240 Scope::emitTypeDeclarations(out);
241
242 for (const auto &field : *mFields) {
243 std::string extra;
244 out << field->type().getCppType(&extra)
245 << " "
246 << field->name()
247 << extra
248 << ";\n";
249 }
250
251 if (needsEmbeddedReadWrite()) {
252 out << "\n::android::status_t readEmbeddedFromParcel(\n";
253
254 out.indent();
255 out.indent();
256
Andreas Huber8a82ff72016-08-04 10:29:39 -0700257 out << "const ::android::hardware::Parcel &parcel,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700258 << "size_t parentHandle,\n"
259 << "size_t parentOffset);\n\n";
260
261 out.unindent();
262 out.unindent();
263
264 out << "::android::status_t writeEmbeddedToParcel(\n";
265
266 out.indent();
267 out.indent();
268
Andreas Huber8a82ff72016-08-04 10:29:39 -0700269 out << "::android::hardware::Parcel *parcel,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700270 << "size_t parentHandle,\n"
271 << "size_t parentOffset) const;\n";
272
273 out.unindent();
274 out.unindent();
275 }
276
277 out.unindent();
278 out << "};\n\n";
279
280 return OK;
281}
282
283status_t CompoundType::emitTypeDefinitions(
284 Formatter &out, const std::string prefix) const {
Andreas Huber0e00de42016-08-03 09:56:02 -0700285 status_t err = Scope::emitTypeDefinitions(out, prefix + "::" + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700286
287 if (err != OK) {
288 return err;
289 }
290
291 if (!needsEmbeddedReadWrite()) {
292 return OK;
293 }
294
295 emitStructReaderWriter(out, prefix, true /* isReader */);
296 emitStructReaderWriter(out, prefix, false /* isReader */);
297
298 return OK;
299}
300
Andreas Huber85eabdb2016-08-25 11:24:49 -0700301status_t CompoundType::emitJavaTypeDeclarations(
302 Formatter &out, bool atTopLevel) const {
303 out << "public final ";
304
305 if (!atTopLevel) {
306 out << "static ";
307 }
308
309 out << "class "
310 << localName()
311 << " {\n";
312
313 out.indent();
314
315 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
316
317 for (const auto &field : *mFields) {
318 const bool isScope = field->type().isScope(); // really isStruct...
319
320 out << "public ";
321
322 field->type().emitJavaFieldInitializer(out, field->name());
323 }
324
325 if (!mFields->empty()) {
326 out << "\n";
327 }
328
329 out << "public final void readFromParcel(HwParcel parcel) {\n";
330 out.indent();
331 out << "HwBlob blob = parcel.readBuffer();\n";
332 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
333 out.unindent();
334 out << "}\n\n";
335
Andreas Huberf630bc82016-09-09 14:52:25 -0700336 ////////////////////////////////////////////////////////////////////////////
337
338 out << "public static final "
339 << localName()
340 << "[] readArrayFromParcel(HwParcel parcel, int size) {\n";
341 out.indent();
342
343 out << localName()
344 << "[] _hidl_array = new "
345 << localName()
346 << "[size];\n";
347
348 out << "HwBlob _hidl_blob = parcel.readBuffer();\n\n";
349
350 out << "for (int _hidl_index = 0; _hidl_index < size; ++_hidl_index) {\n";
351 out.indent();
352
353 out << "_hidl_array[_hidl_index] = new "
354 << localName()
355 << "();\n";
356
357 size_t structAlign, structSize;
358 getAlignmentAndSize(&structAlign, &structSize);
359
360 out << "_hidl_array[_hidl_index].readEmbeddedFromParcel(\n";
361 out.indent();
362 out.indent();
363 out << "parcel, _hidl_blob, _hidl_index * "
364 << structSize
365 << " /* parentOffset */);\n";
366
367 out.unindent();
368 out.unindent();
369 out.unindent();
370
371 out << "}\nreturn _hidl_array;\n";
372
373 out.unindent();
374 out << "}\n\n";
375
376 ////////////////////////////////////////////////////////////////////////////
377
378 out << "public static final "
379 << localName()
380 << "[] readVectorFromParcel(HwParcel parcel) {\n";
381 out.indent();
382
383 out << "Vector<"
384 << localName()
385 << "> _hidl_vec = new Vector();\n";
386
387 out << "HwBlob _hidl_blob = parcel.readBuffer();\n\n";
388
389 VectorType::EmitJavaFieldReaderWriterForElementType(
390 out, this, "_hidl_blob", "_hidl_vec", "0", true /* isReader */);
391
392 out << "\nreturn _hidl_vec.toArray(new "
393 << localName()
394 << "[_hidl_vec.size()]);\n";
395
396 out.unindent();
397 out << "}\n\n";
398
399 ////////////////////////////////////////////////////////////////////////////
400
Andreas Huber85eabdb2016-08-25 11:24:49 -0700401 out << "public final void readEmbeddedFromParcel(\n";
402 out.indent();
403 out.indent();
404 out << "HwParcel parcel, HwBlob _hidl_blob, long _hidl_offset) {\n";
405 out.unindent();
406
407 size_t offset = 0;
408 for (const auto &field : *mFields) {
409 size_t fieldAlign, fieldSize;
410 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
411
412 size_t pad = offset % fieldAlign;
413 if (pad > 0) {
414 offset += fieldAlign - pad;
415 }
416
417 field->type().emitJavaFieldReaderWriter(
418 out,
419 "_hidl_blob",
420 field->name(),
421 "_hidl_offset + " + std::to_string(offset),
422 true /* isReader */);
423
424 offset += fieldSize;
425 }
426
427 out.unindent();
428 out << "}\n\n";
429
Andreas Huberf630bc82016-09-09 14:52:25 -0700430 ////////////////////////////////////////////////////////////////////////////
431
Andreas Huber85eabdb2016-08-25 11:24:49 -0700432 out << "public final void writeToParcel(HwParcel parcel) {\n";
433 out.indent();
434
Andreas Huber85eabdb2016-08-25 11:24:49 -0700435 out << "HwBlob _hidl_blob = new HwBlob("
436 << structSize
437 << " /* size */);\n";
438
439 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
440 << "parcel.writeBuffer(_hidl_blob);\n";
441
442 out.unindent();
443 out << "}\n\n";
444
Andreas Huberf630bc82016-09-09 14:52:25 -0700445 ////////////////////////////////////////////////////////////////////////////
446
447 out << "public static final void writeArrayToParcel(\n";
448 out.indent();
449 out.indent();
450 out << "HwParcel parcel, int size, "
451 << localName()
452 << "[] _hidl_array) {\n";
453 out.unindent();
454
455 out << "HwBlob _hidl_blob = new HwBlob("
456 << "size * "
457 << structSize
458 << " /* size */);\n";
459
460 out << "for (int _hidl_index = 0; _hidl_index < size; ++_hidl_index) {\n";
461 out.indent();
462
463 out << "_hidl_array[_hidl_index].writeEmbeddedToBlob(\n";
464 out.indent();
465 out.indent();
466 out << "_hidl_blob, _hidl_index * "
467 << structSize
468 << " /* parentOffset */);\n";
469
470 out.unindent();
471 out.unindent();
472 out.unindent();
473
474 out << "}\nparcel.writeBuffer(_hidl_blob);\n";
475
476 out.unindent();
477 out << "}\n\n";
478
479 ////////////////////////////////////////////////////////////////////////////
480
481 out << "public static final void writeVectorToParcel(\n";
482 out.indent();
483 out.indent();
484 out << "HwParcel parcel, "
485 << localName()
486 << "[] _hidl_array) {\n";
487 out.unindent();
488
489 out << "Vector<"
490 << localName()
491 << "> _hidl_vec = new Vector(Arrays.asList(_hidl_array));\n";
492
493 out << "HwBlob _hidl_blob = new HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
494
495 VectorType::EmitJavaFieldReaderWriterForElementType(
496 out, this, "_hidl_blob", "_hidl_vec", "0", false /* isReader */);
497
498 out << "\nparcel.writeBuffer(_hidl_blob);\n";
499
500 out.unindent();
501 out << "}\n\n";
502
503 ////////////////////////////////////////////////////////////////////////////
504
Andreas Huber85eabdb2016-08-25 11:24:49 -0700505 out << "public final void writeEmbeddedToBlob(\n";
506 out.indent();
507 out.indent();
508 out << "HwBlob _hidl_blob, long _hidl_offset) {\n";
509 out.unindent();
510
511 offset = 0;
512 for (const auto &field : *mFields) {
513 size_t fieldAlign, fieldSize;
514 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
515
516 size_t pad = offset % fieldAlign;
517 if (pad > 0) {
518 offset += fieldAlign - pad;
519 }
520
521 field->type().emitJavaFieldReaderWriter(
522 out,
523 "_hidl_blob",
524 field->name(),
525 "_hidl_offset + " + std::to_string(offset),
526 false /* isReader */);
527
528 offset += fieldSize;
529 }
530
531 out.unindent();
532 out << "}\n";
533
534 out.unindent();
535 out << "};\n\n";
536
537 return OK;
538}
539
Andreas Huber881227d2016-08-02 14:20:21 -0700540void CompoundType::emitStructReaderWriter(
541 Formatter &out, const std::string &prefix, bool isReader) const {
542 out << "::android::status_t "
543 << (prefix.empty() ? "" : (prefix + "::"))
Andreas Huber0e00de42016-08-03 09:56:02 -0700544 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700545 << (isReader ? "::readEmbeddedFromParcel"
546 : "::writeEmbeddedToParcel")
547 << "(\n";
548
549 out.indent();
550 out.indent();
551
552 if (isReader) {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700553 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700554 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700555 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700556 }
557
558 out << "size_t parentHandle,\n"
559 << "size_t parentOffset)";
560
561 if (!isReader) {
562 out << " const";
563 }
564
565 out << " {\n";
566
567 out.unindent();
568 out.unindent();
569 out.indent();
570
Iliyan Malchev549e2592016-08-10 08:59:12 -0700571 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700572
573 for (const auto &field : *mFields) {
574 if (!field->type().needsEmbeddedReadWrite()) {
575 continue;
576 }
577
578 field->type().emitReaderWriterEmbedded(
579 out,
580 field->name(),
581 false /* nameIsPointer */,
582 "parcel",
583 !isReader /* parcelObjIsPointer */,
584 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700585 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700586 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700587 "parentOffset + offsetof("
588 + fullName()
589 + ", "
590 + field->name()
591 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700592 }
593
594 out.unindent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700595 out << "_hidl_error:\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700596 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700597 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700598
599 out.unindent();
600 out << "}\n\n";
601}
602
603bool CompoundType::needsEmbeddedReadWrite() const {
604 if (mStyle != STYLE_STRUCT) {
605 return false;
606 }
607
608 for (const auto &field : *mFields) {
609 if (field->type().needsEmbeddedReadWrite()) {
610 return true;
611 }
612 }
613
614 return false;
615}
616
617bool CompoundType::resultNeedsDeref() const {
618 return true;
619}
620
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700621status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
622 out << "name: \"" << localName() << "\"\n";
623 switch (mStyle) {
624 case STYLE_STRUCT:
625 {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700626 out << "type: TYPE_STRUCT\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700627 break;
628 }
629 case STYLE_UNION:
630 {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700631 out << "type: TYPE_UNION\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700632 break;
633 }
634 default:
635 break;
636 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700637
638 // Emit declaration for each subtype.
639 for (const auto &type : getSubTypes()) {
640 switch (mStyle) {
641 case STYLE_STRUCT:
642 {
643 out << "struct_value: {\n";
644 break;
645 }
646 case STYLE_UNION:
647 {
648 out << "union_value: {\n";
649 break;
650 }
651 default:
652 break;
653 }
654 out.indent();
655 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700656 if (status != OK) {
657 return status;
658 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700659 out.unindent();
660 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700661 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700662
663 // Emit declaration for each field.
664 for (const auto &field : *mFields) {
665 switch (mStyle) {
666 case STYLE_STRUCT:
667 {
668 out << "struct_value: {\n";
669 break;
670 }
671 case STYLE_UNION:
672 {
673 out << "union_value: {\n";
674 break;
675 }
676 default:
677 break;
678 }
679 out.indent();
680 out << "name: \"" << field->name() << "\"\n";
681 status_t status = field->type().emitVtsAttributeType(out);
682 if (status != OK) {
683 return status;
684 }
685 out.unindent();
686 out << "}\n";
687 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700688
689 return OK;
690}
691
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700692status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700693 switch (mStyle) {
694 case STYLE_STRUCT:
695 {
696 out << "type: TYPE_STRUCT\n";
697 break;
698 }
699 case STYLE_UNION:
700 {
701 out << "type: TYPE_UNION\n";
702 break;
703 }
704 default:
705 break;
706 }
707 out << "predefined_type: \"" << localName() << "\"\n";
708 return OK;
709}
710
Andreas Huber70a59e12016-08-16 12:57:01 -0700711bool CompoundType::isJavaCompatible() const {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700712 if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
713 return false;
714 }
715
716 for (const auto &field : *mFields) {
717 if (!field->type().isJavaCompatible()) {
718 return false;
719 }
720 }
721
722 return true;
Andreas Huber85eabdb2016-08-25 11:24:49 -0700723}
724
725void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
726 *align = 1;
727
728 size_t offset = 0;
729 for (const auto &field : *mFields) {
730 // Each field is aligned according to its alignment requirement.
731 // The surrounding structure's alignment is the maximum of its
732 // fields' aligments.
733
734 size_t fieldAlign, fieldSize;
735 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
736
737 size_t pad = offset % fieldAlign;
738 if (pad > 0) {
739 offset += fieldAlign - pad;
740 }
741
742 offset += fieldSize;
743
744 if (fieldAlign > (*align)) {
745 *align = fieldAlign;
746 }
747 }
748
749 // Final padding to account for the structure's alignment.
750 size_t pad = offset % (*align);
751 if (pad > 0) {
752 offset += (*align) - pad;
753 }
754
755 *size = offset;
Andreas Huber70a59e12016-08-16 12:57:01 -0700756}
757
Andreas Huber31629bc2016-08-03 09:06:40 -0700758////////////////////////////////////////////////////////////////////////////////
759
760CompoundField::CompoundField(const char *name, Type *type)
761 : mName(name),
762 mType(type) {
763}
764
765std::string CompoundField::name() const {
766 return mName;
767}
768
769const Type &CompoundField::type() const {
770 return *mType;
771}
772
Andreas Huberc9410c72016-07-28 12:18:40 -0700773} // namespace android
774