/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "Type.h" #include "Annotation.h" #include "ScalarType.h" #include <hidl-util/Formatter.h> #include <android-base/logging.h> namespace android { Type::Type() : mAnnotations(nullptr) { } Type::~Type() {} void Type::setAnnotations(std::vector<Annotation *> *annotations) { mAnnotations = annotations; } const std::vector<Annotation *> &Type::annotations() const { return *mAnnotations; } bool Type::isScope() const { return false; } bool Type::isInterface() const { return false; } bool Type::isScalar() const { return false; } bool Type::isString() const { return false; } bool Type::isEnum() const { return false; } bool Type::isBitField() const { return false; } bool Type::isHandle() const { return false; } bool Type::isTypeDef() const { return false; } bool Type::isBinder() const { return false; } bool Type::isNamedType() const { return false; } bool Type::isMemory() const { return false; } bool Type::isCompoundType() const { return false; } bool Type::isArray() const { return false; } bool Type::isVector() const { return false; } bool Type::isTemplatedType() const { return false; } bool Type::isPointer() const { return false; } std::string Type::typeName() const { return ""; } const ScalarType *Type::resolveToScalarType() const { return NULL; } bool Type::isValidEnumStorageType() const { const ScalarType *scalarType = resolveToScalarType(); if (scalarType == NULL) { return false; } return scalarType->isValidEnumStorageType(); } bool Type::isElidableType() const { return false; } bool Type::canCheckEquality() const { return false; } std::string Type::getCppType(StorageMode, bool) const { CHECK(!"Should not be here"); return std::string(); } std::string Type::decorateCppName( const std::string &name, StorageMode mode, bool specifyNamespaces) const { return getCppType(mode, specifyNamespaces) + " " + name; } std::string Type::getJavaType(bool /* forInitializer */) const { CHECK(!"Should not be here"); return std::string(); } std::string Type::getJavaWrapperType() const { return getJavaType(); } std::string Type::getJavaSuffix() const { CHECK(!"Should not be here"); return std::string(); } std::string Type::getVtsType() const { CHECK(!"Should not be here"); return std::string(); } std::string Type::getVtsValueName() const { CHECK(!"Should not be here"); return std::string(); } void Type::emitReaderWriter( Formatter &, const std::string &, const std::string &, bool, bool, ErrorMode) const { CHECK(!"Should not be here"); } void Type::emitResolveReferences( Formatter &, const std::string &, bool, const std::string &, bool, bool, ErrorMode) const { CHECK(!"Should not be here"); } void Type::emitResolveReferencesEmbedded( Formatter &, size_t, const std::string &, const std::string &, bool, const std::string &, bool, bool, ErrorMode, const std::string &, const std::string &) const { CHECK(!"Should not be here"); } void Type::emitDump( Formatter &out, const std::string &streamName, const std::string &name) const { emitDumpWithMethod(out, streamName, "::android::hardware::toString", name); } void Type::emitDumpWithMethod( Formatter &out, const std::string &streamName, const std::string &methodName, const std::string &name) const { out << streamName << " += " << methodName << "(" << name << ");\n"; } void Type::emitJavaDump( Formatter &out, const std::string &streamName, const std::string &name) const { out << streamName << ".append(" << name << ");\n"; } bool Type::useParentInEmitResolveReferencesEmbedded() const { return needsResolveReferences(); } bool Type::useNameInEmitReaderWriterEmbedded(bool) const { return needsEmbeddedReadWrite(); } void Type::emitReaderWriterEmbedded( Formatter &, size_t, const std::string &, const std::string &, bool, const std::string &, bool, bool, ErrorMode, const std::string &, const std::string &) const { CHECK(!"Should not be here"); } void Type::emitJavaReaderWriter( Formatter &out, const std::string &parcelObj, const std::string &argName, bool isReader) const { emitJavaReaderWriterWithSuffix( out, parcelObj, argName, isReader, getJavaSuffix(), "" /* extra */); } void Type::emitJavaFieldInitializer( Formatter &out, const std::string &fieldName) const { out << getJavaType() << " " << fieldName << ";\n"; } void Type::emitJavaFieldReaderWriter( Formatter &, size_t, const std::string &, const std::string &, const std::string &, const std::string &, bool) const { CHECK(!"Should not be here"); } void Type::handleError(Formatter &out, ErrorMode mode) const { switch (mode) { case ErrorMode_Ignore: { out << "/* _hidl_err ignored! */\n\n"; break; } case ErrorMode_Goto: { out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n"; break; } case ErrorMode_Break: { out << "if (_hidl_err != ::android::OK) { break; }\n\n"; break; } case ErrorMode_Return: { out << "if (_hidl_err != ::android::OK) { return _hidl_err; }\n\n"; break; } } } void Type::emitReaderWriterEmbeddedForTypeName( Formatter &out, const std::string &name, bool nameIsPointer, const std::string &parcelObj, bool parcelObjIsPointer, bool isReader, ErrorMode mode, const std::string &parentName, const std::string &offsetText, const std::string &typeName, const std::string &childName, const std::string &funcNamespace) const { const std::string parcelObjDeref = parcelObjIsPointer ? ("*" + parcelObj) : parcelObj; const std::string parcelObjPointer = parcelObjIsPointer ? parcelObj : ("&" + parcelObj); const std::string nameDerefed = nameIsPointer ? ("*" + name) : name; const std::string namePointer = nameIsPointer ? name : ("&" + name); out << "_hidl_err = "; if (!funcNamespace.empty()) { out << funcNamespace << "::"; } out << (isReader ? "readEmbeddedFromParcel(\n" : "writeEmbeddedToParcel(\n"); out.indent(); out.indent(); if (isReader) { out << "const_cast<" << typeName << " &>(" << nameDerefed << "),\n"; } else { out << nameDerefed << ",\n"; } out << (isReader ? parcelObjDeref : parcelObjPointer) << ",\n" << parentName << ",\n" << offsetText; if (!childName.empty()) { out << ", &" << childName; } out << ");\n\n"; out.unindent(); out.unindent(); handleError(out, mode); } status_t Type::emitTypeDeclarations(Formatter &) const { return OK; } status_t Type::emitGlobalTypeDeclarations(Formatter &) const { return OK; } status_t Type::emitGlobalHwDeclarations(Formatter &) const { return OK; } status_t Type::emitTypeDefinitions( Formatter &, const std::string) const { return OK; } status_t Type::emitJavaTypeDeclarations(Formatter &, bool) const { return OK; } bool Type::needsEmbeddedReadWrite() const { return false; } bool Type::needsResolveReferences() const { return false; } bool Type::resultNeedsDeref() const { return false; } std::string Type::getCppStackType(bool specifyNamespaces) const { return getCppType(StorageMode_Stack, specifyNamespaces); } std::string Type::getCppResultType(bool specifyNamespaces) const { return getCppType(StorageMode_Result, specifyNamespaces); } std::string Type::getCppArgumentType(bool specifyNamespaces) const { return getCppType(StorageMode_Argument, specifyNamespaces); } void Type::emitJavaReaderWriterWithSuffix( Formatter &out, const std::string &parcelObj, const std::string &argName, bool isReader, const std::string &suffix, const std::string &extra) const { out << parcelObj << "." << (isReader ? "read" : "write") << suffix << "("; if (isReader) { out << extra; } else { out << (extra.empty() ? "" : (extra + ", ")); out << argName; } out << ");\n"; } status_t Type::emitVtsTypeDeclarations(Formatter &) const { return OK; } status_t Type::emitVtsAttributeType(Formatter &out) const { return emitVtsTypeDeclarations(out); } bool Type::isJavaCompatible() const { return true; } void Type::getAlignmentAndSize( size_t * /* align */, size_t * /* size */) const { CHECK(!"Should not be here."); } bool Type::containsPointer() const { return false; } void Type::appendToExportedTypesVector( std::vector<const Type *> * /* exportedTypes */) const { } status_t Type::emitExportedHeader( Formatter & /* out */, bool /* forJava */) const { return OK; } //////////////////////////////////////// TemplatedType::TemplatedType() : mElementType(nullptr) { } void TemplatedType::setElementType(Type *elementType) { CHECK(mElementType == nullptr); // can only be set once. CHECK(isCompatibleElementType(elementType)); mElementType = elementType; } Type *TemplatedType::getElementType() const { return mElementType; } bool TemplatedType::isTemplatedType() const { return true; } status_t TemplatedType::emitVtsTypeDeclarations(Formatter &out) const { out << "type: " << getVtsType() << "\n"; out << getVtsValueName() << ": {\n"; out.indent(); status_t err = mElementType->emitVtsTypeDeclarations(out); if (err != OK) { return err; } out.unindent(); out << "}\n"; return OK; } status_t TemplatedType::emitVtsAttributeType(Formatter &out) const { out << "type: " << getVtsType() << "\n"; out << getVtsValueName() << ": {\n"; out.indent(); status_t status = mElementType->emitVtsAttributeType(out); if (status != OK) { return status; } out.unindent(); out << "}\n"; return OK; } } // namespace android