1/*
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
17#include "Type.h"
18
19#include "Annotation.h"
20#include "ScalarType.h"
21
22#include <hidl-util/Formatter.h>
23#include <android-base/logging.h>
24
25namespace android {
26
27Type::Type()
28    : mAnnotations(nullptr) {
29}
30
31Type::~Type() {}
32
33void Type::setAnnotations(std::vector<Annotation *> *annotations) {
34    mAnnotations = annotations;
35}
36
37const std::vector<Annotation *> &Type::annotations() const {
38    return *mAnnotations;
39}
40
41bool Type::isScope() const {
42    return false;
43}
44
45bool Type::isInterface() const {
46    return false;
47}
48
49bool Type::isScalar() const {
50    return false;
51}
52
53bool Type::isString() const {
54    return false;
55}
56
57bool Type::isEnum() const {
58    return false;
59}
60
61bool Type::isBitField() const {
62    return false;
63}
64
65bool Type::isHandle() const {
66    return false;
67}
68
69bool Type::isTypeDef() const {
70    return false;
71}
72
73bool Type::isBinder() const {
74    return false;
75}
76
77bool Type::isNamedType() const {
78    return false;
79}
80
81bool Type::isMemory() const {
82    return false;
83}
84
85bool Type::isCompoundType() const {
86    return false;
87}
88
89bool Type::isArray() const {
90    return false;
91}
92
93bool Type::isVector() const {
94    return false;
95}
96
97bool Type::isTemplatedType() const {
98    return false;
99}
100
101bool Type::isPointer() const {
102    return false;
103}
104
105const ScalarType *Type::resolveToScalarType() const {
106    return NULL;
107}
108
109bool Type::isValidEnumStorageType() const {
110    const ScalarType *scalarType = resolveToScalarType();
111
112    if (scalarType == NULL) {
113        return false;
114    }
115
116    return scalarType->isValidEnumStorageType();
117}
118
119bool Type::isElidableType() const {
120    return false;
121}
122
123bool Type::canCheckEquality() const {
124    return false;
125}
126
127std::string Type::getCppType(StorageMode, bool) const {
128    CHECK(!"Should not be here");
129    return std::string();
130}
131
132std::string Type::decorateCppName(
133        const std::string &name, StorageMode mode, bool specifyNamespaces) const {
134    return getCppType(mode, specifyNamespaces) + " " + name;
135}
136
137std::string Type::getJavaType(bool /* forInitializer */) const {
138    CHECK(!"Should not be here");
139    return std::string();
140}
141
142std::string Type::getJavaWrapperType() const {
143    return getJavaType();
144}
145
146std::string Type::getJavaSuffix() const {
147    CHECK(!"Should not be here");
148    return std::string();
149}
150
151std::string Type::getVtsType() const {
152    CHECK(!"Should not be here");
153    return std::string();
154}
155
156std::string Type::getVtsValueName() const {
157    CHECK(!"Should not be here");
158    return std::string();
159}
160
161void Type::emitReaderWriter(
162        Formatter &,
163        const std::string &,
164        const std::string &,
165        bool,
166        bool,
167        ErrorMode) const {
168    CHECK(!"Should not be here");
169}
170
171void Type::emitResolveReferences(
172        Formatter &,
173        const std::string &,
174        bool,
175        const std::string &,
176        bool,
177        bool,
178        ErrorMode) const {
179    CHECK(!"Should not be here");
180}
181
182void Type::emitResolveReferencesEmbedded(
183        Formatter &,
184        size_t,
185        const std::string &,
186        const std::string &,
187        bool,
188        const std::string &,
189        bool,
190        bool,
191        ErrorMode,
192        const std::string &,
193        const std::string &) const {
194    CHECK(!"Should not be here");
195}
196
197void Type::emitDump(
198        Formatter &out,
199        const std::string &streamName,
200        const std::string &name) const {
201    emitDumpWithMethod(out, streamName, "::android::hardware::toString", name);
202}
203
204void Type::emitDumpWithMethod(
205        Formatter &out,
206        const std::string &streamName,
207        const std::string &methodName,
208        const std::string &name) const {
209    out << streamName
210        << " += "
211        << methodName
212        << "("
213        << name
214        << ");\n";
215}
216
217void Type::emitJavaDump(
218        Formatter &out,
219        const std::string &streamName,
220        const std::string &name) const {
221    out << streamName << ".append(" << name << ");\n";
222}
223
224bool Type::useParentInEmitResolveReferencesEmbedded() const {
225    return needsResolveReferences();
226}
227
228bool Type::useNameInEmitReaderWriterEmbedded(bool) const {
229    return needsEmbeddedReadWrite();
230}
231
232void Type::emitReaderWriterEmbedded(
233        Formatter &,
234        size_t,
235        const std::string &,
236        const std::string &,
237        bool,
238        const std::string &,
239        bool,
240        bool,
241        ErrorMode,
242        const std::string &,
243        const std::string &) const {
244    CHECK(!"Should not be here");
245}
246
247void Type::emitJavaReaderWriter(
248        Formatter &out,
249        const std::string &parcelObj,
250        const std::string &argName,
251        bool isReader) const {
252    emitJavaReaderWriterWithSuffix(
253            out,
254            parcelObj,
255            argName,
256            isReader,
257            getJavaSuffix(),
258            "" /* extra */);
259}
260
261void Type::emitJavaFieldInitializer(
262        Formatter &out,
263        const std::string &fieldName) const {
264    out << getJavaType()
265        << " "
266        << fieldName
267        << ";\n";
268}
269
270void Type::emitJavaFieldReaderWriter(
271        Formatter &,
272        size_t,
273        const std::string &,
274        const std::string &,
275        const std::string &,
276        const std::string &,
277        bool) const {
278    CHECK(!"Should not be here");
279}
280
281void Type::handleError(Formatter &out, ErrorMode mode) const {
282    switch (mode) {
283        case ErrorMode_Ignore:
284        {
285            out << "/* _hidl_err ignored! */\n\n";
286            break;
287        }
288
289        case ErrorMode_Goto:
290        {
291            out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
292            break;
293        }
294
295        case ErrorMode_Break:
296        {
297            out << "if (_hidl_err != ::android::OK) { break; }\n\n";
298            break;
299        }
300
301        case ErrorMode_Return:
302        {
303            out << "if (_hidl_err != ::android::OK) { return _hidl_err; }\n\n";
304            break;
305        }
306    }
307}
308
309void Type::emitReaderWriterEmbeddedForTypeName(
310        Formatter &out,
311        const std::string &name,
312        bool nameIsPointer,
313        const std::string &parcelObj,
314        bool parcelObjIsPointer,
315        bool isReader,
316        ErrorMode mode,
317        const std::string &parentName,
318        const std::string &offsetText,
319        const std::string &typeName,
320        const std::string &childName,
321        const std::string &funcNamespace) const {
322
323        const std::string parcelObjDeref =
324        parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
325
326    const std::string parcelObjPointer =
327        parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
328
329    const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
330    const std::string namePointer = nameIsPointer ? name : ("&" + name);
331
332    out << "_hidl_err = ";
333
334    if (!funcNamespace.empty()) {
335        out << funcNamespace << "::";
336    }
337
338    out << (isReader ? "readEmbeddedFromParcel(\n" : "writeEmbeddedToParcel(\n");
339
340    out.indent();
341    out.indent();
342
343    if (isReader) {
344        out << "const_cast<"
345            << typeName
346            << " &>("
347            << nameDerefed
348            << "),\n";
349    } else {
350        out << nameDerefed
351            << ",\n";
352    }
353
354    out << (isReader ? parcelObjDeref : parcelObjPointer)
355        << ",\n"
356        << parentName
357        << ",\n"
358        << offsetText;
359
360    if (!childName.empty()) {
361        out << ", &"
362            << childName;
363    }
364
365    out << ");\n\n";
366
367    out.unindent();
368    out.unindent();
369
370    handleError(out, mode);
371}
372
373status_t Type::emitTypeDeclarations(Formatter &) const {
374    return OK;
375}
376
377status_t Type::emitGlobalTypeDeclarations(Formatter &) const {
378    return OK;
379}
380
381status_t Type::emitGlobalHwDeclarations(Formatter &) const {
382    return OK;
383}
384
385status_t Type::emitTypeDefinitions(
386        Formatter &, const std::string) const {
387    return OK;
388}
389
390status_t Type::emitJavaTypeDeclarations(Formatter &, bool) const {
391    return OK;
392}
393
394bool Type::needsEmbeddedReadWrite() const {
395    return false;
396}
397
398bool Type::needsResolveReferences() const {
399    return false;
400}
401
402bool Type::resultNeedsDeref() const {
403    return false;
404}
405
406std::string Type::getCppStackType(bool specifyNamespaces) const {
407    return getCppType(StorageMode_Stack, specifyNamespaces);
408}
409
410std::string Type::getCppResultType(bool specifyNamespaces) const {
411    return getCppType(StorageMode_Result, specifyNamespaces);
412}
413
414std::string Type::getCppArgumentType(bool specifyNamespaces) const {
415    return getCppType(StorageMode_Argument, specifyNamespaces);
416}
417
418void Type::emitJavaReaderWriterWithSuffix(
419        Formatter &out,
420        const std::string &parcelObj,
421        const std::string &argName,
422        bool isReader,
423        const std::string &suffix,
424        const std::string &extra) const {
425    out << parcelObj
426        << "."
427        << (isReader ? "read" : "write")
428        << suffix
429        << "(";
430
431    if (isReader) {
432        out << extra;
433    } else {
434        out << (extra.empty() ? "" : (extra + ", "));
435        out << argName;
436    }
437
438    out << ");\n";
439}
440
441status_t Type::emitVtsTypeDeclarations(Formatter &) const {
442    return OK;
443}
444
445status_t Type::emitVtsAttributeType(Formatter &out) const {
446    return emitVtsTypeDeclarations(out);
447}
448
449bool Type::isJavaCompatible() const {
450    return true;
451}
452
453void Type::getAlignmentAndSize(
454        size_t * /* align */, size_t * /* size */) const {
455    CHECK(!"Should not be here.");
456}
457
458bool Type::containsPointer() const {
459    return false;
460}
461
462void Type::appendToExportedTypesVector(
463        std::vector<const Type *> * /* exportedTypes */) const {
464}
465
466status_t Type::emitExportedHeader(
467        Formatter & /* out */, bool /* forJava */) const {
468    return OK;
469}
470
471////////////////////////////////////////
472
473TemplatedType::TemplatedType() : mElementType(nullptr) {
474}
475
476void TemplatedType::setElementType(Type *elementType) {
477    CHECK(mElementType == nullptr); // can only be set once.
478    CHECK(isCompatibleElementType(elementType));
479    mElementType = elementType;
480}
481
482Type *TemplatedType::getElementType() const {
483    return mElementType;
484}
485
486bool TemplatedType::isTemplatedType() const {
487    return true;
488}
489
490status_t TemplatedType::emitVtsTypeDeclarations(Formatter &out) const {
491    out << "type: " << getVtsType() << "\n";
492    out << getVtsValueName() << ": {\n";
493    out.indent();
494    status_t err = mElementType->emitVtsTypeDeclarations(out);
495    if (err != OK) {
496        return err;
497    }
498    out.unindent();
499    out << "}\n";
500    return OK;
501}
502
503status_t TemplatedType::emitVtsAttributeType(Formatter &out) const {
504    out << "type: " << getVtsType() << "\n";
505    out << getVtsValueName() << ": {\n";
506    out.indent();
507    status_t status = mElementType->emitVtsAttributeType(out);
508    if (status != OK) {
509        return status;
510    }
511    out.unindent();
512    out << "}\n";
513    return OK;
514}
515}  // namespace android
516
517