blob: 2123602ad4cf02c41df162fdde8531bd599b70db [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"
Timur Iskhakovcec46c42017-08-09 00:22:02 -070021
Andreas Huber5a545442016-08-03 10:44:56 -070022#include <android-base/logging.h>
Timur Iskhakovcec46c42017-08-09 00:22:02 -070023#include <hidl-util/Formatter.h>
24#include <unordered_set>
Andreas Huber5a545442016-08-03 10:44:56 -070025
Andreas Huberc9410c72016-07-28 12:18:40 -070026namespace android {
27
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070028CompoundType::CompoundType(Style style, const char* localName, const Location& location,
29 Scope* parent)
30 : Scope(localName, location, parent), mStyle(style), mFields(NULL) {}
Andreas Huberc9410c72016-07-28 12:18:40 -070031
Yifan Hong27e85db2016-11-09 15:45:52 -080032CompoundType::Style CompoundType::style() const {
33 return mStyle;
34}
35
Timur Iskhakovcec46c42017-08-09 00:22:02 -070036void CompoundType::setFields(std::vector<NamedReference<Type>*>* fields) {
Andreas Huberc9410c72016-07-28 12:18:40 -070037 mFields = fields;
Timur Iskhakovcec46c42017-08-09 00:22:02 -070038}
Andreas Huber5a545442016-08-03 10:44:56 -070039
Timur Iskhakov33431e62017-08-21 17:31:23 -070040std::vector<Reference<Type>> CompoundType::getReferences() const {
41 std::vector<Reference<Type>> ret;
42 for (const auto* field : *mFields) {
43 ret.push_back(*field);
Timur Iskhakovcec46c42017-08-09 00:22:02 -070044 }
Timur Iskhakov33431e62017-08-21 17:31:23 -070045 return ret;
Timur Iskhakovcec46c42017-08-09 00:22:02 -070046}
47
48status_t CompoundType::validate() const {
49 for (const auto* field : *mFields) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070050 const Type& type = field->type();
Andreas Huber5a545442016-08-03 10:44:56 -070051
Andreas Huber86a112b2016-10-19 14:25:16 -070052 if (type.isBinder()
53 || (type.isVector()
54 && static_cast<const VectorType *>(
55 &type)->isVectorOfBinders())) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070056 std::cerr << "ERROR: Struct/Union must not contain references to interfaces at "
57 << field->location() << "\n";
58 return UNKNOWN_ERROR;
Andreas Huberb95ea8a2016-08-15 15:35:42 -070059 }
60
Andreas Huber5a545442016-08-03 10:44:56 -070061 if (mStyle == STYLE_UNION) {
62 if (type.needsEmbeddedReadWrite()) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070063 std::cerr << "ERROR: Union must not contain any types that need fixup at "
64 << field->location() << "\n";
65 return UNKNOWN_ERROR;
Andreas Huber5a545442016-08-03 10:44:56 -070066 }
Andreas Huber5a545442016-08-03 10:44:56 -070067 }
68 }
69
Timur Iskhakovcec46c42017-08-09 00:22:02 -070070 status_t err = validateUniqueNames();
71 if (err != OK) return err;
72
73 return Scope::validate();
74}
75
76status_t CompoundType::validateUniqueNames() const {
77 std::unordered_set<std::string> names;
78
79 for (const auto* field : *mFields) {
80 if (names.find(field->name()) != names.end()) {
81 std::cerr << "ERROR: Redefinition of field '" << field->name() << "' at "
82 << field->location() << "\n";
83 return UNKNOWN_ERROR;
84 }
85 names.insert(field->name());
86 }
87
88 return OK;
Andreas Huberc9410c72016-07-28 12:18:40 -070089}
90
Andreas Huberf630bc82016-09-09 14:52:25 -070091bool CompoundType::isCompoundType() const {
92 return true;
93}
94
Yifan Hongc6752dc2016-12-20 14:00:14 -080095bool CompoundType::canCheckEquality() const {
96 if (mStyle == STYLE_UNION) {
97 return false;
98 }
99 for (const auto &field : *mFields) {
100 if (!field->type().canCheckEquality()) {
101 return false;
102 }
103 }
104 return true;
105}
106
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700107std::string CompoundType::typeName() const {
108 switch (mStyle) {
109 case STYLE_STRUCT: {
110 return "struct " + localName();
111 }
112 case STYLE_UNION: {
113 return "union " + localName();
114 }
115 }
116 CHECK(!"Should not be here");
117}
118
Andreas Huber881227d2016-08-02 14:20:21 -0700119std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -0700120 StorageMode mode,
Steven Morelande30ee9b2017-05-09 13:31:01 -0700121 bool /* specifyNamespaces */) const {
122 const std::string base = fullName();
Andreas Huber881227d2016-08-02 14:20:21 -0700123
124 switch (mode) {
125 case StorageMode_Stack:
126 return base;
127
128 case StorageMode_Argument:
129 return "const " + base + "&";
130
131 case StorageMode_Result:
132 return "const " + base + "*";
133 }
134}
135
Yifan Hong4ed13472016-11-02 10:44:11 -0700136std::string CompoundType::getJavaType(bool /* forInitializer */) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700137 return fullJavaName();
138}
139
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700140std::string CompoundType::getVtsType() const {
141 switch (mStyle) {
142 case STYLE_STRUCT:
143 {
144 return "TYPE_STRUCT";
145 }
146 case STYLE_UNION:
147 {
148 return "TYPE_UNION";
149 }
150 }
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700151 CHECK(!"Should not be here");
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700152}
153
Andreas Huber881227d2016-08-02 14:20:21 -0700154void CompoundType::emitReaderWriter(
155 Formatter &out,
156 const std::string &name,
157 const std::string &parcelObj,
158 bool parcelObjIsPointer,
159 bool isReader,
160 ErrorMode mode) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700161 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700162
163 out << "size_t " << parentName << ";\n\n";
164
165 const std::string parcelObjDeref =
166 parcelObj + (parcelObjIsPointer ? "->" : ".");
167
168 if (isReader) {
Martijn Coenen6a082c62017-01-11 12:47:02 +0100169 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700170 << parcelObjDeref
171 << "readBuffer("
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700172 << "sizeof(*"
173 << name
174 << "), &"
Andreas Huber881227d2016-08-02 14:20:21 -0700175 << parentName
Martijn Coenen6a082c62017-01-11 12:47:02 +0100176 << ", "
177 << " reinterpret_cast<const void **>("
178 << "&" << name
179 << "));\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700180
Martijn Coenen6a082c62017-01-11 12:47:02 +0100181 handleError(out, mode);
Andreas Huber881227d2016-08-02 14:20:21 -0700182 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700183 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700184 << parcelObjDeref
185 << "writeBuffer(&"
186 << name
187 << ", sizeof("
188 << name
189 << "), &"
190 << parentName
191 << ");\n";
192
193 handleError(out, mode);
194 }
195
196 if (mStyle != STYLE_STRUCT || !needsEmbeddedReadWrite()) {
197 return;
198 }
199
200 emitReaderWriterEmbedded(
201 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700202 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700203 name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700204 name, /* sanitizedName */
Andreas Huber881227d2016-08-02 14:20:21 -0700205 isReader /* nameIsPointer */,
206 parcelObj,
207 parcelObjIsPointer,
208 isReader,
209 mode,
210 parentName,
211 "0 /* parentOffset */");
212}
213
214void CompoundType::emitReaderWriterEmbedded(
215 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700216 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700217 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700218 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700219 bool nameIsPointer,
220 const std::string &parcelObj,
221 bool parcelObjIsPointer,
222 bool isReader,
223 ErrorMode mode,
224 const std::string &parentName,
225 const std::string &offsetText) const {
226 emitReaderWriterEmbeddedForTypeName(
227 out,
228 name,
229 nameIsPointer,
230 parcelObj,
231 parcelObjIsPointer,
232 isReader,
233 mode,
234 parentName,
235 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700236 fullName(),
Yifan Hong244e82d2016-11-11 11:13:57 -0800237 "" /* childName */,
238 "" /* namespace */);
Andreas Huber881227d2016-08-02 14:20:21 -0700239}
240
Andreas Huber85eabdb2016-08-25 11:24:49 -0700241void CompoundType::emitJavaReaderWriter(
242 Formatter &out,
243 const std::string &parcelObj,
244 const std::string &argName,
245 bool isReader) const {
246 if (isReader) {
247 out << "new " << fullJavaName() << "();\n";
248 }
249
250 out << argName
251 << "."
252 << (isReader ? "readFromParcel" : "writeToParcel")
253 << "("
254 << parcelObj
255 << ");\n";
256}
257
258void CompoundType::emitJavaFieldInitializer(
259 Formatter &out, const std::string &fieldName) const {
260 out << "final "
261 << fullJavaName()
262 << " "
263 << fieldName
264 << " = new "
265 << fullJavaName()
266 << "();\n";
267}
268
269void CompoundType::emitJavaFieldReaderWriter(
270 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700271 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700272 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700273 const std::string &blobName,
274 const std::string &fieldName,
275 const std::string &offset,
276 bool isReader) const {
277 if (isReader) {
278 out << fieldName
Andreas Huber709b62d2016-09-19 11:21:18 -0700279 << ".readEmbeddedFromParcel("
280 << parcelName
281 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700282 << blobName
283 << ", "
284 << offset
285 << ");\n";
286
287 return;
288 }
289
290 out << fieldName
291 << ".writeEmbeddedToBlob("
292 << blobName
293 << ", "
294 << offset
295 << ");\n";
296}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700297void CompoundType::emitResolveReferences(
298 Formatter &out,
299 const std::string &name,
300 bool nameIsPointer,
301 const std::string &parcelObj,
302 bool parcelObjIsPointer,
303 bool isReader,
304 ErrorMode mode) const {
305 emitResolveReferencesEmbedded(
306 out,
307 0 /* depth */,
308 name,
309 name /* sanitizedName */,
310 nameIsPointer,
311 parcelObj,
312 parcelObjIsPointer,
313 isReader,
314 mode,
315 "_hidl_" + name + "_parent",
316 "0 /* parentOffset */");
317}
318
319void CompoundType::emitResolveReferencesEmbedded(
320 Formatter &out,
321 size_t /* depth */,
322 const std::string &name,
323 const std::string &/* sanitizedName */,
324 bool nameIsPointer,
325 const std::string &parcelObj,
326 bool parcelObjIsPointer,
327 bool isReader,
328 ErrorMode mode,
329 const std::string &parentName,
330 const std::string &offsetText) const {
331 CHECK(needsResolveReferences());
332
333 const std::string parcelObjDeref =
334 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
335
336 const std::string parcelObjPointer =
337 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
338
Yifan Hong244e82d2016-11-11 11:13:57 -0800339 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700340 const std::string namePointer = nameIsPointer ? name : ("&" + name);
341
342 out << "_hidl_err = ";
343
344 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800345 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700346 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800347 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700348 }
349
Yifan Hong33223ca2016-12-13 15:07:35 -0800350 out.indent(2, [&]{
Yifan Hong244e82d2016-11-11 11:13:57 -0800351 if (isReader) {
352 out << "const_cast<"
353 << fullName()
354 << " *"
355 << ">("
356 << namePointer
357 << "),\n"
358 << parcelObjDeref;
359 } else {
360 out << nameDerefed
361 << ",\n"
362 << parcelObjPointer;
363 }
364
365 out << ",\n"
Yifan Hong0a68a282016-10-21 16:32:34 -0700366 << parentName
367 << ",\n"
368 << offsetText
369 << ");\n\n";
370 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700371
372 handleError(out, mode);
373}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700374
Andreas Huber881227d2016-08-02 14:20:21 -0700375status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
376 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
377 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700378 << localName()
Yifan Hongb1d2ebc2016-12-20 17:18:07 -0800379 << " final {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700380
381 out.indent();
382
383 Scope::emitTypeDeclarations(out);
384
Andreas Huber60d3b222017-03-30 09:10:56 -0700385 if (containsPointer()) {
Andreas Huberca4bc892017-01-09 14:58:12 -0800386 for (const auto &field : *mFields) {
387 out << field->type().getCppStackType()
388 << " "
389 << field->name()
390 << ";\n";
391 }
392
393 out.unindent();
394 out << "};\n\n";
395
396 return OK;
Andreas Huber881227d2016-08-02 14:20:21 -0700397 }
398
Andreas Huberca4bc892017-01-09 14:58:12 -0800399 for (int pass = 0; pass < 2; ++pass) {
400 size_t offset = 0;
401 for (const auto &field : *mFields) {
402 size_t fieldAlign, fieldSize;
403 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
404
405 size_t pad = offset % fieldAlign;
406 if (pad > 0) {
407 offset += fieldAlign - pad;
408 }
409
410 if (pass == 0) {
411 out << field->type().getCppStackType()
412 << " "
413 << field->name()
414 << " __attribute__ ((aligned("
415 << fieldAlign
416 << ")));\n";
417 } else {
418 out << "static_assert(offsetof("
419 << fullName()
420 << ", "
421 << field->name()
422 << ") == "
423 << offset
424 << ", \"wrong offset\");\n";
425 }
426
Andreas Huber60d3b222017-03-30 09:10:56 -0700427 if (mStyle == STYLE_STRUCT) {
428 offset += fieldSize;
429 }
Andreas Huberca4bc892017-01-09 14:58:12 -0800430 }
431
432 if (pass == 0) {
433 out.unindent();
434 out << "};\n\n";
435 }
436 }
437
438 size_t structAlign, structSize;
439 getAlignmentAndSize(&structAlign, &structSize);
440
441 out << "static_assert(sizeof("
442 << fullName()
443 << ") == "
444 << structSize
445 << ", \"wrong size\");\n";
446
447 out << "static_assert(__alignof("
448 << fullName()
449 << ") == "
450 << structAlign
451 << ", \"wrong alignment\");\n\n";
Yifan Hong244e82d2016-11-11 11:13:57 -0800452
453 return OK;
454}
455
456
Yifan Hongc6752dc2016-12-20 14:00:14 -0800457status_t CompoundType::emitGlobalTypeDeclarations(Formatter &out) const {
458 Scope::emitGlobalTypeDeclarations(out);
459
Steven Moreland3d98bc42017-06-23 21:36:41 +0000460 out << "std::string toString("
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800461 << getCppArgumentType()
Steven Moreland3d98bc42017-06-23 21:36:41 +0000462 << ");\n\n";
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800463
Yifan Hong42c68432017-03-13 16:22:03 -0700464 if (canCheckEquality()) {
Steven Morelandf91048a2017-06-23 21:38:35 +0000465 out << "bool operator==("
466 << getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
Yifan Hong42c68432017-03-13 16:22:03 -0700467
Steven Morelandf91048a2017-06-23 21:38:35 +0000468 out << "bool operator!=("
469 << getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
Yifan Hong42c68432017-03-13 16:22:03 -0700470 } else {
Steven Morelandf91048a2017-06-23 21:38:35 +0000471 out << "// operator== and operator!= are not generated for " << localName() << "\n\n";
Yifan Hongc6752dc2016-12-20 14:00:14 -0800472 }
473
Yifan Hongc6752dc2016-12-20 14:00:14 -0800474 return OK;
475}
476
Yifan Hong244e82d2016-11-11 11:13:57 -0800477status_t CompoundType::emitGlobalHwDeclarations(Formatter &out) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700478 if (needsEmbeddedReadWrite()) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800479 out << "::android::status_t readEmbeddedFromParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700480
Yifan Hong0a68a282016-10-21 16:32:34 -0700481 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700482
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700483 out << "const " << fullName() << " &obj,\n"
Yifan Hong244e82d2016-11-11 11:13:57 -0800484 << "const ::android::hardware::Parcel &parcel,\n"
485 << "size_t parentHandle,\n"
486 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700487
Yifan Hong0a68a282016-10-21 16:32:34 -0700488 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700489
490 out << "::android::status_t writeEmbeddedToParcel(\n";
491
Yifan Hong0a68a282016-10-21 16:32:34 -0700492 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700493
Yifan Hong244e82d2016-11-11 11:13:57 -0800494 out << "const " << fullName() << " &obj,\n"
495 << "::android::hardware::Parcel *parcel,\n"
496 << "size_t parentHandle,\n"
497 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700498
Yifan Hong0a68a282016-10-21 16:32:34 -0700499 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700500 }
501
Yifan Hongbf459bc2016-08-23 16:50:37 -0700502 if(needsResolveReferences()) {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700503 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700504 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800505 out << fullName() << " *obj,\n"
506 << "const ::android::hardware::Parcel &parcel,\n"
507 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700508 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700509 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700510 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800511 out << "const " << fullName() << " &obj,\n"
512 << "::android::hardware::Parcel *,\n"
513 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700514 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700515 }
516
Andreas Huber881227d2016-08-02 14:20:21 -0700517 return OK;
518}
519
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -0700520status_t CompoundType::emitTypeDefinitions(Formatter& out, const std::string& prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -0700521 std::string space = prefix.empty() ? "" : (prefix + "::");
522 status_t err = Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700523
524 if (err != OK) {
525 return err;
526 }
527
Yifan Hongbf459bc2016-08-23 16:50:37 -0700528 if (needsEmbeddedReadWrite()) {
529 emitStructReaderWriter(out, prefix, true /* isReader */);
530 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -0700531 }
532
Yifan Hongbf459bc2016-08-23 16:50:37 -0700533 if (needsResolveReferences()) {
534 emitResolveReferenceDef(out, prefix, true /* isReader */);
535 emitResolveReferenceDef(out, prefix, false /* isReader */);
536 }
Andreas Huber881227d2016-08-02 14:20:21 -0700537
Steven Moreland3d98bc42017-06-23 21:36:41 +0000538 out << "std::string toString("
539 << getCppArgumentType()
540 << (mFields->empty() ? "" : " o")
541 << ") ";
542
543 out.block([&] {
544 // include toString for scalar types
545 out << "using ::android::hardware::toString;\n"
546 << "std::string os;\n";
547 out << "os += \"{\";\n";
548
Timur Iskhakov7fa79f62017-08-09 11:04:54 -0700549 for (const NamedReference<Type>* field : *mFields) {
Steven Moreland3d98bc42017-06-23 21:36:41 +0000550 out << "os += \"";
551 if (field != *(mFields->begin())) {
552 out << ", ";
553 }
554 out << "." << field->name() << " = \";\n";
555 field->type().emitDump(out, "os", "o." + field->name());
556 }
557
558 out << "os += \"}\"; return os;\n";
559 }).endl().endl();
560
Steven Morelandf91048a2017-06-23 21:38:35 +0000561 if (canCheckEquality()) {
562 out << "bool operator==("
563 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
564 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
565 out.block([&] {
566 for (const auto &field : *mFields) {
567 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
568 out << "return false;\n";
569 }).endl();
570 }
571 out << "return true;\n";
572 }).endl().endl();
573
574 out << "bool operator!=("
575 << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
576 out.block([&] {
577 out << "return !(lhs == rhs);\n";
578 }).endl().endl();
579 } else {
580 out << "// operator== and operator!= are not generated for " << localName() << "\n";
581 }
582
Andreas Huber881227d2016-08-02 14:20:21 -0700583 return OK;
584}
585
Andreas Huber85eabdb2016-08-25 11:24:49 -0700586status_t CompoundType::emitJavaTypeDeclarations(
587 Formatter &out, bool atTopLevel) const {
588 out << "public final ";
589
590 if (!atTopLevel) {
591 out << "static ";
592 }
593
594 out << "class "
595 << localName()
596 << " {\n";
597
598 out.indent();
599
600 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
601
602 for (const auto &field : *mFields) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700603 out << "public ";
604
605 field->type().emitJavaFieldInitializer(out, field->name());
606 }
607
608 if (!mFields->empty()) {
609 out << "\n";
610 }
611
Yifan Hongec102272016-12-20 18:10:07 -0800612 ////////////////////////////////////////////////////////////////////////////
613
614 if (canCheckEquality()) {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800615 out << "@Override\npublic final boolean equals(Object otherObject) ";
Yifan Hongec102272016-12-20 18:10:07 -0800616 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800617 out.sIf("this == otherObject", [&] {
618 out << "return true;\n";
619 }).endl();
620 out.sIf("otherObject == null", [&] {
621 out << "return false;\n";
622 }).endl();
Yifan Hong45b331b2017-03-27 12:59:54 -0700623 // Though class is final, we use getClass instead of instanceof to be explicit.
624 out.sIf("otherObject.getClass() != " + fullJavaName() + ".class", [&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800625 out << "return false;\n";
626 }).endl();
627 out << fullJavaName() << " other = (" << fullJavaName() << ")otherObject;\n";
Yifan Hongec102272016-12-20 18:10:07 -0800628 for (const auto &field : *mFields) {
Yifan Hong45b331b2017-03-27 12:59:54 -0700629 std::string condition = (field->type().isScalar() || field->type().isEnum())
Yifan Hongec102272016-12-20 18:10:07 -0800630 ? "this." + field->name() + " != other." + field->name()
Yifan Hong45b331b2017-03-27 12:59:54 -0700631 : ("!android.os.HidlSupport.deepEquals(this." + field->name()
Yifan Hongec102272016-12-20 18:10:07 -0800632 + ", other." + field->name() + ")");
633 out.sIf(condition, [&] {
634 out << "return false;\n";
635 }).endl();
636 }
637 out << "return true;\n";
638 }).endl().endl();
639
Yifan Hong7d1839f2017-02-22 13:24:29 -0800640 out << "@Override\npublic final int hashCode() ";
Yifan Hongec102272016-12-20 18:10:07 -0800641 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800642 out << "return java.util.Objects.hash(\n";
643 out.indent(2, [&] {
Yifan Hong932464e2017-03-30 15:40:22 -0700644 out.join(mFields->begin(), mFields->end(), ", \n", [&] (const auto &field) {
Yifan Hong45b331b2017-03-27 12:59:54 -0700645 out << "android.os.HidlSupport.deepHashCode(this." << field->name() << ")";
Yifan Hong932464e2017-03-30 15:40:22 -0700646 });
Yifan Hong7d1839f2017-02-22 13:24:29 -0800647 });
Yifan Hongec102272016-12-20 18:10:07 -0800648 out << ");\n";
649 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -0700650 } else {
651 out << "// equals() is not generated for " << localName() << "\n";
Yifan Hongec102272016-12-20 18:10:07 -0800652 }
653
654 ////////////////////////////////////////////////////////////////////////////
655
Yifan Honge45b5302017-02-22 10:49:07 -0800656 out << "@Override\npublic final String toString() ";
657 out.block([&] {
658 out << "java.lang.StringBuilder builder = new java.lang.StringBuilder();\n"
659 << "builder.append(\"{\");\n";
660 for (const auto &field : *mFields) {
661 out << "builder.append(\"";
662 if (field != *(mFields->begin())) {
663 out << ", ";
664 }
665 out << "." << field->name() << " = \");\n";
666 field->type().emitJavaDump(out, "builder", "this." + field->name());
667 }
668 out << "builder.append(\"}\");\nreturn builder.toString();\n";
669 }).endl().endl();
670
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700671 size_t structAlign, structSize;
672 getAlignmentAndSize(&structAlign, &structSize);
673
Yifan Honge45b5302017-02-22 10:49:07 -0800674 ////////////////////////////////////////////////////////////////////////////
675
Yifan Hong1af73532016-11-09 14:32:58 -0800676 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700677 out.indent();
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700678 out << "android.os.HwBlob blob = parcel.readBuffer(";
679 out << structSize << "/* size */);\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700680 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
681 out.unindent();
682 out << "}\n\n";
683
Andreas Huberf630bc82016-09-09 14:52:25 -0700684 ////////////////////////////////////////////////////////////////////////////
685
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700686 size_t vecAlign, vecSize;
687 VectorType::getAlignmentAndSizeStatic(&vecAlign, &vecSize);
688
Yifan Hong1af73532016-11-09 14:32:58 -0800689 out << "public static final java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700690 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800691 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700692 out.indent();
693
Yifan Hong1af73532016-11-09 14:32:58 -0800694 out << "java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700695 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800696 << "> _hidl_vec = new java.util.ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700697
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700698 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer(";
699 out << vecSize << " /* sizeof hidl_vec<T> */);\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700700
701 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700702 out,
703 0 /* depth */,
704 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700705 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700706 "_hidl_blob",
707 "_hidl_vec",
708 "0",
709 true /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700710
Andreas Huber1b6822b2016-10-18 09:28:40 -0700711 out << "\nreturn _hidl_vec;\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700712
713 out.unindent();
714 out << "}\n\n";
715
716 ////////////////////////////////////////////////////////////////////////////
717
Andreas Huber85eabdb2016-08-25 11:24:49 -0700718 out << "public final void readEmbeddedFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700719 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800720 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700721 out.unindent();
722
723 size_t offset = 0;
724 for (const auto &field : *mFields) {
725 size_t fieldAlign, fieldSize;
726 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
727
728 size_t pad = offset % fieldAlign;
729 if (pad > 0) {
730 offset += fieldAlign - pad;
731 }
732
733 field->type().emitJavaFieldReaderWriter(
734 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700735 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700736 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700737 "_hidl_blob",
738 field->name(),
739 "_hidl_offset + " + std::to_string(offset),
740 true /* isReader */);
741
742 offset += fieldSize;
743 }
744
745 out.unindent();
746 out << "}\n\n";
747
Andreas Huberf630bc82016-09-09 14:52:25 -0700748 ////////////////////////////////////////////////////////////////////////////
749
Yifan Hong1af73532016-11-09 14:32:58 -0800750 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700751 out.indent();
752
Yifan Hong1af73532016-11-09 14:32:58 -0800753 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
Andreas Huber85eabdb2016-08-25 11:24:49 -0700754 << structSize
755 << " /* size */);\n";
756
757 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
758 << "parcel.writeBuffer(_hidl_blob);\n";
759
760 out.unindent();
761 out << "}\n\n";
762
Andreas Huberf630bc82016-09-09 14:52:25 -0700763 ////////////////////////////////////////////////////////////////////////////
764
Andreas Huberf630bc82016-09-09 14:52:25 -0700765 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700766 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800767 out << "android.os.HwParcel parcel, java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700768 << localName()
Andreas Huber1b6822b2016-10-18 09:28:40 -0700769 << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700770 out.unindent();
771
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700772 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
773 << vecSize << " /* sizeof(hidl_vec<T>) */);\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700774
775 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700776 out,
777 0 /* depth */,
778 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700779 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700780 "_hidl_blob",
781 "_hidl_vec",
782 "0",
783 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700784
785 out << "\nparcel.writeBuffer(_hidl_blob);\n";
786
787 out.unindent();
788 out << "}\n\n";
789
790 ////////////////////////////////////////////////////////////////////////////
791
Andreas Huber85eabdb2016-08-25 11:24:49 -0700792 out << "public final void writeEmbeddedToBlob(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700793 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800794 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700795 out.unindent();
796
797 offset = 0;
798 for (const auto &field : *mFields) {
799 size_t fieldAlign, fieldSize;
800 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
801
802 size_t pad = offset % fieldAlign;
803 if (pad > 0) {
804 offset += fieldAlign - pad;
805 }
806
807 field->type().emitJavaFieldReaderWriter(
808 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700809 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700810 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700811 "_hidl_blob",
812 field->name(),
813 "_hidl_offset + " + std::to_string(offset),
814 false /* isReader */);
815
816 offset += fieldSize;
817 }
818
819 out.unindent();
820 out << "}\n";
821
822 out.unindent();
823 out << "};\n\n";
824
825 return OK;
826}
827
Andreas Huber881227d2016-08-02 14:20:21 -0700828void CompoundType::emitStructReaderWriter(
829 Formatter &out, const std::string &prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800830
831 std::string space = prefix.empty() ? "" : (prefix + "::");
832
Andreas Huber881227d2016-08-02 14:20:21 -0700833 out << "::android::status_t "
Yifan Hong244e82d2016-11-11 11:13:57 -0800834 << (isReader ? "readEmbeddedFromParcel"
835 : "writeEmbeddedToParcel")
836 << "(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700837
Yifan Hong0a68a282016-10-21 16:32:34 -0700838 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700839
Yifan Hong244e82d2016-11-11 11:13:57 -0800840 bool useName = false;
841 for (const auto &field : *mFields) {
842 if (field->type().useNameInEmitReaderWriterEmbedded(isReader)) {
843 useName = true;
844 break;
845 }
846 }
847 std::string name = useName ? "obj" : "/* obj */";
848 // if not useName, then obj should not be used at all,
849 // then the #error should not be emitted.
850 std::string error = useName ? "" : "\n#error\n";
851
Andreas Huber881227d2016-08-02 14:20:21 -0700852 if (isReader) {
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700853 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700854 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700855 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800856 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700857 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700858 }
859
860 out << "size_t parentHandle,\n"
861 << "size_t parentOffset)";
862
Andreas Huber881227d2016-08-02 14:20:21 -0700863 out << " {\n";
864
Yifan Hong0a68a282016-10-21 16:32:34 -0700865 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700866 out.indent();
867
Iliyan Malchev549e2592016-08-10 08:59:12 -0700868 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700869
870 for (const auto &field : *mFields) {
871 if (!field->type().needsEmbeddedReadWrite()) {
872 continue;
873 }
874
875 field->type().emitReaderWriterEmbedded(
876 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700877 0 /* depth */,
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700878 name + "." + field->name() + error,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700879 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700880 false /* nameIsPointer */,
881 "parcel",
882 !isReader /* parcelObjIsPointer */,
883 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700884 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700885 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700886 "parentOffset + offsetof("
887 + fullName()
888 + ", "
889 + field->name()
890 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700891 }
892
Iliyan Malchev549e2592016-08-10 08:59:12 -0700893 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700894
895 out.unindent();
896 out << "}\n\n";
897}
898
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -0700899void CompoundType::emitResolveReferenceDef(Formatter& out, const std::string& prefix,
900 bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800901 out << "::android::status_t ";
902 const std::string space(prefix.empty() ? "" : (prefix + "::"));
Yifan Hong00f47172016-09-30 14:40:45 -0700903
904 bool useParent = false;
905 for (const auto &field : *mFields) {
906 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
907 useParent = true;
908 break;
909 }
910 }
911
912 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
913 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
914
Yifan Hongbf459bc2016-08-23 16:50:37 -0700915 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800916 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700917 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800918 out << space + localName() + " *obj,\n"
919 << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700920 << "size_t " << parentHandleName << ", "
921 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700922 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700923 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800924 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700925 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800926 out << "const " << space + localName() + " &obj,\n"
927 << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700928 << "size_t " << parentHandleName << ", "
Yifan Hong244e82d2016-11-11 11:13:57 -0800929 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700930 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700931 }
932
933 out << " {\n";
934
935 out.indent();
936
937 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
938
Yifan Hong244e82d2016-11-11 11:13:57 -0800939 const std::string nameDeref(isReader ? "obj->" : "obj.");
Yifan Hong00f47172016-09-30 14:40:45 -0700940 // if not useParent, then parentName and offsetText
941 // should not be used at all, then the #error should not be emitted.
942 std::string error = useParent ? "" : "\n#error\n";
943
Yifan Hongbf459bc2016-08-23 16:50:37 -0700944 for (const auto &field : *mFields) {
945 if (!field->type().needsResolveReferences()) {
946 continue;
947 }
948
949 field->type().emitResolveReferencesEmbedded(
950 out,
951 0 /* depth */,
Yifan Hong244e82d2016-11-11 11:13:57 -0800952 nameDeref + field->name(),
Yifan Hongbf459bc2016-08-23 16:50:37 -0700953 field->name() /* sanitizedName */,
954 false, // nameIsPointer
955 "parcel", // const std::string &parcelObj,
956 !isReader, // bool parcelObjIsPointer,
957 isReader, // bool isReader,
958 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -0700959 parentHandleName + error,
960 parentOffsetName
961 + " + offsetof("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700962 + fullName()
963 + ", "
964 + field->name()
Yifan Hong00f47172016-09-30 14:40:45 -0700965 + ")"
966 + error);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700967 }
968
Yifan Hongbf459bc2016-08-23 16:50:37 -0700969 out << "return _hidl_err;\n";
970
971 out.unindent();
972 out << "}\n\n";
973}
974
Andreas Huber881227d2016-08-02 14:20:21 -0700975bool CompoundType::needsEmbeddedReadWrite() const {
976 if (mStyle != STYLE_STRUCT) {
977 return false;
978 }
979
980 for (const auto &field : *mFields) {
981 if (field->type().needsEmbeddedReadWrite()) {
982 return true;
983 }
984 }
985
986 return false;
987}
988
Yifan Hongbf459bc2016-08-23 16:50:37 -0700989bool CompoundType::needsResolveReferences() const {
990 if (mStyle != STYLE_STRUCT) {
991 return false;
992 }
993
994 for (const auto &field : *mFields) {
995 if (field->type().needsResolveReferences()) {
996 return true;
997 }
998 }
999
1000 return false;
1001}
1002
Andreas Huber881227d2016-08-02 14:20:21 -07001003bool CompoundType::resultNeedsDeref() const {
1004 return true;
1005}
1006
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001007status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07001008 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001009 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001010
1011 // Emit declaration for each subtype.
1012 for (const auto &type : getSubTypes()) {
1013 switch (mStyle) {
1014 case STYLE_STRUCT:
1015 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001016 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001017 break;
1018 }
1019 case STYLE_UNION:
1020 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001021 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001022 break;
1023 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001024 }
1025 out.indent();
1026 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001027 if (status != OK) {
1028 return status;
1029 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001030 out.unindent();
1031 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001032 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001033
1034 // Emit declaration for each field.
1035 for (const auto &field : *mFields) {
1036 switch (mStyle) {
1037 case STYLE_STRUCT:
1038 {
1039 out << "struct_value: {\n";
1040 break;
1041 }
1042 case STYLE_UNION:
1043 {
1044 out << "union_value: {\n";
1045 break;
1046 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001047 }
1048 out.indent();
1049 out << "name: \"" << field->name() << "\"\n";
1050 status_t status = field->type().emitVtsAttributeType(out);
1051 if (status != OK) {
1052 return status;
1053 }
1054 out.unindent();
1055 out << "}\n";
1056 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001057
1058 return OK;
1059}
1060
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001061status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001062 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07001063 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001064 return OK;
1065}
1066
Andreas Huber70a59e12016-08-16 12:57:01 -07001067bool CompoundType::isJavaCompatible() const {
Andreas Huber0fa9e392016-08-31 09:05:44 -07001068 if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
1069 return false;
1070 }
1071
1072 for (const auto &field : *mFields) {
1073 if (!field->type().isJavaCompatible()) {
1074 return false;
1075 }
1076 }
1077
1078 return true;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001079}
1080
Andreas Huber60d3b222017-03-30 09:10:56 -07001081bool CompoundType::containsPointer() const {
1082 if (Scope::containsPointer()) {
1083 return true;
1084 }
1085
1086 for (const auto &field : *mFields) {
1087 if (field->type().containsPointer()) {
1088 return true;
1089 }
1090 }
1091
1092 return false;
1093}
1094
Andreas Huber85eabdb2016-08-25 11:24:49 -07001095void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
1096 *align = 1;
Andreas Huber60d3b222017-03-30 09:10:56 -07001097 *size = 0;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001098
1099 size_t offset = 0;
1100 for (const auto &field : *mFields) {
1101 // Each field is aligned according to its alignment requirement.
1102 // The surrounding structure's alignment is the maximum of its
1103 // fields' aligments.
1104
1105 size_t fieldAlign, fieldSize;
1106 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1107
1108 size_t pad = offset % fieldAlign;
1109 if (pad > 0) {
1110 offset += fieldAlign - pad;
1111 }
1112
Andreas Huber60d3b222017-03-30 09:10:56 -07001113 if (mStyle == STYLE_STRUCT) {
1114 offset += fieldSize;
1115 } else {
1116 *size = std::max(*size, fieldSize);
1117 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001118
1119 if (fieldAlign > (*align)) {
1120 *align = fieldAlign;
1121 }
1122 }
1123
Andreas Huber60d3b222017-03-30 09:10:56 -07001124 if (mStyle == STYLE_STRUCT) {
1125 *size = offset;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001126 }
1127
Andreas Huber60d3b222017-03-30 09:10:56 -07001128 // Final padding to account for the structure's alignment.
1129 size_t pad = (*size) % (*align);
1130 if (pad > 0) {
1131 (*size) += (*align) - pad;
1132 }
Andreas Huberca4bc892017-01-09 14:58:12 -08001133
1134 if (*size == 0) {
1135 // An empty struct still occupies a byte of space in C++.
1136 *size = 1;
1137 }
Andreas Huber70a59e12016-08-16 12:57:01 -07001138}
1139
Andreas Huberc9410c72016-07-28 12:18:40 -07001140} // namespace android
1141