Add operator== and != for some structs.

operator== and != are defined for type T where T is
one of the following:
* scalars
* strings
* enums
* U[] where U is in this list
* vec<U> where U is in this list
* structs that contain only types in this list.

If a struct contains a handle, an MQDescriptor,
or a union, for example, then == and != is not generated.

Bug: 32834072

Test: hidl_test
Change-Id: Icac73a14f81274ee6592e2b8fadf26d629151d9f
diff --git a/CompoundType.cpp b/CompoundType.cpp
index c984878..5f3dd5a 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -68,6 +68,19 @@
     return true;
 }
 
+bool CompoundType::canCheckEquality() const {
+    if (mStyle == STYLE_UNION) {
+        return false;
+    }
+    for (const auto &field : *mFields) {
+        if (!field->type().canCheckEquality()) {
+            return false;
+        }
+    }
+    return true;
+}
+
+
 std::string CompoundType::getCppType(
         StorageMode mode,
         bool specifyNamespaces) const {
@@ -355,6 +368,34 @@
 }
 
 
+status_t CompoundType::emitGlobalTypeDeclarations(Formatter &out) const {
+    Scope::emitGlobalTypeDeclarations(out);
+
+    if (!canCheckEquality()) {
+        return OK;
+    }
+
+    out << "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 << "inline bool operator!=("
+        << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
+    out.block([&] {
+        out << "return !(lhs == rhs);\n";
+    }).endl().endl();
+
+    return OK;
+}
+
 status_t CompoundType::emitGlobalHwDeclarations(Formatter &out) const  {
     if (needsEmbeddedReadWrite()) {
         out << "::android::status_t readEmbeddedFromParcel(\n";