blob: 8a692c1cc0b51ac1db5c60309d2ebc5ad0761107 [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,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700145 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700146 name,
147 isReader /* nameIsPointer */,
148 parcelObj,
149 parcelObjIsPointer,
150 isReader,
151 mode,
152 parentName,
153 "0 /* parentOffset */");
154}
155
156void CompoundType::emitReaderWriterEmbedded(
157 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700158 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700159 const std::string &name,
160 bool nameIsPointer,
161 const std::string &parcelObj,
162 bool parcelObjIsPointer,
163 bool isReader,
164 ErrorMode mode,
165 const std::string &parentName,
166 const std::string &offsetText) const {
167 emitReaderWriterEmbeddedForTypeName(
168 out,
169 name,
170 nameIsPointer,
171 parcelObj,
172 parcelObjIsPointer,
173 isReader,
174 mode,
175 parentName,
176 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700177 fullName(),
Andreas Huber881227d2016-08-02 14:20:21 -0700178 "" /* childName */);
179}
180
Andreas Huber85eabdb2016-08-25 11:24:49 -0700181void CompoundType::emitJavaReaderWriter(
182 Formatter &out,
183 const std::string &parcelObj,
184 const std::string &argName,
185 bool isReader) const {
186 if (isReader) {
187 out << "new " << fullJavaName() << "();\n";
188 }
189
190 out << argName
191 << "."
192 << (isReader ? "readFromParcel" : "writeToParcel")
193 << "("
194 << parcelObj
195 << ");\n";
196}
197
198void CompoundType::emitJavaFieldInitializer(
199 Formatter &out, const std::string &fieldName) const {
200 out << "final "
201 << fullJavaName()
202 << " "
203 << fieldName
204 << " = new "
205 << fullJavaName()
206 << "();\n";
207}
208
209void CompoundType::emitJavaFieldReaderWriter(
210 Formatter &out,
211 const std::string &blobName,
212 const std::string &fieldName,
213 const std::string &offset,
214 bool isReader) const {
215 if (isReader) {
216 out << fieldName
217 << ".readEmbeddedFromParcel(parcel, "
218 << blobName
219 << ", "
220 << offset
221 << ");\n";
222
223 return;
224 }
225
226 out << fieldName
227 << ".writeEmbeddedToBlob("
228 << blobName
229 << ", "
230 << offset
231 << ");\n";
232}
233
Andreas Huber881227d2016-08-02 14:20:21 -0700234status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
235 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
236 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700237 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700238 << " {\n";
239
240 out.indent();
241
242 Scope::emitTypeDeclarations(out);
243
244 for (const auto &field : *mFields) {
245 std::string extra;
246 out << field->type().getCppType(&extra)
247 << " "
248 << field->name()
249 << extra
250 << ";\n";
251 }
252
253 if (needsEmbeddedReadWrite()) {
254 out << "\n::android::status_t readEmbeddedFromParcel(\n";
255
256 out.indent();
257 out.indent();
258
Andreas Huber8a82ff72016-08-04 10:29:39 -0700259 out << "const ::android::hardware::Parcel &parcel,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700260 << "size_t parentHandle,\n"
261 << "size_t parentOffset);\n\n";
262
263 out.unindent();
264 out.unindent();
265
266 out << "::android::status_t writeEmbeddedToParcel(\n";
267
268 out.indent();
269 out.indent();
270
Andreas Huber8a82ff72016-08-04 10:29:39 -0700271 out << "::android::hardware::Parcel *parcel,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700272 << "size_t parentHandle,\n"
273 << "size_t parentOffset) const;\n";
274
275 out.unindent();
276 out.unindent();
277 }
278
279 out.unindent();
280 out << "};\n\n";
281
282 return OK;
283}
284
285status_t CompoundType::emitTypeDefinitions(
286 Formatter &out, const std::string prefix) const {
Andreas Huber0e00de42016-08-03 09:56:02 -0700287 status_t err = Scope::emitTypeDefinitions(out, prefix + "::" + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700288
289 if (err != OK) {
290 return err;
291 }
292
293 if (!needsEmbeddedReadWrite()) {
294 return OK;
295 }
296
297 emitStructReaderWriter(out, prefix, true /* isReader */);
298 emitStructReaderWriter(out, prefix, false /* isReader */);
299
300 return OK;
301}
302
Andreas Huber85eabdb2016-08-25 11:24:49 -0700303status_t CompoundType::emitJavaTypeDeclarations(
304 Formatter &out, bool atTopLevel) const {
305 out << "public final ";
306
307 if (!atTopLevel) {
308 out << "static ";
309 }
310
311 out << "class "
312 << localName()
313 << " {\n";
314
315 out.indent();
316
317 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
318
319 for (const auto &field : *mFields) {
320 const bool isScope = field->type().isScope(); // really isStruct...
321
322 out << "public ";
323
324 field->type().emitJavaFieldInitializer(out, field->name());
325 }
326
327 if (!mFields->empty()) {
328 out << "\n";
329 }
330
331 out << "public final void readFromParcel(HwParcel parcel) {\n";
332 out.indent();
333 out << "HwBlob blob = parcel.readBuffer();\n";
334 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
335 out.unindent();
336 out << "}\n\n";
337
Andreas Huberf630bc82016-09-09 14:52:25 -0700338 ////////////////////////////////////////////////////////////////////////////
339
340 out << "public static final "
341 << localName()
342 << "[] readArrayFromParcel(HwParcel parcel, int size) {\n";
343 out.indent();
344
345 out << localName()
346 << "[] _hidl_array = new "
347 << localName()
348 << "[size];\n";
349
350 out << "HwBlob _hidl_blob = parcel.readBuffer();\n\n";
351
352 out << "for (int _hidl_index = 0; _hidl_index < size; ++_hidl_index) {\n";
353 out.indent();
354
355 out << "_hidl_array[_hidl_index] = new "
356 << localName()
357 << "();\n";
358
359 size_t structAlign, structSize;
360 getAlignmentAndSize(&structAlign, &structSize);
361
362 out << "_hidl_array[_hidl_index].readEmbeddedFromParcel(\n";
363 out.indent();
364 out.indent();
365 out << "parcel, _hidl_blob, _hidl_index * "
366 << structSize
367 << " /* parentOffset */);\n";
368
369 out.unindent();
370 out.unindent();
371 out.unindent();
372
373 out << "}\nreturn _hidl_array;\n";
374
375 out.unindent();
376 out << "}\n\n";
377
378 ////////////////////////////////////////////////////////////////////////////
379
380 out << "public static final "
381 << localName()
382 << "[] readVectorFromParcel(HwParcel parcel) {\n";
383 out.indent();
384
385 out << "Vector<"
386 << localName()
387 << "> _hidl_vec = new Vector();\n";
388
389 out << "HwBlob _hidl_blob = parcel.readBuffer();\n\n";
390
391 VectorType::EmitJavaFieldReaderWriterForElementType(
392 out, this, "_hidl_blob", "_hidl_vec", "0", true /* isReader */);
393
394 out << "\nreturn _hidl_vec.toArray(new "
395 << localName()
396 << "[_hidl_vec.size()]);\n";
397
398 out.unindent();
399 out << "}\n\n";
400
401 ////////////////////////////////////////////////////////////////////////////
402
Andreas Huber85eabdb2016-08-25 11:24:49 -0700403 out << "public final void readEmbeddedFromParcel(\n";
404 out.indent();
405 out.indent();
406 out << "HwParcel parcel, HwBlob _hidl_blob, long _hidl_offset) {\n";
407 out.unindent();
408
409 size_t offset = 0;
410 for (const auto &field : *mFields) {
411 size_t fieldAlign, fieldSize;
412 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
413
414 size_t pad = offset % fieldAlign;
415 if (pad > 0) {
416 offset += fieldAlign - pad;
417 }
418
419 field->type().emitJavaFieldReaderWriter(
420 out,
421 "_hidl_blob",
422 field->name(),
423 "_hidl_offset + " + std::to_string(offset),
424 true /* isReader */);
425
426 offset += fieldSize;
427 }
428
429 out.unindent();
430 out << "}\n\n";
431
Andreas Huberf630bc82016-09-09 14:52:25 -0700432 ////////////////////////////////////////////////////////////////////////////
433
Andreas Huber85eabdb2016-08-25 11:24:49 -0700434 out << "public final void writeToParcel(HwParcel parcel) {\n";
435 out.indent();
436
Andreas Huber85eabdb2016-08-25 11:24:49 -0700437 out << "HwBlob _hidl_blob = new HwBlob("
438 << structSize
439 << " /* size */);\n";
440
441 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
442 << "parcel.writeBuffer(_hidl_blob);\n";
443
444 out.unindent();
445 out << "}\n\n";
446
Andreas Huberf630bc82016-09-09 14:52:25 -0700447 ////////////////////////////////////////////////////////////////////////////
448
449 out << "public static final void writeArrayToParcel(\n";
450 out.indent();
451 out.indent();
452 out << "HwParcel parcel, int size, "
453 << localName()
454 << "[] _hidl_array) {\n";
455 out.unindent();
456
457 out << "HwBlob _hidl_blob = new HwBlob("
458 << "size * "
459 << structSize
460 << " /* size */);\n";
461
462 out << "for (int _hidl_index = 0; _hidl_index < size; ++_hidl_index) {\n";
463 out.indent();
464
465 out << "_hidl_array[_hidl_index].writeEmbeddedToBlob(\n";
466 out.indent();
467 out.indent();
468 out << "_hidl_blob, _hidl_index * "
469 << structSize
470 << " /* parentOffset */);\n";
471
472 out.unindent();
473 out.unindent();
474 out.unindent();
475
476 out << "}\nparcel.writeBuffer(_hidl_blob);\n";
477
478 out.unindent();
479 out << "}\n\n";
480
481 ////////////////////////////////////////////////////////////////////////////
482
483 out << "public static final void writeVectorToParcel(\n";
484 out.indent();
485 out.indent();
486 out << "HwParcel parcel, "
487 << localName()
488 << "[] _hidl_array) {\n";
489 out.unindent();
490
491 out << "Vector<"
492 << localName()
493 << "> _hidl_vec = new Vector(Arrays.asList(_hidl_array));\n";
494
495 out << "HwBlob _hidl_blob = new HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
496
497 VectorType::EmitJavaFieldReaderWriterForElementType(
498 out, this, "_hidl_blob", "_hidl_vec", "0", false /* isReader */);
499
500 out << "\nparcel.writeBuffer(_hidl_blob);\n";
501
502 out.unindent();
503 out << "}\n\n";
504
505 ////////////////////////////////////////////////////////////////////////////
506
Andreas Huber85eabdb2016-08-25 11:24:49 -0700507 out << "public final void writeEmbeddedToBlob(\n";
508 out.indent();
509 out.indent();
510 out << "HwBlob _hidl_blob, long _hidl_offset) {\n";
511 out.unindent();
512
513 offset = 0;
514 for (const auto &field : *mFields) {
515 size_t fieldAlign, fieldSize;
516 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
517
518 size_t pad = offset % fieldAlign;
519 if (pad > 0) {
520 offset += fieldAlign - pad;
521 }
522
523 field->type().emitJavaFieldReaderWriter(
524 out,
525 "_hidl_blob",
526 field->name(),
527 "_hidl_offset + " + std::to_string(offset),
528 false /* isReader */);
529
530 offset += fieldSize;
531 }
532
533 out.unindent();
534 out << "}\n";
535
536 out.unindent();
537 out << "};\n\n";
538
539 return OK;
540}
541
Andreas Huber881227d2016-08-02 14:20:21 -0700542void CompoundType::emitStructReaderWriter(
543 Formatter &out, const std::string &prefix, bool isReader) const {
544 out << "::android::status_t "
545 << (prefix.empty() ? "" : (prefix + "::"))
Andreas Huber0e00de42016-08-03 09:56:02 -0700546 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700547 << (isReader ? "::readEmbeddedFromParcel"
548 : "::writeEmbeddedToParcel")
549 << "(\n";
550
551 out.indent();
552 out.indent();
553
554 if (isReader) {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700555 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700556 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700557 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700558 }
559
560 out << "size_t parentHandle,\n"
561 << "size_t parentOffset)";
562
563 if (!isReader) {
564 out << " const";
565 }
566
567 out << " {\n";
568
569 out.unindent();
570 out.unindent();
571 out.indent();
572
Iliyan Malchev549e2592016-08-10 08:59:12 -0700573 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700574
575 for (const auto &field : *mFields) {
576 if (!field->type().needsEmbeddedReadWrite()) {
577 continue;
578 }
579
580 field->type().emitReaderWriterEmbedded(
581 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700582 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700583 field->name(),
584 false /* nameIsPointer */,
585 "parcel",
586 !isReader /* parcelObjIsPointer */,
587 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700588 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700589 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700590 "parentOffset + offsetof("
591 + fullName()
592 + ", "
593 + field->name()
594 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700595 }
596
597 out.unindent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700598 out << "_hidl_error:\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700599 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700600 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700601
602 out.unindent();
603 out << "}\n\n";
604}
605
606bool CompoundType::needsEmbeddedReadWrite() const {
607 if (mStyle != STYLE_STRUCT) {
608 return false;
609 }
610
611 for (const auto &field : *mFields) {
612 if (field->type().needsEmbeddedReadWrite()) {
613 return true;
614 }
615 }
616
617 return false;
618}
619
620bool CompoundType::resultNeedsDeref() const {
621 return true;
622}
623
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700624status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
625 out << "name: \"" << localName() << "\"\n";
626 switch (mStyle) {
627 case STYLE_STRUCT:
628 {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700629 out << "type: TYPE_STRUCT\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700630 break;
631 }
632 case STYLE_UNION:
633 {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700634 out << "type: TYPE_UNION\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700635 break;
636 }
637 default:
638 break;
639 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700640
641 // Emit declaration for each subtype.
642 for (const auto &type : getSubTypes()) {
643 switch (mStyle) {
644 case STYLE_STRUCT:
645 {
646 out << "struct_value: {\n";
647 break;
648 }
649 case STYLE_UNION:
650 {
651 out << "union_value: {\n";
652 break;
653 }
654 default:
655 break;
656 }
657 out.indent();
658 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700659 if (status != OK) {
660 return status;
661 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700662 out.unindent();
663 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700664 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700665
666 // Emit declaration for each field.
667 for (const auto &field : *mFields) {
668 switch (mStyle) {
669 case STYLE_STRUCT:
670 {
671 out << "struct_value: {\n";
672 break;
673 }
674 case STYLE_UNION:
675 {
676 out << "union_value: {\n";
677 break;
678 }
679 default:
680 break;
681 }
682 out.indent();
683 out << "name: \"" << field->name() << "\"\n";
684 status_t status = field->type().emitVtsAttributeType(out);
685 if (status != OK) {
686 return status;
687 }
688 out.unindent();
689 out << "}\n";
690 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700691
692 return OK;
693}
694
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700695status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700696 switch (mStyle) {
697 case STYLE_STRUCT:
698 {
699 out << "type: TYPE_STRUCT\n";
700 break;
701 }
702 case STYLE_UNION:
703 {
704 out << "type: TYPE_UNION\n";
705 break;
706 }
707 default:
708 break;
709 }
710 out << "predefined_type: \"" << localName() << "\"\n";
711 return OK;
712}
713
Andreas Huber70a59e12016-08-16 12:57:01 -0700714bool CompoundType::isJavaCompatible() const {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700715 if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
716 return false;
717 }
718
719 for (const auto &field : *mFields) {
720 if (!field->type().isJavaCompatible()) {
721 return false;
722 }
723 }
724
725 return true;
Andreas Huber85eabdb2016-08-25 11:24:49 -0700726}
727
728void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
729 *align = 1;
730
731 size_t offset = 0;
732 for (const auto &field : *mFields) {
733 // Each field is aligned according to its alignment requirement.
734 // The surrounding structure's alignment is the maximum of its
735 // fields' aligments.
736
737 size_t fieldAlign, fieldSize;
738 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
739
740 size_t pad = offset % fieldAlign;
741 if (pad > 0) {
742 offset += fieldAlign - pad;
743 }
744
745 offset += fieldSize;
746
747 if (fieldAlign > (*align)) {
748 *align = fieldAlign;
749 }
750 }
751
752 // Final padding to account for the structure's alignment.
753 size_t pad = offset % (*align);
754 if (pad > 0) {
755 offset += (*align) - pad;
756 }
757
758 *size = offset;
Andreas Huber70a59e12016-08-16 12:57:01 -0700759}
760
Andreas Huber31629bc2016-08-03 09:06:40 -0700761////////////////////////////////////////////////////////////////////////////////
762
763CompoundField::CompoundField(const char *name, Type *type)
764 : mName(name),
765 mType(type) {
766}
767
768std::string CompoundField::name() const {
769 return mName;
770}
771
772const Type &CompoundField::type() const {
773 return *mType;
774}
775
Andreas Huberc9410c72016-07-28 12:18:40 -0700776} // namespace android
777