blob: 9a3457e64d9406df2fa062c0a411e00f28f75d19 [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 Huber4c865b72016-09-14 15:26:27 -070085std::string CompoundType::getJavaType(
86 std::string *extra, bool /* forInitializer */) const {
87 extra->clear();
Andreas Huber85eabdb2016-08-25 11:24:49 -070088 return fullJavaName();
89}
90
Andreas Huber881227d2016-08-02 14:20:21 -070091void CompoundType::emitReaderWriter(
92 Formatter &out,
93 const std::string &name,
94 const std::string &parcelObj,
95 bool parcelObjIsPointer,
96 bool isReader,
97 ErrorMode mode) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -070098 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -070099
100 out << "size_t " << parentName << ";\n\n";
101
102 const std::string parcelObjDeref =
103 parcelObj + (parcelObjIsPointer ? "->" : ".");
104
105 if (isReader) {
106 out << name
107 << " = (const "
Andreas Huber0e00de42016-08-03 09:56:02 -0700108 << fullName()
Andreas Huber881227d2016-08-02 14:20:21 -0700109 << " *)"
110 << parcelObjDeref
111 << "readBuffer("
112 << "&"
113 << parentName
114 << ");\n";
115
116 out << "if ("
117 << name
118 << " == nullptr) {\n";
119
120 out.indent();
121
Iliyan Malchev549e2592016-08-10 08:59:12 -0700122 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700123 handleError2(out, mode);
124
125 out.unindent();
126 out << "}\n\n";
127 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700128 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700129 << parcelObjDeref
130 << "writeBuffer(&"
131 << name
132 << ", sizeof("
133 << name
134 << "), &"
135 << parentName
136 << ");\n";
137
138 handleError(out, mode);
139 }
140
141 if (mStyle != STYLE_STRUCT || !needsEmbeddedReadWrite()) {
142 return;
143 }
144
145 emitReaderWriterEmbedded(
146 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700147 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700148 name,
149 isReader /* nameIsPointer */,
150 parcelObj,
151 parcelObjIsPointer,
152 isReader,
153 mode,
154 parentName,
155 "0 /* parentOffset */");
156}
157
158void CompoundType::emitReaderWriterEmbedded(
159 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700160 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700161 const std::string &name,
162 bool nameIsPointer,
163 const std::string &parcelObj,
164 bool parcelObjIsPointer,
165 bool isReader,
166 ErrorMode mode,
167 const std::string &parentName,
168 const std::string &offsetText) const {
169 emitReaderWriterEmbeddedForTypeName(
170 out,
171 name,
172 nameIsPointer,
173 parcelObj,
174 parcelObjIsPointer,
175 isReader,
176 mode,
177 parentName,
178 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700179 fullName(),
Andreas Huber881227d2016-08-02 14:20:21 -0700180 "" /* childName */);
181}
182
Andreas Huber85eabdb2016-08-25 11:24:49 -0700183void CompoundType::emitJavaReaderWriter(
184 Formatter &out,
185 const std::string &parcelObj,
186 const std::string &argName,
187 bool isReader) const {
188 if (isReader) {
189 out << "new " << fullJavaName() << "();\n";
190 }
191
192 out << argName
193 << "."
194 << (isReader ? "readFromParcel" : "writeToParcel")
195 << "("
196 << parcelObj
197 << ");\n";
198}
199
200void CompoundType::emitJavaFieldInitializer(
201 Formatter &out, const std::string &fieldName) const {
202 out << "final "
203 << fullJavaName()
204 << " "
205 << fieldName
206 << " = new "
207 << fullJavaName()
208 << "();\n";
209}
210
211void CompoundType::emitJavaFieldReaderWriter(
212 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700213 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700214 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700215 const std::string &blobName,
216 const std::string &fieldName,
217 const std::string &offset,
218 bool isReader) const {
219 if (isReader) {
220 out << fieldName
Andreas Huber709b62d2016-09-19 11:21:18 -0700221 << ".readEmbeddedFromParcel("
222 << parcelName
223 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700224 << blobName
225 << ", "
226 << offset
227 << ");\n";
228
229 return;
230 }
231
232 out << fieldName
233 << ".writeEmbeddedToBlob("
234 << blobName
235 << ", "
236 << offset
237 << ");\n";
238}
239
Andreas Huber881227d2016-08-02 14:20:21 -0700240status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
241 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
242 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700243 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700244 << " {\n";
245
246 out.indent();
247
248 Scope::emitTypeDeclarations(out);
249
250 for (const auto &field : *mFields) {
251 std::string extra;
252 out << field->type().getCppType(&extra)
253 << " "
254 << field->name()
255 << extra
256 << ";\n";
257 }
258
259 if (needsEmbeddedReadWrite()) {
260 out << "\n::android::status_t readEmbeddedFromParcel(\n";
261
262 out.indent();
263 out.indent();
264
Andreas Huber8a82ff72016-08-04 10:29:39 -0700265 out << "const ::android::hardware::Parcel &parcel,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700266 << "size_t parentHandle,\n"
267 << "size_t parentOffset);\n\n";
268
269 out.unindent();
270 out.unindent();
271
272 out << "::android::status_t writeEmbeddedToParcel(\n";
273
274 out.indent();
275 out.indent();
276
Andreas Huber8a82ff72016-08-04 10:29:39 -0700277 out << "::android::hardware::Parcel *parcel,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700278 << "size_t parentHandle,\n"
279 << "size_t parentOffset) const;\n";
280
281 out.unindent();
282 out.unindent();
283 }
284
285 out.unindent();
286 out << "};\n\n";
287
288 return OK;
289}
290
291status_t CompoundType::emitTypeDefinitions(
292 Formatter &out, const std::string prefix) const {
Andreas Huber0e00de42016-08-03 09:56:02 -0700293 status_t err = Scope::emitTypeDefinitions(out, prefix + "::" + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700294
295 if (err != OK) {
296 return err;
297 }
298
299 if (!needsEmbeddedReadWrite()) {
300 return OK;
301 }
302
303 emitStructReaderWriter(out, prefix, true /* isReader */);
304 emitStructReaderWriter(out, prefix, false /* isReader */);
305
306 return OK;
307}
308
Andreas Huber85eabdb2016-08-25 11:24:49 -0700309status_t CompoundType::emitJavaTypeDeclarations(
310 Formatter &out, bool atTopLevel) const {
311 out << "public final ";
312
313 if (!atTopLevel) {
314 out << "static ";
315 }
316
317 out << "class "
318 << localName()
319 << " {\n";
320
321 out.indent();
322
323 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
324
325 for (const auto &field : *mFields) {
326 const bool isScope = field->type().isScope(); // really isStruct...
327
328 out << "public ";
329
330 field->type().emitJavaFieldInitializer(out, field->name());
331 }
332
333 if (!mFields->empty()) {
334 out << "\n";
335 }
336
337 out << "public final void readFromParcel(HwParcel parcel) {\n";
338 out.indent();
339 out << "HwBlob blob = parcel.readBuffer();\n";
340 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
341 out.unindent();
342 out << "}\n\n";
343
Andreas Huberf630bc82016-09-09 14:52:25 -0700344 ////////////////////////////////////////////////////////////////////////////
345
346 out << "public static final "
347 << localName()
Andreas Huberf630bc82016-09-09 14:52:25 -0700348 << "[] readVectorFromParcel(HwParcel parcel) {\n";
349 out.indent();
350
351 out << "Vector<"
352 << localName()
353 << "> _hidl_vec = new Vector();\n";
354
355 out << "HwBlob _hidl_blob = parcel.readBuffer();\n\n";
356
357 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700358 out,
359 0 /* depth */,
360 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700361 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700362 "_hidl_blob",
363 "_hidl_vec",
364 "0",
365 true /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700366
367 out << "\nreturn _hidl_vec.toArray(new "
368 << localName()
369 << "[_hidl_vec.size()]);\n";
370
371 out.unindent();
372 out << "}\n\n";
373
374 ////////////////////////////////////////////////////////////////////////////
375
Andreas Huber85eabdb2016-08-25 11:24:49 -0700376 out << "public final void readEmbeddedFromParcel(\n";
377 out.indent();
378 out.indent();
379 out << "HwParcel parcel, HwBlob _hidl_blob, long _hidl_offset) {\n";
380 out.unindent();
381
382 size_t offset = 0;
383 for (const auto &field : *mFields) {
384 size_t fieldAlign, fieldSize;
385 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
386
387 size_t pad = offset % fieldAlign;
388 if (pad > 0) {
389 offset += fieldAlign - pad;
390 }
391
392 field->type().emitJavaFieldReaderWriter(
393 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700394 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700395 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700396 "_hidl_blob",
397 field->name(),
398 "_hidl_offset + " + std::to_string(offset),
399 true /* isReader */);
400
401 offset += fieldSize;
402 }
403
404 out.unindent();
405 out << "}\n\n";
406
Andreas Huberf630bc82016-09-09 14:52:25 -0700407 ////////////////////////////////////////////////////////////////////////////
408
Andreas Huber709b62d2016-09-19 11:21:18 -0700409 size_t structAlign, structSize;
410 getAlignmentAndSize(&structAlign, &structSize);
411
Andreas Huber85eabdb2016-08-25 11:24:49 -0700412 out << "public final void writeToParcel(HwParcel parcel) {\n";
413 out.indent();
414
Andreas Huber85eabdb2016-08-25 11:24:49 -0700415 out << "HwBlob _hidl_blob = new HwBlob("
416 << structSize
417 << " /* size */);\n";
418
419 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
420 << "parcel.writeBuffer(_hidl_blob);\n";
421
422 out.unindent();
423 out << "}\n\n";
424
Andreas Huberf630bc82016-09-09 14:52:25 -0700425 ////////////////////////////////////////////////////////////////////////////
426
Andreas Huberf630bc82016-09-09 14:52:25 -0700427 out << "public static final void writeVectorToParcel(\n";
428 out.indent();
429 out.indent();
430 out << "HwParcel parcel, "
431 << localName()
432 << "[] _hidl_array) {\n";
433 out.unindent();
434
435 out << "Vector<"
436 << localName()
437 << "> _hidl_vec = new Vector(Arrays.asList(_hidl_array));\n";
438
439 out << "HwBlob _hidl_blob = new HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
440
441 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700442 out,
443 0 /* depth */,
444 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700445 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700446 "_hidl_blob",
447 "_hidl_vec",
448 "0",
449 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700450
451 out << "\nparcel.writeBuffer(_hidl_blob);\n";
452
453 out.unindent();
454 out << "}\n\n";
455
456 ////////////////////////////////////////////////////////////////////////////
457
Andreas Huber85eabdb2016-08-25 11:24:49 -0700458 out << "public final void writeEmbeddedToBlob(\n";
459 out.indent();
460 out.indent();
461 out << "HwBlob _hidl_blob, long _hidl_offset) {\n";
462 out.unindent();
463
464 offset = 0;
465 for (const auto &field : *mFields) {
466 size_t fieldAlign, fieldSize;
467 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
468
469 size_t pad = offset % fieldAlign;
470 if (pad > 0) {
471 offset += fieldAlign - pad;
472 }
473
474 field->type().emitJavaFieldReaderWriter(
475 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700476 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700477 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700478 "_hidl_blob",
479 field->name(),
480 "_hidl_offset + " + std::to_string(offset),
481 false /* isReader */);
482
483 offset += fieldSize;
484 }
485
486 out.unindent();
487 out << "}\n";
488
489 out.unindent();
490 out << "};\n\n";
491
492 return OK;
493}
494
Andreas Huber881227d2016-08-02 14:20:21 -0700495void CompoundType::emitStructReaderWriter(
496 Formatter &out, const std::string &prefix, bool isReader) const {
497 out << "::android::status_t "
498 << (prefix.empty() ? "" : (prefix + "::"))
Andreas Huber0e00de42016-08-03 09:56:02 -0700499 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700500 << (isReader ? "::readEmbeddedFromParcel"
501 : "::writeEmbeddedToParcel")
502 << "(\n";
503
504 out.indent();
505 out.indent();
506
507 if (isReader) {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700508 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700509 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700510 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700511 }
512
513 out << "size_t parentHandle,\n"
514 << "size_t parentOffset)";
515
516 if (!isReader) {
517 out << " const";
518 }
519
520 out << " {\n";
521
522 out.unindent();
523 out.unindent();
524 out.indent();
525
Iliyan Malchev549e2592016-08-10 08:59:12 -0700526 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700527
528 for (const auto &field : *mFields) {
529 if (!field->type().needsEmbeddedReadWrite()) {
530 continue;
531 }
532
533 field->type().emitReaderWriterEmbedded(
534 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700535 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700536 field->name(),
537 false /* nameIsPointer */,
538 "parcel",
539 !isReader /* parcelObjIsPointer */,
540 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700541 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700542 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700543 "parentOffset + offsetof("
544 + fullName()
545 + ", "
546 + field->name()
547 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700548 }
549
550 out.unindent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700551 out << "_hidl_error:\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700552 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700553 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700554
555 out.unindent();
556 out << "}\n\n";
557}
558
559bool CompoundType::needsEmbeddedReadWrite() const {
560 if (mStyle != STYLE_STRUCT) {
561 return false;
562 }
563
564 for (const auto &field : *mFields) {
565 if (field->type().needsEmbeddedReadWrite()) {
566 return true;
567 }
568 }
569
570 return false;
571}
572
573bool CompoundType::resultNeedsDeref() const {
574 return true;
575}
576
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700577status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
578 out << "name: \"" << localName() << "\"\n";
579 switch (mStyle) {
580 case STYLE_STRUCT:
581 {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700582 out << "type: TYPE_STRUCT\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700583 break;
584 }
585 case STYLE_UNION:
586 {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700587 out << "type: TYPE_UNION\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700588 break;
589 }
590 default:
591 break;
592 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700593
594 // Emit declaration for each subtype.
595 for (const auto &type : getSubTypes()) {
596 switch (mStyle) {
597 case STYLE_STRUCT:
598 {
599 out << "struct_value: {\n";
600 break;
601 }
602 case STYLE_UNION:
603 {
604 out << "union_value: {\n";
605 break;
606 }
607 default:
608 break;
609 }
610 out.indent();
611 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700612 if (status != OK) {
613 return status;
614 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700615 out.unindent();
616 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700617 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700618
619 // Emit declaration for each field.
620 for (const auto &field : *mFields) {
621 switch (mStyle) {
622 case STYLE_STRUCT:
623 {
624 out << "struct_value: {\n";
625 break;
626 }
627 case STYLE_UNION:
628 {
629 out << "union_value: {\n";
630 break;
631 }
632 default:
633 break;
634 }
635 out.indent();
636 out << "name: \"" << field->name() << "\"\n";
637 status_t status = field->type().emitVtsAttributeType(out);
638 if (status != OK) {
639 return status;
640 }
641 out.unindent();
642 out << "}\n";
643 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700644
645 return OK;
646}
647
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700648status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700649 switch (mStyle) {
650 case STYLE_STRUCT:
651 {
652 out << "type: TYPE_STRUCT\n";
653 break;
654 }
655 case STYLE_UNION:
656 {
657 out << "type: TYPE_UNION\n";
658 break;
659 }
660 default:
661 break;
662 }
663 out << "predefined_type: \"" << localName() << "\"\n";
664 return OK;
665}
666
Andreas Huber70a59e12016-08-16 12:57:01 -0700667bool CompoundType::isJavaCompatible() const {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700668 if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
669 return false;
670 }
671
672 for (const auto &field : *mFields) {
673 if (!field->type().isJavaCompatible()) {
674 return false;
675 }
676 }
677
678 return true;
Andreas Huber85eabdb2016-08-25 11:24:49 -0700679}
680
681void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
682 *align = 1;
683
684 size_t offset = 0;
685 for (const auto &field : *mFields) {
686 // Each field is aligned according to its alignment requirement.
687 // The surrounding structure's alignment is the maximum of its
688 // fields' aligments.
689
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 offset += fieldSize;
699
700 if (fieldAlign > (*align)) {
701 *align = fieldAlign;
702 }
703 }
704
705 // Final padding to account for the structure's alignment.
706 size_t pad = offset % (*align);
707 if (pad > 0) {
708 offset += (*align) - pad;
709 }
710
711 *size = offset;
Andreas Huber70a59e12016-08-16 12:57:01 -0700712}
713
Andreas Huber31629bc2016-08-03 09:06:40 -0700714////////////////////////////////////////////////////////////////////////////////
715
716CompoundField::CompoundField(const char *name, Type *type)
717 : mName(name),
718 mType(type) {
719}
720
721std::string CompoundField::name() const {
722 return mName;
723}
724
725const Type &CompoundField::type() const {
726 return *mType;
727}
728
Andreas Huberc9410c72016-07-28 12:18:40 -0700729} // namespace android
730