blob: 768c820c5adc80de311131d9d07981cc0d09052d [file] [log] [blame]
Andreas Huberc9410c72016-07-28 12:18:40 -07001#include "CompoundType.h"
2
3#include "Formatter.h"
4
Andreas Huber5a545442016-08-03 10:44:56 -07005#include <android-base/logging.h>
6
Andreas Huberc9410c72016-07-28 12:18:40 -07007namespace android {
8
Andreas Huber9ed827c2016-08-22 12:31:13 -07009CompoundType::CompoundType(Style style, const char *localName)
10 : Scope(localName),
11 mStyle(style),
Andreas Huberc9410c72016-07-28 12:18:40 -070012 mFields(NULL) {
13}
14
Andreas Huber0d0f9a22016-08-17 10:26:11 -070015bool CompoundType::setFields(
16 std::vector<CompoundField *> *fields, std::string *errorMsg) {
Andreas Huberc9410c72016-07-28 12:18:40 -070017 mFields = fields;
Andreas Huber5a545442016-08-03 10:44:56 -070018
19 for (const auto &field : *fields) {
20 const Type &type = field->type();
21
Andreas Huber295ad302016-08-16 11:35:00 -070022 if (type.isBinder()) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -070023 *errorMsg =
24 "Structs/Unions must not contain references to interfaces.";
Andreas Huberb95ea8a2016-08-15 15:35:42 -070025
26 return false;
27 }
28
Andreas Huber5a545442016-08-03 10:44:56 -070029 if (mStyle == STYLE_UNION) {
30 if (type.needsEmbeddedReadWrite()) {
31 // Can't have those in a union.
32
Andreas Huber0d0f9a22016-08-17 10:26:11 -070033 *errorMsg =
34 "Unions must not contain any types that need fixup.";
Andreas Huber5a545442016-08-03 10:44:56 -070035
36 return false;
37 }
Andreas Huber5a545442016-08-03 10:44:56 -070038 }
39 }
40
41 return true;
Andreas Huberc9410c72016-07-28 12:18:40 -070042}
43
Andreas Huber881227d2016-08-02 14:20:21 -070044std::string CompoundType::getCppType(
45 StorageMode mode, std::string *extra) const {
46 extra->clear();
Andreas Huber0e00de42016-08-03 09:56:02 -070047 const std::string base = fullName();
Andreas Huber881227d2016-08-02 14:20:21 -070048
49 switch (mode) {
50 case StorageMode_Stack:
51 return base;
52
53 case StorageMode_Argument:
54 return "const " + base + "&";
55
56 case StorageMode_Result:
57 return "const " + base + "*";
58 }
59}
60
61void CompoundType::emitReaderWriter(
62 Formatter &out,
63 const std::string &name,
64 const std::string &parcelObj,
65 bool parcelObjIsPointer,
66 bool isReader,
67 ErrorMode mode) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -070068 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -070069
70 out << "size_t " << parentName << ";\n\n";
71
72 const std::string parcelObjDeref =
73 parcelObj + (parcelObjIsPointer ? "->" : ".");
74
75 if (isReader) {
76 out << name
77 << " = (const "
Andreas Huber0e00de42016-08-03 09:56:02 -070078 << fullName()
Andreas Huber881227d2016-08-02 14:20:21 -070079 << " *)"
80 << parcelObjDeref
81 << "readBuffer("
82 << "&"
83 << parentName
84 << ");\n";
85
86 out << "if ("
87 << name
88 << " == nullptr) {\n";
89
90 out.indent();
91
Iliyan Malchev549e2592016-08-10 08:59:12 -070092 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
Andreas Huber881227d2016-08-02 14:20:21 -070093 handleError2(out, mode);
94
95 out.unindent();
96 out << "}\n\n";
97 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -070098 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -070099 << parcelObjDeref
100 << "writeBuffer(&"
101 << name
102 << ", sizeof("
103 << name
104 << "), &"
105 << parentName
106 << ");\n";
107
108 handleError(out, mode);
109 }
110
111 if (mStyle != STYLE_STRUCT || !needsEmbeddedReadWrite()) {
112 return;
113 }
114
115 emitReaderWriterEmbedded(
116 out,
117 name,
118 isReader /* nameIsPointer */,
119 parcelObj,
120 parcelObjIsPointer,
121 isReader,
122 mode,
123 parentName,
124 "0 /* parentOffset */");
125}
126
127void CompoundType::emitReaderWriterEmbedded(
128 Formatter &out,
129 const std::string &name,
130 bool nameIsPointer,
131 const std::string &parcelObj,
132 bool parcelObjIsPointer,
133 bool isReader,
134 ErrorMode mode,
135 const std::string &parentName,
136 const std::string &offsetText) const {
137 emitReaderWriterEmbeddedForTypeName(
138 out,
139 name,
140 nameIsPointer,
141 parcelObj,
142 parcelObjIsPointer,
143 isReader,
144 mode,
145 parentName,
146 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700147 fullName(),
Andreas Huber881227d2016-08-02 14:20:21 -0700148 "" /* childName */);
149}
150
151status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
152 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
153 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700154 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700155 << " {\n";
156
157 out.indent();
158
159 Scope::emitTypeDeclarations(out);
160
161 for (const auto &field : *mFields) {
162 std::string extra;
163 out << field->type().getCppType(&extra)
164 << " "
165 << field->name()
166 << extra
167 << ";\n";
168 }
169
170 if (needsEmbeddedReadWrite()) {
171 out << "\n::android::status_t readEmbeddedFromParcel(\n";
172
173 out.indent();
174 out.indent();
175
Andreas Huber8a82ff72016-08-04 10:29:39 -0700176 out << "const ::android::hardware::Parcel &parcel,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700177 << "size_t parentHandle,\n"
178 << "size_t parentOffset);\n\n";
179
180 out.unindent();
181 out.unindent();
182
183 out << "::android::status_t writeEmbeddedToParcel(\n";
184
185 out.indent();
186 out.indent();
187
Andreas Huber8a82ff72016-08-04 10:29:39 -0700188 out << "::android::hardware::Parcel *parcel,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700189 << "size_t parentHandle,\n"
190 << "size_t parentOffset) const;\n";
191
192 out.unindent();
193 out.unindent();
194 }
195
196 out.unindent();
197 out << "};\n\n";
198
199 return OK;
200}
201
202status_t CompoundType::emitTypeDefinitions(
203 Formatter &out, const std::string prefix) const {
Andreas Huber0e00de42016-08-03 09:56:02 -0700204 status_t err = Scope::emitTypeDefinitions(out, prefix + "::" + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700205
206 if (err != OK) {
207 return err;
208 }
209
210 if (!needsEmbeddedReadWrite()) {
211 return OK;
212 }
213
214 emitStructReaderWriter(out, prefix, true /* isReader */);
215 emitStructReaderWriter(out, prefix, false /* isReader */);
216
217 return OK;
218}
219
220void CompoundType::emitStructReaderWriter(
221 Formatter &out, const std::string &prefix, bool isReader) const {
222 out << "::android::status_t "
223 << (prefix.empty() ? "" : (prefix + "::"))
Andreas Huber0e00de42016-08-03 09:56:02 -0700224 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700225 << (isReader ? "::readEmbeddedFromParcel"
226 : "::writeEmbeddedToParcel")
227 << "(\n";
228
229 out.indent();
230 out.indent();
231
232 if (isReader) {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700233 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700234 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700235 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700236 }
237
238 out << "size_t parentHandle,\n"
239 << "size_t parentOffset)";
240
241 if (!isReader) {
242 out << " const";
243 }
244
245 out << " {\n";
246
247 out.unindent();
248 out.unindent();
249 out.indent();
250
Iliyan Malchev549e2592016-08-10 08:59:12 -0700251 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700252
253 for (const auto &field : *mFields) {
254 if (!field->type().needsEmbeddedReadWrite()) {
255 continue;
256 }
257
258 field->type().emitReaderWriterEmbedded(
259 out,
260 field->name(),
261 false /* nameIsPointer */,
262 "parcel",
263 !isReader /* parcelObjIsPointer */,
264 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700265 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700266 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700267 "parentOffset + offsetof("
268 + fullName()
269 + ", "
270 + field->name()
271 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700272 }
273
274 out.unindent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700275 out << "_hidl_error:\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700276 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700277 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700278
279 out.unindent();
280 out << "}\n\n";
281}
282
283bool CompoundType::needsEmbeddedReadWrite() const {
284 if (mStyle != STYLE_STRUCT) {
285 return false;
286 }
287
288 for (const auto &field : *mFields) {
289 if (field->type().needsEmbeddedReadWrite()) {
290 return true;
291 }
292 }
293
294 return false;
295}
296
297bool CompoundType::resultNeedsDeref() const {
298 return true;
299}
300
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700301status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
302 out << "name: \"" << localName() << "\"\n";
303 switch (mStyle) {
304 case STYLE_STRUCT:
305 {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700306 out << "type: TYPE_STRUCT\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700307 break;
308 }
309 case STYLE_UNION:
310 {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700311 out << "type: TYPE_UNION\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700312 break;
313 }
314 default:
315 break;
316 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700317
318 // Emit declaration for each subtype.
319 for (const auto &type : getSubTypes()) {
320 switch (mStyle) {
321 case STYLE_STRUCT:
322 {
323 out << "struct_value: {\n";
324 break;
325 }
326 case STYLE_UNION:
327 {
328 out << "union_value: {\n";
329 break;
330 }
331 default:
332 break;
333 }
334 out.indent();
335 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700336 if (status != OK) {
337 return status;
338 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700339 out.unindent();
340 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700341 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700342
343 // Emit declaration for each field.
344 for (const auto &field : *mFields) {
345 switch (mStyle) {
346 case STYLE_STRUCT:
347 {
348 out << "struct_value: {\n";
349 break;
350 }
351 case STYLE_UNION:
352 {
353 out << "union_value: {\n";
354 break;
355 }
356 default:
357 break;
358 }
359 out.indent();
360 out << "name: \"" << field->name() << "\"\n";
361 status_t status = field->type().emitVtsAttributeType(out);
362 if (status != OK) {
363 return status;
364 }
365 out.unindent();
366 out << "}\n";
367 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700368
369 return OK;
370}
371
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700372status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700373 switch (mStyle) {
374 case STYLE_STRUCT:
375 {
376 out << "type: TYPE_STRUCT\n";
377 break;
378 }
379 case STYLE_UNION:
380 {
381 out << "type: TYPE_UNION\n";
382 break;
383 }
384 default:
385 break;
386 }
387 out << "predefined_type: \"" << localName() << "\"\n";
388 return OK;
389}
390
Andreas Huber70a59e12016-08-16 12:57:01 -0700391bool CompoundType::isJavaCompatible() const {
392 return false;
393}
394
Andreas Huber31629bc2016-08-03 09:06:40 -0700395////////////////////////////////////////////////////////////////////////////////
396
397CompoundField::CompoundField(const char *name, Type *type)
398 : mName(name),
399 mType(type) {
400}
401
402std::string CompoundField::name() const {
403 return mName;
404}
405
406const Type &CompoundField::type() const {
407 return *mType;
408}
409
Andreas Huberc9410c72016-07-28 12:18:40 -0700410} // namespace android
411