/*
* 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