Build toString + operator== in client libraries.
This is Phase I of a three phase plan to remove toString + operator==
from sources since the VNDK is currently not in place.
Phase I: functions in client and source libraries
Phase II: rebuild prebuilts with the functions in the clients
across all targets and vendors.
Phase III: remove functions from the source libraries
Test: hidl_test
Bug: 65200821
Change-Id: I4f2b10c088b1c1663a7a10d479e2607311dc462c
diff --git a/CompoundType.cpp b/CompoundType.cpp
index d70bc78..91bf0cf 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -459,19 +459,64 @@
status_t CompoundType::emitGlobalTypeDeclarations(Formatter &out) const {
Scope::emitGlobalTypeDeclarations(out);
+ // TODO(b/65200821): remove these ifdefs
+ out << "#ifdef REALLY_IS_HIDL_INTERNAL_LIB" << gCurrentCompileName << "\n";
out << "std::string toString("
<< getCppArgumentType()
<< ");\n\n";
-
if (canCheckEquality()) {
out << "bool operator==("
<< getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
out << "bool operator!=("
<< getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
+ }
+ out << "#else\n";
+ out << "static inline std::string toString("
+ << getCppArgumentType()
+ << (mFields->empty() ? "" : " o")
+ << ") ";
+
+ out.block([&] {
+ // include toString for scalar types
+ out << "using ::android::hardware::toString;\n"
+ << "std::string os;\n";
+ out << "os += \"{\";\n";
+
+ for (const NamedReference<Type>* field : *mFields) {
+ out << "os += \"";
+ if (field != *(mFields->begin())) {
+ out << ", ";
+ }
+ out << "." << field->name() << " = \";\n";
+ field->type().emitDump(out, "os", "o." + field->name());
+ }
+
+ out << "os += \"}\"; return os;\n";
+ }).endl().endl();
+
+ if (canCheckEquality()) {
+ out << "static inline bool operator==("
+ << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
+ << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
+ out.block([&] {
+ for (const auto &field : *mFields) {
+ out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
+ out << "return false;\n";
+ }).endl();
+ }
+ out << "return true;\n";
+ }).endl().endl();
+
+ out << "static inline bool operator!=("
+ << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
+ out.block([&] {
+ out << "return !(lhs == rhs);\n";
+ }).endl().endl();
} else {
out << "// operator== and operator!= are not generated for " << localName() << "\n\n";
}
+ out << "#endif // REALLY_IS_HIDL_INTERNAL_LIB\n";
return OK;
}
@@ -537,6 +582,8 @@
emitResolveReferenceDef(out, prefix, false /* isReader */);
}
+ // TODO(b/65200821): remove toString + operator== from .cpp once all prebuilts are rebuilt
+
out << "std::string toString("
<< getCppArgumentType()
<< (mFields->empty() ? "" : " o")
diff --git a/EnumType.cpp b/EnumType.cpp
index 02caf62..151ca26 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -359,25 +359,83 @@
emitBitFieldBitwiseAssignmentOperator(out, "|");
emitBitFieldBitwiseAssignmentOperator(out, "&");
- // toString for bitfields, equivalent to dumpBitfield in Java
+ // TODO(b/65200821): remove these ifndefs
+ out << "#ifdef REALLY_IS_HIDL_INTERNAL_LIB" << gCurrentCompileName << "\n";
+ // toString for bitfields, equivalent to dumpBitfield in Java
+ out << "template<typename>\n"
+ << "std::string toString("
+ << resolveToScalarType()->getCppArgumentType()
+ << " o);\n";
+ out << "template<>\n"
+ << "std::string toString<" << getCppStackType() << ">("
+ << resolveToScalarType()->getCppArgumentType()
+ << " o);\n\n";
+
+ // toString for enum itself
+ out << "std::string toString("
+ << getCppArgumentType()
+ << " o);\n\n";
+ out << "#else\n";
+ const ScalarType *scalarType = mStorageType->resolveToScalarType();
+ CHECK(scalarType != NULL);
+
out << "template<typename>\n"
- << "std::string toString("
- << resolveToScalarType()->getCppArgumentType()
+ << "static inline std::string toString(" << resolveToScalarType()->getCppArgumentType()
<< " o);\n";
out << "template<>\n"
- << "std::string toString<" << getCppStackType() << ">("
- << resolveToScalarType()->getCppArgumentType()
- << " o);\n\n";
+ << "inline std::string toString<" << getCppStackType() << ">("
+ << scalarType->getCppArgumentType() << " o) ";
+ out.block([&] {
+ // include toHexString for scalar types
+ out << "using ::android::hardware::details::toHexString;\n"
+ << "std::string os;\n"
+ << getBitfieldCppType(StorageMode_Stack) << " flipped = 0;\n"
+ << "bool first = true;\n";
+ for (EnumValue *value : values()) {
+ std::string valueName = fullName() + "::" + value->name();
+ out.sIf("(o & " + valueName + ")" +
+ " == static_cast<" + scalarType->getCppStackType() +
+ ">(" + valueName + ")", [&] {
+ out << "os += (first ? \"\" : \" | \");\n"
+ << "os += \"" << value->name() << "\";\n"
+ << "first = false;\n"
+ << "flipped |= " << valueName << ";\n";
+ }).endl();
+ }
+ // put remaining bits
+ out.sIf("o != flipped", [&] {
+ out << "os += (first ? \"\" : \" | \");\n";
+ scalarType->emitHexDump(out, "os", "o & (~flipped)");
+ });
+ out << "os += \" (\";\n";
+ scalarType->emitHexDump(out, "os", "o");
+ out << "os += \")\";\n";
- // toString for enum itself
- out << "std::string toString("
- << getCppArgumentType()
- << " o);\n\n";
+ out << "return os;\n";
+ }).endl().endl();
+
+ out << "static inline std::string toString(" << getCppArgumentType() << " o) ";
+
+ out.block([&] {
+ out << "using ::android::hardware::details::toHexString;\n";
+ for (EnumValue *value : values()) {
+ out.sIf("o == " + fullName() + "::" + value->name(), [&] {
+ out << "return \"" << value->name() << "\";\n";
+ }).endl();
+ }
+ out << "std::string os;\n";
+ scalarType->emitHexDump(out, "os",
+ "static_cast<" + scalarType->getCppStackType() + ">(o)");
+ out << "return os;\n";
+ }).endl().endl();
+ out << "#endif // REALLY_IS_HIDL_INTERNAL_LIB\n";
return OK;
}
status_t EnumType::emitTypeDefinitions(Formatter& out, const std::string& /* prefix */) const {
+ // TODO(b/65200821): remove toString from .cpp once all prebuilts are rebuilt
+
const ScalarType *scalarType = mStorageType->resolveToScalarType();
CHECK(scalarType != NULL);
diff --git a/Interface.cpp b/Interface.cpp
index e9e1c8f..3d9786f 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -822,9 +822,24 @@
if (status != OK) {
return status;
}
+
+ // TODO(b/65200821): remove these ifndefs
+ out << "#ifdef REALLY_IS_HIDL_INTERNAL_LIB" << gCurrentCompileName << "\n";
out << "std::string toString("
<< getCppArgumentType()
<< ");\n";
+ out << "#else\n";
+ out << "static inline std::string toString(" << getCppArgumentType() << " o) ";
+
+ out.block([&] {
+ out << "std::string os = \"[class or subclass of \";\n"
+ << "os += " << fullName() << "::descriptor;\n"
+ << "os += \"]\";\n"
+ << "os += o->isRemote() ? \"@remote\" : \"@local\";\n"
+ << "return os;\n";
+ }).endl().endl();
+ out << "#endif // REALLY_IS_HIDL_INTERNAL_LIB\n";
+
return OK;
}
@@ -835,6 +850,7 @@
return err;
}
+ // TODO(b/65200821): remove toString from .cpp once all prebuilts are rebuilt
out << "std::string toString("
<< getCppArgumentType()
<< " o) ";
diff --git a/Type.cpp b/Type.cpp
index c26d68c..930f9b9 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -28,6 +28,9 @@
namespace android {
+// TODO(b/65200821): remove
+std::string gCurrentCompileName;
+
Type::Type(Scope* parent) : mParent(parent) {}
Type::~Type() {}
diff --git a/Type.h b/Type.h
index cf6478a..d45e066 100644
--- a/Type.h
+++ b/Type.h
@@ -30,6 +30,10 @@
namespace android {
+// TODO(b/65200821): remove
+// HACK because no no type can depend or see AST
+extern std::string gCurrentCompileName;
+
struct ConstantExpression;
struct Formatter;
struct FQName;
diff --git a/generateCpp.cpp b/generateCpp.cpp
index 6822090..ba66b1b 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -893,6 +893,9 @@
<< mPackage.string() << "::" << baseName
<< "\"\n\n";
+ // TODO(b/65200821): remove define
+ out << "#define REALLY_IS_HIDL_INTERNAL_LIB" << gCurrentCompileName << "\n";
+
out << "#include <android/log.h>\n";
out << "#include <cutils/trace.h>\n";
out << "#include <hidl/HidlTransportSupport.h>\n\n";
diff --git a/main.cpp b/main.cpp
index 5dc93ce..c83c296 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1479,6 +1479,9 @@
for (int i = 0; i < argc; ++i) {
FQName fqName(argv[i]);
+ // TODO(b/65200821): remove
+ gCurrentCompileName = "_" + StringHelper::Uppercase(fqName.tokenName());
+
if (!fqName.isValid()) {
fprintf(stderr,
"ERROR: Invalid fully-qualified name.\n");